npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, πŸ‘‹, I’m Ryan HefnerΒ  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you πŸ™

Β© 2024 – Pkg Stats / Ryan Hefner

@woofjs/view

v0.6.3

Published

Isolated component development for dogs. πŸ•

Downloads

1

Readme

@woofjs/view

Isolated component development environment for Woof projects. Basically a minimalistic Storybook for Woof.

How to Use

First, install this package in your Woof project as a dev dependency.

npm i --save-dev @woofjs/view

Installing this package makes the woof-view command available in package.json scripts.

{
  "scripts": {
    "view": "woof-view start ./path/to/client.js"
  }
}

Inside your project, you can create <Name>.view.jsx files for each of your components. Here is an example component:

// MyHeader.jsx

import { makeState } from "@woofjs/client";

/**
 * A really contrived header that makes an HTTP call to get the user's name.
 */
export function MyHeader($attrs, self) {
  const onclick = $attrs.get("onclick");

  const $greeting = $attrs.map("greeting");
  const $name = makeState("...");

  self.beforeConnect(() => {
    self
      .getService("@http")
      .get("/users/me")
      .then((res) => {
        $name.set(res.body.name);
      });
  });

  return (
    <h1 onclick={onclick}>
      {$greeting}, {$name}
    </h1>
  );
}

And here is a hypothetical view file to test it:

// MyHeader.view.jsx

import { MyHeader } from "./MyHeader.jsx";
import { makeMockHTTP } from "@woofjs/client/testing";

/**
 * Views are defined by an exported function. This function receives a `view` object with variables
 * and methods to configure the view. You can also export an object with view names as keys and
 * functions as values if you want to create multiple views for a single component.
 **/
export default (view) => {
  // Views are named by converting the function name from "PascalCaseLikeThis" to "Sentence Case Like This".
  // If you don't like this conversion, you can override it to any string you want:
  view.name = "Custom name here";

  // The description will be shown alongside the view. Use this space to explain what the purpose of the view is
  // and what unfamiliar users need to know. Supports Markdown formatting.
  view.description = `
    # Personalized Header

    This header displays a custom greeting and the user's name.
    You can select a few example greetings from a list in this view.
  `;

  // Provide mock versions of any services used by your component.
  view.service(
    "@http",
    /**
     * We are using makeMockHTTP from the testing tools to create an `@http` service
     * that returns mock data. This prevents the view from touching a real API.
     **/
    makeMockHTTP((self) => {
      self.get("/users/me", () => {
        // Log this event to the action log whenever the component makes a call to this mock API route.
        // This validates that the expected API calls are actually being made within the view.
        view.fireAction("requested user from API");

        return { id: 1, name: "Jimbo Jones" };
      });
    })
  );

  view.render(MyHeader, {
    // You can expose attributes to make them editable in the browser with a dedicated UI.
    greeting: view.attribute("Bonjour", {
      // The attribute key is used as the name by default (`greeting` in this case), but you can provide your own:
      name: "The Greeting",

      // Provide a description that will be displayed next to the input.
      description: "A phrase to greet the user with.",

      // The type of input the user sees is chosen based on the data type by default.
      // A string attribute would normally show a text input. Here we use a dropdown menu with preset options.
      input: {
        type: "select",
        options: ["Bonjour", "Howdy", "Konnichiwa"],
      },
    }),

    // Actions are no-op functions that log when they are called.
    // Useful as dummy functions to test that callbacks are working as you interact with components.
    onclick: view.action("header clicked"),
  });
};

Commands

start

Starts an HTTP server you can visit in your browser.

build

TODO: Implement

Bundles the project's views into a standalone static file dump that you can host on just about any web server.

Use the -o or --output option to specify where this folder will go. For example,

woof-view build -o ./view-static

Attribute Inputs

Attributes let the user interact with their values using a variety of input widgets. A default input type will be chosen based on the attribute's default value if you don't specify one. You can always override this with an input object in the attribute options.

Default Types

  • string: text
  • number: number
  • boolean: toggle
  • Date: date
  • $state, array or object: none

Text Input

Your basic text input. Takes a string.

view.attribute("value", {
  input: {
    type: "text",
  },
});

Number Input

Takes a number.

view.attribute(10, {
  input: {
    type: "number",
  },
});

Range Slider

Choose a numeric value within a range.

view.attribute(10, {
  input: {
    type: "range",
    min: 5,
    max: 50,

    // optional (defaults to 1)
    step: 5,
  },
});

Toggle

Toggle between true and false.

view.attribute(true, {
  input: {
    type: "toggle",
  },
});

Select (Dropdown Menu)

Choose one from a list of predefined options. Works best when there are many options.

view.attribute(10, {
  input: {
    type: "select",
    options: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
  },
});

Radio

Choose one from a list of predefined options using radio buttons. Works best when there are fewer options.

view.attribute("primary", {
  input: {
    type: "radio",
    options: ["primary", "secondary", "tertiary"],
  },
});

Date

TODO: Implement

Pick a date and time.

view.attribute(new Date(2022, 10, 10), {
  input: {
    type: "date",
  },
});

Color

Pick a color. The attribute value will be a CSS-compatible color string.

view.attribute("#ff0088", {
  input: {
    type: "color",
  },
});

None

Expose the attribute in the UI but don't provide any input for editing. Use this when you want to document an attribute but keep it read-only.

This is the default value for objects and arrays because structured data doesn't map well to simple input widgets. Consider using a select with predefined options for object/array attributes.

view.attribute("value", {
  input: {
    type: "none",
  },
});

πŸ¦†