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-computed

v0.0.3

Published

Hydrate and compute values reactively from other (server side rendered/generated) HTML signals via local script tags.

Downloads

8

Readme

be-computed [WIP]

Playwright Tests NPM version How big is this package in your project?

Hydrate and compute values reactively from other (server side rendered/generated) HTML signals via local script tags.

be-computed is very close in purpose to be-overloading. be-overloading focuses more on user-initiated event driven reactions. be-computed is more focused on observing peer elements (and/or the host) and calculating values based on these dependencies reactively.

Obscure note (ignore if it not understanding the context): This behavior probably doesn't make sense to be used where it makes sense to use the trans-render web component. For that reason, not separating the be-hive registration from the be-computed class.

Special Symbols

In the examples below, we will encounter special symbols used in order to keep the statements small, as far as identifying which elements to pull in property values from, and observing those elements for property value changes:

| Symbol | Meaning | Notes | |-------------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| | /propName |"Hostish" | Attaches listeners to getters/setters on properties of "hostish". | | @propName |Name attribute | Listens for input events on form elements based on matching the name attribute. | | |propName |Itemprop attribute | Matches element based on matching itemprop attribute. If contenteditible, listens for input events. Otherwise, uses be-value-added. | | #propName |Id attribute | Matches element based on id within ShadowDOM realm. Listens for input events. | | -prop-name |Marker indicates prop | Matches elements based on finding the exact attribute starting with a dash. Attaches listeners to getters/setters. |

"Hostish" means:

  1. First, do a "closest" for an element with attribute itemscope, where the tag name has a dash in it. Do that search recursively.
  2. If no match found, use getRootNode().host.

Example 1a -- Locality of behavior notation with inline expression

<div itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <link itemprop=isWealthy href=https://schema.org/False>

    ...
    
    <link itemprop=isInNirvana 
        onload="isHappy && !isWealthy"
        be-computed='from onload expression, passing in |isHappy, |isWealthy.' 
    >
</div>

What this does:

  1. Since the onload attribute expression doesn't start with export const ..., and doesn't start with an open parenthesis, be-computed wraps the expression like so:
export const expr = async ({isHappy, isWealthy}) => {
    return isHappy && !isWealthy;
}
  1. Since the return statement returns a primitive, it applies the value to the adorned element, based on context. In this case, it sets:
<link itemprop=isInNirvana href=https://schema.org/True>

if the conditions are met, and attaches the be-value-added enhancement.

The value of the computation can be obtained via oLink.beEnhanced.beValueAdded.value.

Example 1b -- Verbose notation with external script tag

<div itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <link itemprop=isWealthy href=https://schema.org/False>

    ...

    <script nomodule>
        isHappy && !isWealthy
    </script>
    <link itemprop=isInNirvana be-computed='from previous script element expression, passing in |isHappy, |isWealthy.'>
</div>

Advantages of using script element -- less issues with characters that cause problems inside an attribute, may get better IDE support. Disadvantages -- a little further away, a little more verbose, if you need to move the element, need to remember to move the associated script element along with it.

Example 1c -- compact notation with inline expression

<div itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <link itemprop=isWealthy href=https://schema.org/False>

    ...
    
    <link itemprop=isInNirvana 
        onload="isHappy && !isWealthy" 
        be-computed='from |isHappy, |isWealthy.' 
    >
</div>

Example 1d -- compact notation with external script tag

<div itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <link itemprop=isWealthy href=https://schema.org/False>

    ...

    <script nomodule>
        isHappy && !isWealthy
    </script>
    <link itemprop=isInNirvana be-computed='from |isHappy, |isWealthy.'>
</div>

Example 1e -- bind to named elements and id'd elements

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...
    <link itemprop=isInNirvana
      onload="isHappy && !isWealthy && liberated?.length > 17"
      be-computed='from |isHappy, @isWealthy, #liberated.'
    >
</form>

Example 1f -- Add more context to the scripting

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...

    <link itemprop=isInNirvana 
        onload="
            ({isHappy, isWealthy, liberated}) => {
                console.log({isHappy, isWealthy, liberated});
                return isHappy && !isWealthy && liberated?.length > 17;
            }
        "
        be-computed='from |isHappy, @isWealthy, #liberated.'
    >
</form>

Since the expression starts with open parenthesis, wrapping is more lightweight. Just adds export const default.

Example 1g

Specify export symbol

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...

    <link itemprop=isInNirvana 
        onload="
            export const calculateInNirvana = ({isHappy, isWealthy, liberated}) => {
                console.log({isHappy, isWealthy, liberated});
                return isHappy && !isWealthy && liberated?.length > 17;
            }
        "
        be-computed='from onload export of calculateInNirvana, passing in |isHappy, @isWealthy, #liberated.'
    >
</form>

This allows for multiple expressions that can be used by different enhancements.

Example 1h -- Values coming from host.

<my-custom-element>
    #shadow
        <script nomodule>
            myProp ** 2
        </script>
        <data itemprop=squared be-computed='from /numValue.'></data>
        <be-hive></be-hive>
</my-custom-element>

The slash is optional, so this will also work:

Example 1i -- Values coming from host, take II.

<my-custom-element>
    #shadow
        <script nomodule>
            myProp ** 2
        </script>
        <data itemprop=squared be-computed='from myProp.'>
        <be-hive></be-hive>
</my-custom-element>

Example 1j

Value coming from marker

<form itemscope>
    <my-custom-element -num-value></my-custom-element>
    

    <meta itemprop=square
        onload="numValue ** 2"
        be-computed='from -num-value.'>
</form>

Example 2a Assigning objects, verbose notation, external script

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...

    <script nomodule>
        ({
            prop1: isHappy && !isWealthy && liberated?.length > 17,
            prop2: liberated?.blink()
        })
    </script>
    <any-element itemprop=isInNirvana be-computed='from previous script element expression, passing in |isHappy, @isWealthy, #liberated, and assign result.'></any-element>
</form>

Detecting such expressions: Starts and ends with ({...}), no arrow. If need to use arrow functions inside, need to provide the context.

Example 2b Assigning objects, compact notation, external script

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...

    <script nomodule>
        {
            prop1: isHappy && !isWealthy && liberated?.length > 17,
            prop2: liberated?.blink()
        }
    </script>
    <any-element itemprop=isInNirvana be-computed='from |isHappy, @isWealthy, #liberated, and assign result.'></any-element>
</form>

Example 2c Assigning objects, verbose notation, inline attribute

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...

    <any-element itemprop=isInNirvana
        onload="({
            prop1: isHappy && !isWealthy && liberated?.length > 17,
            prop2: liberated?.blink()
        })" 
        be-computed='from onload expression, passing in |isHappy, @isWealthy, #liberated, and assign result.'></any-element>
</form>

Example 2d Assigning objects, compact notation, inline attribute

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...
    <any-element itemprop=isInNirvana
        onload="
        {
            prop1: isHappy && !isWealthy && liberated?.length > 17,
            prop2: liberated?.blink()
        }
        " 
        be-computed='from |isHappy, @isWealthy, #liberated, and assign result.'>
    </any-element>
</form>

Example 2e Assigning object to sub property [TODO]

Example 2f Assigning object to be-scoped enhancement

This would allow transforms to be based on.

We can assign the result of a computation to an enhancement, or the "stateProp" property of an enhancement (as defined in the static config property of the enhancement). So one prominent use case is assigning to local "scope" of an element:

<form itemscope>
    <link itemprop=isHappy href=https://schema.org/True>
    <input type=checkbox name=isWealthy>
    <div contenteditable id=liberated>abc</div>
    ...
    <div itemscope
        onload="
        {
            prop1: isHappy && !isWealthy && liberated?.length > 17,
            prop2: liberated?.blink()
        }
        " 
        be-computed='from |isHappy, @isWealthy, #liberated, and assign result to $0+beScoped.'>
    </div>
</form>

Viewing Your Element Locally

Any web server that can serve static files will do, but...

  1. Install git.
  2. Fork/clone this repo.
  3. Install node.js.
  4. Open command window to folder where you cloned this repo.
  5. npm install

  6. npm run serve

  7. Open http://localhost:3030/demo/ in a modern browser.

Running Tests

> npm run test

Using from ESM Module:

import 'be-computed/be-computed.js';

Using from CDN:

<script type=module crossorigin=anonymous>
    import 'https://esm.run/be-computed';
</script>