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

be-enhanced

v0.0.147

Published

be-enhanced provides a base class that enables casting spells, or enhancing server-rendered DOM elements based on cross-cutting custom attributes

Downloads

713

Readme

be-enhanced [WIP]

How big is this package in your project? NPM version

be-enhanced provides a base class that attaches a custom class instance onto a third party (built-in or custom) element. It supplements be-hive. The pair of packages enables "casting spells", or enhancing server-rendered DOM elements, based on cross-cutting custom attributes. These base classes can also be used during template instantiation for a more optimal repeated web component scenario, via "non verbal spells".

be-enhanced, which focuses on adding custom properties to an element, and be-hive, which focuses on attaching and forwarding attributes values to the custom property based on a list of one or more attributes to observe, together form a simplified userland implementation of this proposal. Based on the really nice idea of supporting multiple attributes, this component in particular, be-enhanced is oblivious to any attributes, leaving the magic of tying the knot between attributes and associated enhancements to be-hive exclusively.

be-enhanced, together with be-hive, provide a much more "conservative" alternative approach to enhancing existing DOM elements, in place of the controversial "is"-based customized built-in element standard-ish. There are, however, a small number of use cases where the is-based built-in approach may be the preferred one.

In contrast to the "is" approach, we can apply multiple behaviors / decorators / enhancements to the same element:

#shadow-root (open)
<black-eyed-peas 
    be-on-the-next-level=11
    be-rocking-over-that-bass-tremble
    be-chilling-with-my-motherfuckin-crew
></black-eyed-peas>

which seems more readable than:

<is-on-the-next-level level=11>
    <is-rocking-over-that-base-tremble>
        <is-chilling-with-my-motherfunckin-crew>
            <black-eyed-peas></black-eyed-peas>
        </is-chilling-with-my-motherfuckin-crew>
    </is-rocking-over-that-base-tremble>
</is-on-the-next-level>

Not to mention concerns about performance. And then there's this.

Priors

be-enhanced's goals are quite similar to what is achieved via things that go by many names.

We prefer (progressive) "enhancement" as the term, but "decorator", "[cross-cutting] custom attribute", "directive", "behavior" are also acceptable terms.

Differences to these solutions (perhaps):

  1. This can be used independently of any framework (web component based).
  2. Each decorator can be imported independently of others via an ES6 module.
  3. Definition is class-based, but with functional reactive ways of organizing the code ("FROOP")
  4. Applies exclusively within Shadow DOM realms.
  5. Reactive properties are managed declaratively via JSON syntax.
  6. Namespace collisions easily avoidable within each shadow DOM realm.
  7. Use of namespaced properties allows multiple vendors to apply different enhancements simultaneously.
  8. be-enhanced provides "isomorphic" support for using the same declarative syntax while transforming templates during template instantiation, as well as while the DOM is sitting in the live DOM tree. But the critical feature is that if the library is not yet loaded during template instantiation, nuk ka problem, the live DOM decorator can apply the logic progressively when the library is loaded. Meaning we can punt during template instantiation, so that render blocking is avoided. And if the library is loaded prior to template instantiation, it can still be supplemented by the live DOM decorator, but the initial work performed during the template instantiation can be skipped by the live DOM decorator.

Prior to that, there was the heretical htc behaviors.

Examples of constructing a be-enhanced progressive enhancement decorator:

| Enhancement | Purpose | Code | |---------------------|--------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| | be-adoptive | Adopt styles from parent shadow realm | code | | be-a-beacon | Announce arrival of (last) element in HTML Stream | code | | be-based | Adjust URLs from a base URL | code | | be-bound | Provide two-way binding | code | | be-buttoned-up | Make a button link to button menu in popover | code | | be-channeling | Channel events to the host element. | code | | be-clonable | Make DOM element be clonable | code | | be-committed | Trigger a button click on keyboard "enter" | code | | be-computed | Compute values from other HTML signals via local script tags. | code | | be-counted | Track and share how many times button has been clicked. | code | | be-definitive | Define web component from existing DOM in tree. | code | | be-delible | Make DOM element be deletable | code | | be-derived | Derive state from server-rendered HTML | code | | be-detail-oriented | Make the fieldset expandable. | code | | be-dispatching | Dispatch event with specified name. | code | | be-elevating | Elevate local property value to upstream element. | code | | be-entrusting | Derive initial value from server streamed semantic HTML. | code | | be-exportable | Allow script tag to export itself as a module | code | | be-fetching | Fetch resource based on url property | code | | be-formidable | Enhance the form's validation abilities. | code | | be-functional | Connect script to DOM elements. | code | | be-importing | Import Static, Declarative HTML Web Components with Streaming HTML | code | | be-inclusive | Include content from nearby templates | code | | be-intl | Format numbers using intl.NumberFormat. | code | | be-invoking | Invoke method on upstream peer element or the host. | code | | be-it | Forward props to adjacent element. | code | | be-lazy | Load template when it scrolls into view | code | | be-linked | Connect HTML (web) components together with readabe syntax | code | | be-literate | Enhance the input element so it can read local files | code | | be-memed | Cache templates contained within templates | code | | be-observant | One-way-bind from the host or a peer element. | code | | be-promising | Run enhancements in a predictable order | code | | be-prop-slotting | Transfer values from light children to host. | code | | be-propagating | Publish property changes to adorned element. | code | | be-repeated | Repeat section of HTML | code | | be-scoped | Create an EventTarget associated with the adorned element that can hold scoped state. | code | | be-searching | Make a DOM element searchable | code | | be-sharing | Share values from the adorned element to peer elements. | code | | be-switched | Lazy loads content when conditions are met. | code | | be-typed | Allow the user to customize input element during run time. | code | | be-value-added | Add a value property used for formatting. | code | | be-valued | Reflect value of input to the value attribute on input event. | code | | be-written | Stream a url to a target DOM element. | code |

The be-enhancement api

be-enhancement commits the cardinal sin of attaching a custom property gateway, "beEnhanced" on all Elements. Being that the platform has shown little to no interest in providing support for progressive enhancement over many decades when such solutions have proven useful, we should feel no guilt whatsoever.

Having this property gateway is a life-saver as far as performance and providing an easy way of integrating enhancements into (some) frameworks.

To set a value on a namespaced property (e.g. via a framework), do the following:

await customElements.whenDefined('be-enhanced');
const base = myElement.beEnhanced.by.aButterBeerCounter;
Object.assign(base, {count: 7});

This should work just fine even if the enhancement a-butter-beer-counter hasn't loaded yet. The enhancement will absorb the settings the moment it becomes attached to the element it is enhancing.

Server-rendered HTML vs Template Instantiated HTML

If the HTML we are working with is rendered by the server, the most effective way of activating the custom enhancement is via the associated attribute:

<button be-counted>Count me</button>

However, activating enhancements via attributes is not ideal when using client side api's to build the API, such as during template instantiation.

As we stated so very long ago, the way to do this most effectively programmatically is:

import('be-counted/be-counted.js');
await customElements.whenDefined('be-enhanced');
const base = myElement.beEnhanced.by.beCounted;
Object.assign(base, {value: 7});

In the example above, we are importing the dependency asynchronously using the dynamic import. This means that depending on the timing the hydration of the enhancement may be done during template instantiation (for example), or after the element being enhanced has been added to the live DOM tree.

Using dynamic import as shown above has the benefit that the dependency will not cause the template instantiation to be render blocked.

Event Notifications

Be-enhancement element decorators/behaviors typically don't, by default, emit events that get bubbled up the DOM tree.

To subscribe to an event:

const myEnhancement = await myElement.beEnhanced.whenResolved(emc);
myEnhancement.addEventListener('resolved', e => {

})