Files
sigpro/docs/api/quick.md
natxocc 99780e8399
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
New modular Sigpro
2026-04-27 15:22:57 +02:00

9.1 KiB
Raw Blame History

SigPro Complete API Reference

SigPro is a RealDOM first reactive microframework. No virtual DOM, no diffing overhead it updates the DOM directly with surgical precision. Builtin automatic cleanup prevents memory leaks, and the API is designed to be both tiny and powerful.

import { $, $$, watch, h, when, each, router, mount, batch } from 'sigpro'
// Optional sideeffects (activate global helpers & security):
import 'sigpro/tags'   // → window.div, window.span, etc.
import 'sigpro/xss'    // → attribute sanitisation

In a classic IIFE script (<script src="sigpro.min.js">), everything (core, router, tags, XSS, global functions) is available automatically.


Core Reactivity

$(value, localStorageKey?) Signal & Computed

Creates a reactive signal. If a function is passed, it becomes a computed signal that caches its result until dependencies change.

Usage Description
const count = $(0) Basic signal, returns a getter/setter: count() reads, count(5) writes.
const double = $( () => count() * 2 ) Computed signal updates automatically when count changes.
const stored = $('hello', 'myKey') Persisted signal reads/writes to localStorage.

Example

const count = $(0)
const double = $( () => count() * 2 )

watch(() => {
  console.log(`count = ${count()}, double = ${double()}`)
}) // logs on every change

count(5) // triggers log: count=5, double=10

$$(object) Deep Reactive Proxy

Makes a plain object (and all nested objects) deeply reactive. Any property access is tracked, any mutation triggers updates.

const state = $$({ user: { name: 'Alice', age: 30 }, items: [1,2,3] })

watch(() => {
  console.log(state.user.name) // tracks `user.name`
})

state.user.name = 'Bob' // triggers the effect

Note

: $$ caches proxies per original object, so calling $$ multiple times on the same object returns the same proxy.


watch(source, callback?) Reactive Effect

Two modes:

  1. Autotrack mode pass a function: watch(() => { /* reads signals */ })
    Automatically reruns whenever any signal read inside changes.

  2. Explicit mode pass an array of signals and a callback:
    watch([count, double], () => { ... })
    Runs the callback when any of the listed signals change. The callback receives the new values.

Both modes return a stop function that disposes the effect.

// auto mode
const stop = watch(() => console.log(count()))

// explicit mode
watch([count, double], ([newCount, newDouble]) => {
  console.log(newCount, newDouble)
})

Important

: Effects are depthaware they run in topological order, parents before children.


Components & DOM (Hyperscript)

h(tag, props, children) Create DOM Nodes

The universal builder. props can be omitted. Children can be strings, numbers, nodes, arrays, or dynamic functions.

Feature Example
Standard attributes h('div', { class: 'box', id: 'main' })
Events onClick: (e) => ... (automatically cleaned up)
Reactive attributes class: () => count() > 0 ? 'positive' : 'negative'
Twoway binding value: mySignal (works on input, textarea, select)
Refs ref: (el) => ... or ref: { current: null }
SVG support tag names like svg, circle, path sets correct namespace
Dangerous URL sanitising href / src with javascript: or data: are blocked → '#' (when XSS shield is active)

Dynamic children pass a function as a child, it will be reexecuted and the DOM patched automatically:

h('div', {}, [
  () => count() > 0 ? h('span', {}, 'positive') : h('span', {}, 'zero or negative')
])

Tag shortcuts

Tag helpers are not exported individually from the core. To use them globally without the h(...) wrapper, activate the sideeffect module:

import 'sigpro/tags'   // now window.div, window.span, etc. are available

// You can now write:
div({ class: 'container' }, [
  h1({}, 'Title'),
  button({ onClick: () => alert('hi') }, 'Click me')
])

In the IIFE bundle (sigpro.min.js), the helpers are already injected globally no import needed.

Available tags: a, abbr, article, aside, audio, b, blockquote, br, button, canvas, caption, cite, code, col, colgroup, datalist, dd, del, details, dfn, dialog, div, dl, dt, em, embed, fieldset, figcaption, figure, footer, form, h1h6, header, hr, i, iframe, img, input, ins, kbd, label, legend, li, main, mark, meter, nav, object, ol, optgroup, option, output, p, picture, pre, progress, section, select, slot, small, source, span, strong, sub, summary, sup, svg, table, tbody, td, template, textarea, tfoot, th, thead, time, tr, u, ul, video.


Builtin XSS Shield (Optional)

SigPro includes an optional security layer that sanitises dangerous attributes (href, src, formaction, etc.) and blocks javascript: / data: / vbscript: protocols.
To enable it in ESM environments:

import 'sigpro/xss'

In the IIFE bundle, the shield is active by default.

When the shield is enabled, trying to set href="javascript:alert(1)" will log a warning and replace the value with '#'.


Flow Control Components

when(condition, thenComponent, elseComponent?)

Reactive conditional rendering. condition can be a boolean, a signal, or any function that returns a boolean. Both branches can be Node, () => Node, or null. Automatically disposes the unmounted branch.

when(
  () => user.loggedIn(),
  () => div({}, 'Welcome back!'),
  () => button({ onClick: () => login() }, 'Login')
)

each(source, itemRenderer, keyFn)

Optimised keyed list rendering. source can be an array or a signal/function returning an array. itemRenderer(item, index) returns a Node (or a function that returns Nodes). keyFn(item, index) returns a unique identifier required for efficient DOM reuse.

const items = $([{ id: 1, text: 'a' }, { id: 2, text: 'b' }])

each(items,
  (item) => Li({}, item.text),
  (item) => item.id
)

When the array changes, elements are added, removed, or reordered with minimal DOM operations.


Batch

batch(fn)

Batch multiple reactive updates into a single flush, improving performance.

batch(() => {
  count(1)
  name('John')
  // effects run only once after the batch ends
})

Router router(routes)

Hashbased SPA router. Returns a DOM node that renders the current route.

import { router } from 'sigpro'

const routes = [
  { path: '/', component: () => div({}, 'Home') },
  { path: '/user/:id', component: (params) => div({}, `User ${params.id}`) },
  { path: '*', component: () => div({}, '404') }
]

const App = () => div({}, [
  a({ href: '#/' }, 'Home'),
  a({ href: '#/user/42' }, 'User 42'),
  router(routes)
])

API

Method Description
router.params() Returns a reactive signal of current route params (e.g., { id: '42' }).
router.to(path) Navigate to a new hash (e.g., router.to('/user/5')). Prepend # automatically.
router.back() Go back in history.
router.path() Returns current hash path without # (e.g., /user/42).

Mounting mount(component, target)

Clears the target element and mounts the application. Returns the runtime instance (which has a .destroy() method).

mount(() => App(), '#app')
// or
mount(App, document.body)

If you mount again on the same target, the previous instance is automatically destroyed.


Global Cleanup & Memory

SigPro tracks every effect, DOM event listener, and nested component. When a component is unmounted:

  • All its effects are disposed.
  • All DOM event listeners are removed.
  • All onUnmount callbacks run.
  • Child components are recursively destroyed.

You never need to manually clean up just write reactive code.


Full Example Counter with Persistence

import { $, watch, mount } from 'sigpro'
import 'sigpro/tags'   // ← activate global helpers
import 'sigpro/xss'    // ← activate security (optional)

const count = $(0, 'counter') // persists in localStorage

const App = () =>
  div({ class: 'counter' }, [
    h1({}, () => `Count: ${count()}`),
    button({ onClick: () => count(count() + 1) }, '+'),
    button({ onClick: () => count(count() - 1) }, '-'),
    button({ onClick: () => count(0) }, 'Reset')
  ])

mount(App, '#app')

🔧 Customising the API (Renaming)

You can rename everything in one line:

import { $ as signal, watch as effect, h as element, mount as render } from 'sigpro'

In the IIFE bundle, the core functions are already available as both window.$ and window.SigPro.$, so you can alias them globally if needed:

window.myReactive = $   // or window.SigPro.$