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

upd8

v0.4.0

Published

An HTML-friendy javascript mini-framework

Downloads

318

Readme

⬆️ upd8

An HTML-friendly Typescript/Javascript mini-framework

What?

While developing archival, I was looking for a bare-minimum "view only" framework that would work well with pages that were statically generated, while still maintaining event-based reactive UI conventions. This is that library.

TL:DR;

  • Roughly 8k unzipped and <2k gzipped
  • Simple, understandable event-based API
  • No DSL, just DOM APIs
  • Designed to operate on static html

Simple usage

This library assumes that it is running on a pre-existing html page, and that most HTML elements that will need to exist on your site already exist at load. An example of an html snippet that could become an upd8 view would be:

<section id="main" class="main">
  <input id="toggle-all" class="toggle-all" type="checkbox" />
  <label for="toggle-all">Mark all as complete</label>
  <ul id="todo-list" class="todo-list">
    <li data-template="todo" class="todo">
      <div class="view">
        <input class="toggle" type="checkbox" />
        <label></label>
        <button class="destroy"></button>
      </div>
      <input class="edit" value="" />
    </li>
  </ul>
</section>

Note the data-template and the use of ids to identify elements.

A corresponding Upd8View would look like this:

export class TODOView extends Upd8View {
  static get id() {
    return "main";
  }

  get id() {
    return TODOView.id;
  }

  clearInput() {
    this.el("new-todo").value = "";
  }

  mount() {
    return [
      this.eventListener(
        "todo-list",
        "change",
        (_, el) => {
          this.dispatchEvent({
            name: "toggleTodo",
            value: el.closest(".todo").dataset.id,
          });
        },
        ".toggle"
      ),
      this.eventListener("toggle-all", "change", (_, el) => {
        this.dispatchEvent({ name: "toggleAll" });
      }),
    ];
  }

  updated() {
    let completedCount = 0;
    this.setContent(
      "todo-list",
      this.state.todos.map((todo) => {
        const todoEl = this.template("todo");
        todoEl.classList.toggle("completed", todo.completed);
        this.findElement(todoEl, ".toggle").checked = !!todo.completed;
        todoEl.classList.toggle("editing", this.state.editing === todo.id);
        this.setContent(todoEl, todo.title, "label");
        this.setData(todoEl, { id: todo.id });
        const editField = this.findElement(todoEl, ".edit");
        editField.value = todo.title;
        return todoEl;
      })
    );
  }
}

Upd8View has a few main APIs that upd8 uses to manage rendering state:

  • show/hide/showing manage view visibility, which allows you to render multiple views and let upd8 handle showing them based on global state.

  • eventListener allows you to add interactivity and generally just results in dispatchEvent calls

  • el, findElement and template help with you locating or creating HTML elements, and setContent/setData/setAttrs help you to modify them. These methods are used inside update to make your UI reactively represent this.state concisely.

There are a few more APIs for complex or imperative use cases, which you can explore in the documentation.

To wire this view up to a document, you'd create an upd8 function by setting up views and initializing your app:

import { cre8 } from "upd8";
import { TODOView } from "./todo-view";

const initUI = cre8([TODOView]);

const state = {};

const handleEvent = (name, value) => {
  // TODO: modify state
};

window.addEventListener("load", () => {
  const upd8 = initUI(state, (event) => {
    ViewModel.handleEvent(event.name, event.value);
    upd8(state);
  });
});

The general assumption of upd8 apps is that state changes happen outside of your app, and that your app can be represented by a large global state object. For instance, the archival editor uses a (WASM compiled) rust library to manage state and API calls, and the UI is rendered by upd8.

More

upd8 is designed to work extra well with archival, but works anywhere that you're generating static HTML. To explore the full API and view examples, check out the documentation.

Contributing

This package is intended to be very small, but all ideas and contributions are welcome. Feel free to create discussions on this repository or email me at [email protected] with any ideas or observations, or file a pull request.

License

This library is licensed under The Unlicense, and is created and maintained in service of anarchistic goals. I'd prefer you didn't use it to make money for monopolists or governments, but this license is permissive to all uses.