npm package: @html_first/simple_signal
Description: simple asynchronous signal
Author: hakim_jazuli
Latest version: 3.0.0
Deprecated: use npm i virst instead

﻿## about @html_first/simple_signal

all of our classes designed to works in asynchronous context using Queues, so you can use it for api
calls reactively without too much of mental overheads; we use attributeName to target elements on
the DOM so it can be used as declaratively as possible despite minified; non-gzipped version of this
library is less then 5kB;

## classes api

-   `Lifecycle`:

    > -   usefull for:
    >     > -   adding event listeners;
    >     > -   track lifecycle of created element;
    > -   params:
    >     > -   `attrLifecycleCallback`:
    >     >     `{ [attributeName:string]: (element:HTMLElement|Element, observer:MutationObserver)=>(Promise<()=>Promise<void>>) }`
    >     >     > -   fires when element is created/exist in the initial document;
    >     >     > -   returns callback which then fires when element no longer o documentScope
    >     >     > -   param `element` is the curent element which is created/exist in the initial
    >     >     >     document;
    >     > -   `documentScope?`: `HTMLElement|Element|ShadowRoot|Document`
    > -   example:
    >     > -   `const clickEvent=()=>{ console.log("i've been clicked") }`
    >     > -   `new Lifecycle('elem-event', async (element) => { element.addEventListener('click', clickEvent); return async () => { element.removeEventListener('click', clickEvent); }; });`
    >     > -   `<buttton elem-event="unique string optional">click me</button>`
    >     >     > -   you can minimise the number of `MutationObserver` instances on a
    >     >     >     `documentScope`, by keeping attributeName selector to minimum, then handle
    >     >     >     inside the `lifecycleCallback` using `element.getAttribute(attributeName)` to
    >     >     >     conditionally handle element's lifecycle, this is usefull if you are trying to
    >     >     >     create a library, or just having a pattern to render specific attributeName
    >     >     >     inside your html;
    > -   returns:
    >     > -   `unObserve:()=>void`: will un-observe the `MutationObserver` for the
    >     >     `documentScope`, except `documentScope == undefined || documentScope == document`
    > -   note:
    >     > -   observer options are set to `{childList: true, subtree: true}`, for performance
    >     >     purposes, therefore on creating new `Element` OR adding it as `inner/outerHTML` must
    >     >     contains the `attributeName` to be observed;

-   `Let`:

    > -   params:
    >     > -   `value`: `VType`
    >     > -   `attributeName?`: `string`
    >     >     > -   allow to reflect the value to dom, by targeting the value of
    >     >     >     `...(attributeName|propertyName);`;
    >     > -   `documentScope?`: `HTMLElement|Element|ShadowRoot|Document`
    >     >     > -   scope of the dom reflector;
    > -   returns:
    >     > -   `get value(): VType`
    >     > -   `set value(newValue:VType): void`
    >     > -   `call$:()=>void`: manually trigger all registered effects;
    >     > -   `remove$:(effect:$)=>void`: remove registed effect to this Instance;
    >     > -   `removeAll$:()=>void`: remove all registered effects to this Instance, including
    >     >     that is auto recorded using signal to this instance;
    > -   example1:
    >     > -   `const a = new Let('a');`
    > -   example2:
    >     > -   `const a = new Let('example', 'param-b');`
    >     > -   `<div param-b="innerText;data-a"></div>` will reflect to DOM
    >     >     `<div param-b="innerText;data-a" data-a="example">example</div>`
    > -   note:
    >     > -   adding `value` to the html attribute like = `attributeName="...;value;..."`, will
    >     >     bind the js variable value to the element value, only works on element that have
    >     >     valid `oninput` attribute

-   `Derived`:

    > -   params
    >     > -   `asyncCallback`: `()=>Promise<VType>`
    >     > -   `attributeName?`: `string`
    >     >     > -   allow to reflect the value to dom, by targeting the value of
    >     >     >     `...(attributeName|propertyName);`;
    >     > -   `documentScope?`: `HTMLElement|Element|ShadowRoot|Document`
    >     >     > -   scope of the dom reflector;
    > -   returns:
    >     > -   `get value(): VType`
    >     > -   `remove$:(effect:$)=>void`: remove registed effect to this Instance;
    >     > -   `removeAll$:()=>void`: remove all registered effects to this Instance;
    > -   example1:
    >     > -   "const b = new Derived(async()=>\`derived from ${a.value}\`);"
    > -   example2:
    >     > -   "const b = new Derived(async()=>\`derived from ${a.value}\`, 'param-a');"
    >     > -   `<div param-a="innerText;data-a"></div>` will reflect to DOM
    >     >     `<div param-a="innerText;data-a" data-a="value of a">value of a</div>`

-   `Ping`:

    > -   wrapper for async context using simple_signal internal Queue Handler;
    > -   params:
    >     > -   `asyncCallbackWhenPinged`: `(isAtInitisalization:boolean)=>Promise<void>`
    > -   returns:
    >     > -   `ping:(isAtInitisalization:boolean)=>void`
    >     >     > -   run `asyncCallbackWhenPinged`;

-   `$`:

    > -   params:
    >     > -   `asyncCallback`: `(isAtInitialization:boolean)=>Promise<VType>`
    > -   example:
    >     > -   `new $( async (isAtInitialization) => { document.querySelector('p')?.setAttribute('text', b.value) });`
    > -   returns:
    >     > -   `E:asyncCallback`: `(isAtInitialization:boolean)=>Promise<VType>`
    >     >     > -   used for lib internal functionality;

-   `OnViewPort`:

    > -   tips: coupled with `Lifecycle` it can be helpfull for complex client side
    >     routing/rendering;
    > -   params:
    >     > -   `attributeName`: `string`
    >     >     > -   allow to reflect the value to dom, by targeting the value of
    >     >     >     `...(attributeName|propertyName);`;
    >     > -   `OnViewCallback`: `(element:IntersectionObserverEntry['target'])=>Promise<void>`
    >     >     > -   fires when element is entering viewport;
    >     > -   `onExitingViewport?`:
    >     >     `(element:IntersectionObserverEntry['target'], unObserve:()=>void)=>Promise<void>`
    >     >     > -   fires when element is exiting viewport;
    >     >     > -   when `undefined`: will automatically unObserve the elements;
    >     > -   `documentScope?`: `HTMLElement|Element|ShadowRoot|Document`
    >     >     > -   scope of the dom reflector;
    > -   example:
    >     > -   `new OnViewPort('lazy-test', async (element, unobserve) => { console.log({element, message:'lazy is on viewport'}); return async () => { console.log({element, message:'lazy is leavinng viewport'}); unobserve() }; });`
    >     > -   `<p lazy-test>lazy test on view port</p>`

## function api

-   `attrHelper`
    > -   params:
    >     > -   `attrHelpers:Record.<key:string<Vtype>,''>`
    > -   returns:
    >     > -   `Record.<key:string<Vtype>,string>`
    >     >     > -   validated attribute name;

## how to setup

we have several way of installing this library to your app, depending on how do you want to use it

## IF you have no need of typehinting

we have very little api to remember so you can just slap our prebundled on head tag and use it as is

-   download the `prebundled.mjs`;
-   add the script on html `head`;

```html
<head>
	...
	<script src="./path/to/prebundled.mjs" type="module" defer></script>
	...
</head>
```

-   we put it in a `.mjs` and `type="module"` so the `variables` doesn't bleed out without add
    additional closures, or function calls in the libs

## IF you are comfortable with typehinting and you wanted to make it modular

-   install using `npm i @html_first/simple_signal`

```js
// @ts-check

import { Let, $, Derived, Lifecycle, OnViewPort } from '@html_first/simple_signal';
```

## no longer supported as we try to modularize the exports

<strike>
## IF you are comfortable with typehinting but you don't want to be bothered to install using npm

copy the [index.mjs](https://github.com/hakimjazuli/simple_signal/blob/main/index.mjs) on
[our github](https://github.com/hakimjazuli/simple_signal/) code and slap before your own js code

-   delete the `export` statement on all classes; </strike>