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 🙏

© 2025 – Pkg Stats / Ryan Hefner

logical-elements

v0.2.4

Published

A set of tools for creating logical HTML.

Readme

Logical Elements

A set of tools for creating logical HTML.

A Logical Approach

Most JavaScript frameworks are trying to work around HTMLs lack of logic-based functionality, and focus on helping you merge features of JavaScript with HTML. They typically do this by bringing the HTML into the JavaScript domain and controlling the DOM. Sometimes through a virtual DOM and sometimes through a compiler that provides a JS-like experience which handles doing the tedious task of connecting JS and HTML. Each of these tools, React, Vue, Angular, Svelte, etc. requires that the code you write be transformed before a browser can read it.

Logical Elements solves the problem in the other direction. Instead of bring HTML into JavaScript, in brings JavaScript into HTML to provide framework-level reactivity and functionality without a build step. It allows you to write native HTML that can talk directly to nearby custom elements that provide JavaScript logic, reference deeply nested values, update when values change, and iterate over arrays and objects. In short, it provides elements that have logical functionality.

This is achieved through the use of a few combined browser tools such as:

  • Custom Elements
  • Mutation Observers
  • Object Proxies
  • Treewalkers
  • Custom Events
  • And more!

The elements provided serve as both an authoring tool and as useful ways of providing basic logic in your HtML such as if and else statements and each loops.

Core Approach

The primary idea is that HTML elements can have and read from a scoped, local state. Kind of like a React context provder, but without the need for hooks like useContext(). Users can define the state however they need, and return it to the custom HTML element. Then, any ancestor of that element can read the stored values using custom namespaced attributes. Also, since Logical Elements provides authoring tools, that means that users can define their own stateful elements and namespaced attributes.

The HTMLParsedElement Class

The first tool is an enhanced HTMLElement class to use when authoring your own custom elements. It features the following enhancements:

  • Parsed Callback - Fires when the element has been fully parsed with all of its children. This solves an issue with the Custom Element connectedCallback which triggers on the opening tag of an element and doesn't know anything about its children.
  • Updated Callback - Fires when a parsed, attributeChanged, childrenModified, or providerUpdated callback is also fired. Will batch any of those events together if they occur at the same time.
  • Children Modified Callback - Fires when the tree structure of the children changes.
  • Provider Updated Callback - Fires when any parent state provider updates their state.
  • Provider Subscriptions - Automatically subscribes to parent state providers and makes them available to the element.
  • Update Scheduler - Helps batch updates together to minimize the number of times an element runs its update logic
  • Each Child Walker - A treewalker that steps through each child of an element and fires a callback function on them.
  • Lookup State Values - Lookup values from a parent state provider.

The LogicalElement Class

It extends the LogicalElement class and adds a reactive state to it to become a state provider.

  • Reactive Attribute Namespaces - The ability to define reactive attributes and how to handle them. A reactive attribute will have a handler called on it on every update.
  • Reactive State - Uses JavaScript object proxies to capture update events and notify subscribers. Will trigger the stateUpdated, providerUpdated, and updated callbacks.
  • State Updated Callback - Fires when the state of this ContextElement instance updates.

Reactive Attribute Namespaces

One of the main primary functionalities is the ability to declare attribute namespaces that will be evaluated if there is a provider update anywhere above them. Take for example the attr namespace. You can use this to assign any value to another attribute on the same element like this:

<le-context name="exampleContext">
    <script>
        function exampleContext (state) {
            return {
                isDisabled: true,
            }
        }
    </script>

    <button attr:disabled="{exampleContext.isDisabled}">This button is disabled</button>
</le-context>

The namespace gets broken down in this way:

NAMESPACE:COMMAND="{PROVIDER_NAME.PROPERTY_NAME}"

So, using that information attr namespace will look up the value on the context and assign it to the indicated attribute, in this case the disabled attribute.

There are four provided reactive namespaces that are assigned by default to the ContextElement class:

  • attr - Assign values to attributes on the same element, will overwrite any current attribute values
  • cls - Assign class names conditionally
  • on - Add event listeners to the element for the specified event
  • set - Assign values to specific properties such as textContent

Any author of a LogicalElement can add their own reactive namespaces to be processed during the updatedCallback lifecycle.