Files
sigpro/docs/api/quick.md
natxocc 820d55b012
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 4s
Docs
2026-05-02 00:37:15 +02:00

241 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SigPro Complete API Reference
## 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**
```javascript
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.
```javascript
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.
```javascript
// 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:
```javascript
h('div', {}, [
() => count() > 0 ? h('span', {}, 'positive') : h('span', {}, 'zero or negative')
])
```
### Tag shortcuts
Tag helpers **are exported** from the core.
```javascript
import "sigpro"
// 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`, `h1``h6`, `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`.
---
## 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.
```javascript
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.
```javascript
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.
```javascript
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.
```javascript
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).
```javascript
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
```javascript
import { $, mount } from 'sigpro';
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')
```