# 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
```

---

### `watch(source, callback?)` – Reactive Effect

Two modes:

1. **Auto‑track mode** – pass a function: `watch(() => { /* reads signals */ })`  
   Automatically re‑runs 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 depth‑aware – 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'` |
| Two‑way 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 re‑executed 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.

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
})
```

## 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')
```
