New modular Sigpro
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s

This commit is contained in:
2026-04-27 15:22:57 +02:00
parent b931434edc
commit 99780e8399
21 changed files with 888 additions and 1036 deletions

View File

@@ -1,184 +0,0 @@
# Animation Helper: `fx( )`
The `fx` function applies simple **enter animations** to DOM elements. You can either use a predefined CSS keyframes animation or declare inline transition effects (scale, slide, rotate, blur). It is designed to be used when dynamically creating elements especially inside `when` or `each` branches.
## Function Signature
```typescript
fx(
options: {
name?: string; // CSS keyframes animation name (will append '-in')
duration?: number; // Animation duration in ms (default: 200)
scale?: boolean; // Start with scale(0.95) → none
slide?: boolean; // Start with translateY(-10px) → none
rotate?: boolean; // Start with rotate(-2deg) → none
blur?: boolean; // Start with blur(4px) → none
},
child: Node | (() => Node)
): Node
```
| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **`options`** | `object` | Yes | Animation configuration. |
| **`options.name`** | `string` | No | Name of a CSS `@keyframes` animation. The actual animation name becomes `${name}-in`. |
| **`options.duration`** | `number` | No | Duration in milliseconds (default `200`). |
| **`options.scale`** | `boolean` | No | Add a scale transform from `0.95` to `none`. |
| **`options.slide`** | `boolean` | No | Add a vertical slide from `translateY(-10px)` to `none`. |
| **`options.rotate`** | `boolean` | No | Add a small rotation from `rotate(-2deg)` to `none`. |
| **`options.blur`** | `boolean` | No | Add a blur filter from `blur(4px)` to `none`. |
| **`child`** | `Node` or `() => Node` | Yes | The element to animate. If a function is passed, it is called to obtain the node. |
**Returns:** The same DOM node (or the child if it is not a `Node`), after applying the animation setup.
> **Availability:** `fx` is exported from the SigPro module. In **ESM** you must import it (`import { fx } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
---
## Usage Patterns
### 1. Named CSS Keyframes Animation
Define a `@keyframes` rule in your CSS, for example:
```css
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
```
Then apply it with `fx`:
```javascript
const MyComponent = () =>
fx({ name: "fade", duration: 300 },
div("I will fade in")
);
```
> The animation name used is `${name}-in`. In this example: `fade-in`.
### 2. Inline Transition (Scale + Opacity)
No CSS keyframes needed. The element starts with `opacity: 0` and `transform: scale(0.95)`, then transitions to `opacity: 1` and `transform: none`.
```javascript
fx({ scale: true, duration: 200 },
button({ onClick: () => alert("Hi") }, "Click me")
);
```
### 3. Combining Multiple Effects
You can combine `scale`, `slide`, `rotate`, and `blur` at the same time.
```javascript
fx({ scale: true, slide: true, blur: true, duration: 250 },
div({ class: "card" }, "Smooth enter")
);
```
### 4. Using with `when` (Conditional Rendering)
Wrap the branch content with `fx` to animate entering elements.
```javascript
when(show,
() => fx({ slide: true },
div("This slides in when visible")
)
);
```
### 5. Using a Function as Child
If the element is created inside a function (e.g. to avoid recreation until needed), pass a function that returns the node.
```javascript
fx({ scale: true },
() => div("Lazy created and then animated")
);
```
---
## What Happens Under the Hood
### With `name` (CSS animation)
- Sets `el.style.animation = `${name}-in ${duration}ms``.
- The element animates according to your keyframes.
- No further inline style changes are applied.
### Without `name` (transition effects)
- Sets `el.style.transition = `all ${duration}ms ease``.
- Sets initial `opacity: 0`.
- Applies initial transforms (`scale`, `slide`, `rotate`) if selected.
- Applies initial `filter: blur(4px)` if `blur: true`.
- In the next animation frame (via `requestAnimationFrame`), sets:
- `opacity: 1`
- `transform: none`
- `filter: none`
- The element transitions smoothly from the start state to the final state.
> **Important:** The element must be **in the DOM** when the animation starts. `fx` does **not** automatically mount the node you must already have appended it or be about to mount it. In practice, when you call `fx` inside a component that is being mounted, the element will be added to the DOM shortly after, and the animation runs correctly.
---
## Complete Example
```javascript
const App = () =>
div([
fx({ name: "fade", duration: 400 },
h1("Welcome to SigPro")
),
fx({ scale: true, slide: true, duration: 250 },
button({ onClick: () => alert("Animated!") }, "Animated button")
)
]);
mount(App, "#app");
```
With accompanying CSS:
```css
@keyframes fade-in {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
```
---
## Notes
- `fx` is **not** required for basic reactivity it is purely a visual helper for enter animations.
- For exit animations (when an element is removed), use CSS transitions on the element itself combined with `when` or consider adding a wrapper that delays removal. SigPro does not include builtin exit animations.
- The function returns the same node you passed, so you can inline it inside `h` or tag helpers:
```javascript
div([
fx({ scale: true }, span("Hello"))
])
```
- If `child` is not a DOM node (e.g., a string or number), `fx` returns it unchanged no animation is applied.
---
## Summary
| Option | Effect |
| :--- | :--- |
| `name` | Uses `@keyframes ${name}-in` CSS animation. |
| `duration` | Controls animation/transition length (ms). |
| `scale` | Start scale `0.95``none`. |
| `slide` | Start `translateY(-10px)``none`. |
| `rotate` | Start `rotate(-2deg)``none`. |
| `blur` | Start `blur(4px)``none`. |
Combine options to create smooth, modern entrance effects without writing extra CSS.

View File

@@ -112,6 +112,7 @@ export const filteredTodos = $(() => {
```javascript
// components/TodoApp.js
import { todos, filter, addTodo, toggleTodo, filteredTodos } from "../store/todos.js";
import "sigpro/tags" // tags helpers available in global
const TodoApp = () =>
div({ class: "todo-app" }, [

View File

@@ -120,6 +120,7 @@ When `destroy()` is called (or when a new mount replaces an old one), everything
```javascript
import { $, mount, div, h1, button } from 'sigpro';
import "sigpro/tags" // tags helpers available in global
const App = () => {
const count = $(0);

View File

@@ -1,17 +1,19 @@
# SigPro Complete API Reference
# 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.
```javascript
import { $, $$, watch, h, when, each, fx, router, req, mount, batch } from 'sigpro'
// Or, if you prefer the global style in an ESM environment:
// import { sigpro } from 'sigpro'; sigpro(); // then $, h, div... become window globals
// In a classic IIFE script (<script src="sigpro.js">), everything is available globally automatically.
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
## Core Reactivity
### `$(value, localStorageKey?)` Signal & Computed
@@ -82,7 +84,7 @@ watch([count, double], ([newCount, newDouble]) => {
---
## 🧱 Components & DOM (Hyperscript)
## Components & DOM (Hyperscript)
### `h(tag, props, children)` Create DOM Nodes
@@ -96,7 +98,7 @@ The universal builder. `props` can be omitted. Children can be strings, numbers,
| 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 → `'#'` |
| 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:
@@ -108,28 +110,40 @@ h('div', {}, [
### Tag shortcuts
When using the **ESM module with named imports**, you can import the tag helpers individually:
Tag helpers are **not exported individually** from the core. To use them globally without the `h(...)` wrapper, activate the sideeffect module:
```javascript
import { div, h1, button } from 'sigpro'
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')
])
```
If you prefer the **global style** (all tags and core functions on `window`), either:
- Use the classic IIFE script: `<script src="sigpro.js"></script>`
- Or in ESM, call `sigpro()` after importing: `import { sigpro } from 'sigpro'; sigpro();`
After that, you can write `div()`, `span()`, etc. directly, without any import.
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
## 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:
```javascript
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?)`
@@ -162,7 +176,7 @@ When the array changes, elements are added, removed, or reordered with minimal D
---
## 💥 Batch
## Batch
### `batch(fn)`
@@ -178,33 +192,13 @@ batch(() => {
---
## ✨ Animations `fx(options, child)`
Applies smooth enter animations (CSS transitions / keyframes). Returns the modified element.
```javascript
fx({ name: 'fade', duration: 300 },
div({}, 'Hello')
)
```
**Options**
- `name` uses predefined keyframes `${name}-in` (you must define them in your CSS)
- `duration` in ms (default 200)
- `scale` adds `scale(0.95)``none`
- `slide` adds `translateY(-10px)``none`
- `rotate` adds `rotate(-2deg)``none`
- `blur` adds `blur(4px)``none`
If `name` is given, it sets `animation: ${name}-in ${duration}ms`. Otherwise it applies a smooth transition from the initial transform/filter to the final state.
---
## 🧭 Router `router(routes)`
## 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}`) },
@@ -229,44 +223,7 @@ const App = () => div({}, [
---
## 🌐 HTTP Requests `req(config)`
Creates a reactive request controller with builtin loading/error/data signals and abort support.
```javascript
const fetchUser = req({ url: '/api/user/1', method: 'GET' })
// start the request
fetchUser.run().catch(console.error)
// reactively display state
watch(() => {
if (fetchUser.loading()) console.log('loading...')
if (fetchUser.error()) console.error(fetchUser.error())
if (fetchUser.data()) console.log(fetchUser.data())
})
// abort if needed
fetchUser.abort()
```
**Options**
- `url` (required)
- `method` (default `'GET'`)
- `headers` (object, default `{}`)
**Return value**
- `run(body?)` initiates the request, returns a promise.
- `abort()` aborts the current request (AbortController).
- `loading` signal (boolean)
- `error` signal (`null` or error message)
- `data` signal (`null` or parsed JSON)
> **Note**: Automatically sets `Content-Type: application/json` unless `body` is a `FormData`. Timeout after 10 seconds aborts the request.
---
## 🚀 Mounting `mount(component, target)`
## Mounting `mount(component, target)`
Clears the target element and mounts the application. Returns the runtime instance (which has a `.destroy()` method).
@@ -280,7 +237,7 @@ If you mount again on the same target, the previous instance is automatically de
---
## 🧹 Global Cleanup & Memory
## Global Cleanup & Memory
SigPro tracks every effect, DOM event listener, and nested component. When a component is unmounted:
- All its effects are disposed.
@@ -292,10 +249,12 @@ You never need to manually clean up just write reactive code.
---
## 📦 Full Example Counter with Persistence
## Full Example Counter with Persistence
```javascript
import { $, watch, h, mount } from 'sigpro'
import { $, watch, mount } from 'sigpro'
import 'sigpro/tags' // ← activate global helpers
import 'sigpro/xss' // ← activate security (optional)
const count = $(0, 'counter') // persists in localStorage
@@ -320,8 +279,8 @@ You can rename everything in one line:
import { $ as signal, watch as effect, h as element, mount as render } from 'sigpro'
```
Or assign globally (after calling `sigpro()` or using the classic script):
In the IIFE bundle, the core functions are already available as both `window.$` and `window.SigPro.$`, so you can alias them globally if needed:
```javascript
window.myReactive = $
window.myReactive = $ // or window.SigPro.$
```

View File

@@ -1,184 +0,0 @@
# HTTP Requests: `req( )`
The `req` function creates a **reactive HTTP request controller**. It returns signals for `loading`, `error`, and `data`, plus a `run` method to execute the request and an `abort` method to cancel it. All signals update automatically as the request progresses.
## Function Signature
```typescript
req(config: {
url: string;
method?: string; // default: 'GET'
headers?: Record<string, string>;
}): {
run: (body?: any) => Promise<any>;
abort: () => void;
loading: Signal<boolean>;
error: Signal<string | null>;
data: Signal<any | null>;
}
```
| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **`url`** | `string` | Yes | The endpoint to call. |
| **`method`** | `string` | No | HTTP method (`'GET'`, `'POST'`, etc.). Default `'GET'`. |
| **`headers`** | `object` | No | Custom headers (will be merged with defaults). |
**Returns:** A controller object with reactive signals and methods.
> **Availability:** `req` is exported from the SigPro module. In **ESM** you must import it (`import { req } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
---
## Usage Patterns
### 1. Basic GET Request
```javascript
const users = req({ url: '/api/users' });
// Start the request
users.run().catch(console.error);
// React to the response
watch(() => {
if (users.loading()) console.log('Loading...');
if (users.error()) console.error(users.error());
if (users.data()) console.log('Data:', users.data());
});
```
### 2. POST Request with Body
```javascript
const createUser = req({ url: '/api/users', method: 'POST' });
const handleSubmit = async (formData) => {
try {
await createUser.run(formData);
alert('User created!');
} catch (err) {
// Error already in createUser.error()
}
};
```
### 3. Aborting a Request
```javascript
const search = req({ url: '/api/search' });
// Abort if the user types again quickly
let timeout;
input({ onInput: (e) => {
clearTimeout(timeout);
search.abort(); // cancel previous in-flight request
timeout = setTimeout(() => search.run({ q: e.target.value }), 300);
}});
```
### 4. Reactive UI with Signals
```javascript
const profile = req({ url: '/api/me' });
const App = () =>
div([
when(() => profile.loading(),
() => div("Loading...")
),
when(() => profile.error(),
() => div("Error: " + profile.error())
),
when(() => profile.data(),
() => div([
h2(profile.data().name),
p(profile.data().email)
])
)
]);
profile.run();
mount(App, '#app');
```
---
## Request Lifecycle
When you call `run(body?)`:
1. Any previous request is **aborted** automatically.
2. `loading` becomes `true`.
3. `error` is cleared.
4. A 10second timeout is set (autoabort).
5. The request is sent using `fetch`.
6. On success: `data` is set with the parsed JSON, `loading` becomes `false`.
7. On error: `error` is set with the message, `data` is cleared, `loading` becomes `false`.
> **Important:** The response body is parsed as JSON. If the response is not OK or the JSON parsing fails, `error` is set and the promise rejects.
---
## Automatic Headers
- If `body` is a plain object or array, the request automatically includes `Content-Type: application/json` (unless you override it in `headers`).
- If `body` is a `FormData` instance, the `Content-Type` is not set (browser will set it automatically with the correct boundary).
- Other headers can be added via the `headers` option.
```javascript
const upload = req({
url: '/upload',
method: 'POST',
headers: { 'X-Custom': 'value' }
});
const formData = new FormData();
formData.append('file', fileInput.files[0]);
upload.run(formData);
```
---
## Error Handling
- Network errors, timeouts, and HTTP error statuses (4xx, 5xx) all set `error` and cause the promise to reject.
- The `error` signal contains a humanreadable message.
- Abort errors (calling `abort()` or timeout) are **silent** they do not set `error` or reject the promise?
Actually, according to the source: if `e.name === 'AbortError'`, it does **not** call `error(e.message)`, but the promise still rejects with the AbortError. You can handle it with `.catch()` if needed.
---
## Complete Example
```javascript
const api = req({ url: 'https://jsonplaceholder.typicode.com/posts/1' });
const App = () =>
div({ class: "demo" }, [
when(() => api.loading(), () => p("⏳ Loading...")),
when(() => api.error(), () => p("❌ " + api.error())),
when(() => api.data(), () => div([
h2(api.data().title),
p(api.data().body)
])),
button({
onClick: () => api.run(),
disabled: () => api.loading()
}, "Fetch")
]);
mount(App, '#app');
```
---
## Summary
| Member | Type | Description |
| :--- | :--- | :--- |
| `run(body?)` | `(any) => Promise` | Starts the request. Returns a promise. |
| `abort()` | `() => void` | Cancels the current request. |
| `loading` | `Signal<boolean>` | `true` while request is in flight. |
| `error` | `Signal<string\|null>` | Contains an error message, or `null`. |
| `data` | `Signal<any\|null>` | Contains the parsed response (JSON), or `null`. |

View File

@@ -153,6 +153,7 @@ If you want the router outlet to have no layout impact, you can set `display: co
```javascript
import { $, router, mount } from "sigpro";
import "sigpro/tags" // tags helpers available in global
const Home = () => div("Welcome home");
const About = () => div("About us");

View File

@@ -4,58 +4,72 @@ In **SigPro**, you don't need to manually type `h('div', ...)` for every element
## 1. How it Works
SigPro iterates through a list of standard HTML tags and creates a wrapper function for each one.
SigPro creates a wrapper function for each standard HTML tag.
- **Under the hood:** `h('button', { onclick: ... }, 'Click')`
- **SigPro Style:** `button({ onclick: ... }, 'Click')`
> **Note:** All tag helpers are **lowercase** (e.g., `div`, `span`, `button`). This keeps the syntax close to raw HTML.
These helpers can be used in two ways, depending on your environment:
### Mode A: Classic (IIFE) Autoglobal
When you load the **IIFE bundle** (`sigpro.js`) with a traditional `<script>` tag (no `type="module"`), all tag helpers are automatically injected into the `window` object.
```html
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
<script>
// div, span, button, ... are already global
const App = () => div({ class: "card" }, "Hello");
</script>
```
### Mode B: ESM (Modern) Explicit or Imported
When you import the **ES module** (via `import` or CDN with `type="module"`), nothing is added to `window` by default. You have two options:
1. **Manual global injection** import `sigpro` and call it:
```javascript
import { sigpro } from 'sigpro';
sigpro(); // now div, span, button, etc. become global
```
2. **Named imports** (recommended) import the helpers you need directly:
```javascript
import { div, span, button } from 'sigpro';
// use them directly
```
> **Note:** All tag helpers are **lowercase** (e.g., `div`, `span`, `button`) and can be used directly once globally enabled.
---
## 2. The Complete List of Tag Helpers
## 2. Activating the Tag Helpers
All helpers are **lowercase** and follow HTML5 tag names. You can use them globally (after injection) or import them individually.
Depending on how you load SigPro, the activation varies:
### A. Classic IIFE Automatic Global Helpers
When you use the **IIFE bundle** (`sigpro.js` or `sigpro.min.js`) with a traditional `<script>` tag (no `type="module"`), **all tag helpers, signals, and XSS protection are automatically installed on `window`**. No extra steps needed.
```html
<script src="https://cdn.jsdelivr.net/npm/sigpro@latest/dist/sigpro.min.js"></script>
<script>
// div, span, button, $, h, mount, router... are already global
const App = () => div({ class: "card" }, "Hello");
mount(App, '#app');
</script>
```
### B. ESM (Modern JavaScript) Explicit Activation
When you import the **ES module** (`import { ... } from 'sigpro'`), the core **does not** add helpers to `window` by default. To enable global tags, import the dedicated sideeffect module:
```js
import 'sigpro/tags'; // ← activates window.div, window.span, etc.
// Now you can use helpers globally
const App = () => div({ class: "app" }, "Ready!");
```
If you also want builtin **XSS protection**, enable it once:
```js
import 'sigpro/xss'; // ← add security layer
import 'sigpro/tags'; // ← global helpers
```
Both are sideeffect modules, so the order doesnt matter.
> **Important:** The tag helpers are **not** exported as individual named exports from the core (`sigpro`). They become available as global functions (`window.div`, etc.) after the sideeffect runs.
> If you prefer to avoid globals, you can always use `h('div', ...)` directly—its perfectly fine.
---
## 3. The Complete List of Tag Helpers
All helpers are **lowercase** and follow HTML5 tag names.
| Category | Available functions |
| :--- | :--- |
| **Structure** | `div`, `span`, `p`, `section`, `nav`, `main`, `header`, `footer`, `article`, `aside` |
| **Typography** | `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `ul`, `ol`, `li`, `dl`, `dt`, `dd`, `strong`, `em`, `code`, `pre`, `small`, `b`, `u`, `mark` |
| **Typography** | `h1``h6`, `ul`, `ol`, `li`, `dl`, `dt`, `dd`, `strong`, `em`, `code`, `pre`, `small`, `b`, `u`, `mark` |
| **Interactive** | `button`, `a`, `label`, `br`, `hr`, `details`, `summary`, `dialog` |
| **Forms** | `form`, `input`, `select`, `option`, `textarea`, `fieldset`, `legend` |
| **Tables** | `table`, `thead`, `tbody`, `tr`, `th`, `td`, `tfoot`, `caption` |
| **Media** | `img`, `canvas`, `video`, `audio`, `svg`, `iframe`, `picture`, `source` |
Full list includes all standard 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`.
Full list: `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`.
---
## 3. Usage Patterns
## 4. Usage Patterns
### A. Attributes + Children
@@ -79,7 +93,7 @@ section([
---
## 4. Reactive Power
## 5. Reactive Power
These helpers are natively wired into SigPro's reactivity system.
@@ -126,7 +140,7 @@ div([
---
## 5. Custom Components with `h()` or Tag Helpers
## 6. Custom Components with `h()` or Tag Helpers
While the tag helpers cover all standard HTML tags, you can create reusable components using them directly.
@@ -170,7 +184,7 @@ const Timer = () => {
---
## 6. Comparison with `h()`
## 7. Comparison with `h()`
| Use case | Recommendation |
| :--- | :--- |
@@ -182,11 +196,17 @@ const Timer = () => {
---
## 7. Complete Example
## 8. Complete Example
### ESM (modern projects)
```javascript
// In a modern ESM environment (recommended)
import { div, h1, input, p, button, mount, $ } from 'sigpro';
// Enable global helpers + security
import 'sigpro/tags';
import 'sigpro/xss';
// Import core functions
import { $, mount } from 'sigpro';
const nameSignal = $('');
@@ -204,10 +224,10 @@ const App = () =>
mount(App, '#app');
```
Or using the classic script (autoglobal):
### Classic IIFE (autoglobal)
```html
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.23/dist/sigpro.min.js"></script>
<script>
const nameSignal = $('');
const App = () => div({ class: "app" }, [
@@ -222,23 +242,24 @@ Or using the classic script (autoglobal):
---
## 8. Important Notes
## 9. Important Notes
- **Naming:** All tag helpers are **lowercase**.
- **Global availability:**
- **IIFE script** automatically on `window`.
- **ESM module** not global by default; use `import { div } from 'sigpro'` or call `sigpro()` to inject all globals.
- **IIFE script** automatically on `window`.
- **ESM module** not global by default; use `import 'sigpro/tags'` to activate them.
- **Custom components:** Use **PascalCase** for your own component functions (e.g., `UserCard`) to visually distinguish them from builtin tags.
---
## 9. Summary
## 10. Summary
| Feature | Description |
| :--- | :--- |
| **Tag helpers** | Lowercase functions for every HTML element (e.g., `div()`, `button()`). |
| **Availability** | Autoglobal in IIFE; in ESM use named imports or `sigpro()`. |
| **Activation** | IIFE: automatic. ESM: `import 'sigpro/tags'`. |
| **Reactive attributes** | Pass a function to any attribute to keep it synced. |
| **Twoway binding** | Assign a signal directly to `value` or `checked` on form elements. |
| **Dynamic children** | Pass a function as a child for live updating content. |
| **Autocleanup** | All effects, events, and children are disposed when the element is removed. |
| **Security** | Optional XSS shield: `import 'sigpro/xss'`. |