A smaller, simpler signals.
This is not as magical or robust as other implementations, but it is very small. Look at alien-signals or @preact/signals if you need more magic or functionality.
npm i -S @substrate-system/signsCounting clicks.
This example is only 886 bytes after minifying and gzipping.
import { effect, sign } from '@substrate-system/signs'
const qs = document.querySelector.bind(document)
const count = sign(0)
qs('#root').innerHTML = `
<h1 class="count">${count.value}</h1>
<button class="plus">Plus</button>
<button class="reset">Reset</button>
`
effect(() => {
qs('h1').innerHTML = count.value
})
qs('button.reset').addEventListener('click', ev => {
ev.preventDefault()
count.value = 0
})
qs('button.plus').addEventListener('click', ev => {
ev.preventDefault()
count.value++
})Create a new sign.
type Sign<T> = {
value:T
peek:()=>T
}
function sign<T> (value:T, options?: SignOptions):Sign<T>Get the sign's current value, but do not subscribe to that sign.
type Sign<T> = {
value:T
peek:()=>T
}import { sign, effect } from '@substrate-system/signs'
const delta = sign(0)
const count = sign(0)
effect(() => {
// Update `count` without subscribing to `count`:
count.value = count.peek() + delta.value;
})
// rerun the effect
delta.value = 1
// Do not rerun the effect,
// b/c we used `.peek`, not `.value`
count.value = 10Call the subscriber function any time the sign's value changes.
function effect (fn:()=>any):()=>voidCreate a new sign that will update whenever the root sign changes.
function computed<T> (fn:()=>T):Sign<T>import { sign, computed } from '@substrate-system/signs'
const hello = sign('hello')
const derived = computed(() => {
return hello.value + ' world'
})
hello.value = 'goodbye'
console.log('derived value', derived.value)
// => 'goodbye world'Combine multiple signal writes into one single update that is triggered when the callback completes.
function batch<T> (fn:()=>T):Timport { sign, computed, effect, batch } from '@substrate-system/signs'
const name = sign('Jane')
const surname = sign('Doe')
const fullName = computed(() => name.value + ' ' + surname.value)
// Will be called initially and once after the batch completes
effect(() => console.log(fullName.value))
// => Jane Doe
// => Foo Bar
// Combines both signal writes into one update.
batch(() => {
name.value = 'Foo'
surname.value = 'Bar'
})This exposes ESM and common JS via package.json exports field.
import { sign, effect, computed, batch, CycleError } from '@substrate-system/signs'const { sign, effect, computed, batch, CycleError } = require('@substrate-system/signs')This package exposes minified JS files too. Copy them to a location that is accessible to your web server, then link to them in HTML.
cp ./node_modules/@substrate-system/signs/dist/index.min.js ./public/signs.min.js<script type="module" src="/signs.min.js"></script>Start a localhost server of the example directory:
npm startA convenient script that will tell you the filesize of the example app:
npm run sizenpm test | npx tap-spec