Update docs

This commit is contained in:
2026-05-14 14:21:21 +02:00
parent 0b3eb0159f
commit 3fe05d40e6
4 changed files with 45 additions and 308 deletions

View File

@@ -18,4 +18,6 @@
* [Global Store](api/global.md) * [Global Store](api/global.md)
* [JSX Style](api/jsx.md) * [JSX Style](api/jsx.md)
* [HTML converter](convert.md) * [HTML converter](convert.md)
* [UI](ui.md)
* **UI**
* [WIP]

View File

@@ -26,24 +26,6 @@ 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 ### `watch(source, callback?)` Reactive Effect
Two modes: Two modes:
@@ -99,18 +81,6 @@ h('div', {}, [
Tag helpers **are exported** from the core. 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`. 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`.
--- ---
@@ -162,39 +132,6 @@ batch(() => {
}) })
``` ```
---
## Router `router(routes)`
Hashbased SPA router. Returns a DOM node that renders the current route.
```javascript
import { router } from 'sigpro/router' // import router
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)` ## Mounting `mount(component, target)`
Clears the target element and mounts the application. Returns the runtime instance (which has a `.destroy()` method). Clears the target element and mounts the application. Returns the runtime instance (which has a `.destroy()` method).

View File

@@ -10,39 +10,13 @@ SigPro creates a wrapper function for each standard HTML tag.
> **Note:** All tag helpers are **lowercase** (e.g., `div`, `span`, `button`) and can be used directly once globally enabled. > **Note:** All tag helpers are **lowercase** (e.g., `div`, `span`, `button`) and can be used directly once globally enabled.
---
## 2. Activating the Tag Helpers
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
**ES module** (`import { ... } from 'sigpro'`).
```js
import { ... } from 'sigpro';
// Now you can use helpers globally
const App = () => div({ class: "app" }, "Ready!");
```
> If you prefer to avoid globals, you can always use `h('div', ...)` directly—its perfectly fine. > If you prefer to avoid globals, you can always use `h('div', ...)` directly—its perfectly fine.
> **Autocleanup:** All tag helpers and `h` automatically dispose effects, event listeners, and nested components when removed from the DOM.
--- ---
## 3. The Complete List of Tag Helpers ## 2. The Complete List of Tag Helpers
All helpers are **lowercase** and follow HTML5 tag names. All helpers are **lowercase** and follow HTML5 tag names.
@@ -59,7 +33,7 @@ Full list: `a`, `abbr`, `article`, `aside`, `audio`, `b`, `blockquote`, `br`, `b
--- ---
## 4. Usage Patterns ## 3. Usage Patterns
### A. Attributes + Children ### A. Attributes + Children
@@ -83,54 +57,7 @@ section([
--- ---
## 5. Reactive Power ## 4. Custom Components with `h()` or Tag Helpers
These helpers are natively wired into SigPro's reactivity system.
### Reactive Attributes (OneWay)
Pass a **function** that returns the value. SigPro creates an internal effect to keep the DOM in sync.
```javascript
const theme = $("light");
div({
class: () => `app-box ${theme()}`
}, "Themeable Box");
```
### TwoWay Binding (Automatic)
Assign a **signal** directly to `value` or `checked` on form inputs SigPro automatically bridges the signal and the input element bidirectionally.
```javascript
const search = $("");
input({
type: "text",
placeholder: "Search...",
value: search
});
```
> **Pro Tip:** To make an input **readonly** but still reactive, wrap the signal in a function: `value: () => search()` this prevents backward synchronization.
### Dynamic Children
You can pass a **function as a child** it will be reexecuted whenever any signal inside changes, and the DOM will be patched surgically.
```javascript
const count = $(0);
div([
p(() => `Count is ${count()}`),
button({ onClick: () => count(count() + 1) }, "Increment")
]);
```
---
## 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. While the tag helpers cover all standard HTML tags, you can create reusable components using them directly.
@@ -170,58 +97,4 @@ const Timer = () => {
return el; return el;
}; };
``` ```
---
## 7. Comparison with `h()`
| Use case | Recommendation |
| :--- | :--- |
| Standard tags (`div`, `span`, `button`) | Use tag helpers: `div()`, `span()`, `button()` |
| Dynamic tag names (unknown at write time) | Use `h(tagName, props, children)` |
| Components returning a single node | Any function that returns a node (using helpers or `h`) |
> **Autocleanup:** All tag helpers and `h` automatically dispose effects, event listeners, and nested components when removed from the DOM.
---
## 8. Complete Example
### ESM (modern projects)
```javascript
import { $, mount } from 'sigpro';
const nameSignal = $('');
const App = () =>
div({ class: "app" }, [
h1("Welcome"),
input({
placeholder: "Your name",
value: nameSignal
}),
p(() => `Hello, ${nameSignal() || "stranger"}!`),
button({ onClick: () => alert("Clicked") }, "Click me")
]);
mount(App, '#app');
```
### Classic IIFE (autoglobal)
```html
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.23/dist/sigpro.min.js"></script>
<script>
const nameSignal = $('');
const App = () => div({ class: "app" }, [
h1("Welcome"),
input({ placeholder: "Your name", value: nameSignal }),
p(() => `Hello, ${nameSignal() || "stranger"}!`),
button({ onClick: () => alert("Clicked") }, "Click me")
]);
mount(App, '#app');
</script>
```

View File

@@ -12,67 +12,32 @@ Choose the method that best fits your workflow:
```bash ```bash
npm install sigpro npm install sigpro
```
</div> or
<input type="radio" name="install_method" class="tab border-base-300" aria-label="pnpm" />
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
```bash
pnpm add sigpro
```
</div>
<input type="radio" name="install_method" class="tab border-base-300" aria-label="yarn" />
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
```bash
yarn add sigpro
```
</div>
<input type="radio" name="install_method" class="tab border-base-300" aria-label="bun" />
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
```bash
bun add sigpro bun add sigpro
``` ```
</div> </div>
<input type="radio" name="install_method" class="tab border-base-300 whitespace-nowrap" aria-label="CDN (ESM)" /> <input type="radio" name="install_method" class="tab border-base-300 whitespace-nowrap" aria-label="CDN" />
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6"> <div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
```html ```html
<script type="module"> <script type="module">
// Import the core // Import the core
import { $, h, mount } from 'https://cdn.jsdelivr.net/npm/sigpro@latest/dist/sigpro.esm.min.js'; import {
$,
h,
mount,
} from "https://cdn.jsdelivr.net/npm/sigpro@latest/dist/sigpro.esm.min.js";
// For full import and assign to window
// import * as SigPro from "./sigpro.js";
// Object.assign(window, SigPro);
// Option A: use named imports (no globals, recommended)
const count = $(0); const count = $(0);
mount(() => h('h1', {}, () => `Count: ${count()}`), '#app'); mount(() => h("h1", {}, () => `Count: ${count()}`), "#app");
</script>
```
</div>
<input type="radio" name="install_method" class="tab border-base-300 whitespace-nowrap" aria-label="CDN (IIFE)" />
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
```html
<!-- Classic script: full kit (core, router, tags, XSS) autoinstalled -->
<script src="https://cdn.jsdelivr.net/npm/sigpro@latest/dist/sigpro.min.js"></script>
<script>
// $, h, div, button, router, etc. are already global
const count = $(0);
const App = () => div({ class: "card" }, [
h1(() => `Count: ${count()}`),
button({ onclick: () => count(count() + 1) }, "Increment")
]);
mount(App, '#app');
</script> </script>
``` ```
@@ -91,7 +56,7 @@ SigPro uses **lowercase** Tag Helpers (e.g., `div`, `button`) to keep the syntax
```javascript ```javascript
// App.js Use named imports for the core, activate helpers if needed // App.js Use named imports for the core, activate helpers if needed
import { $, mount } from 'sigpro'; import { $, mount } from "sigpro";
const App = () => { const App = () => {
const count = $(0); const count = $(0);
@@ -99,12 +64,12 @@ const App = () => {
h1(() => `Count is: ${count()}`), h1(() => `Count is: ${count()}`),
button( button(
{ class: "btn btn-primary", onclick: () => count(count() + 1) }, { class: "btn btn-primary", onclick: () => count(count() + 1) },
"Increment" "Increment",
), ),
]); ]);
}; };
mount(App, '#app'); mount(App, "#app");
``` ```
</div> </div>
@@ -118,20 +83,22 @@ mount(App, '#app');
<body> <body>
<div id="app"></div> <div id="app"></div>
<!-- IIFE full bundle everything ready to use --> <!-- CDN full bundle everything ready to use -->
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.23/dist/sigpro.min.js"></script> <script type="module">
<script> // Import the core
const name = $('Developer'); import { $, h, mount } from "https://cdn.jsdelivr.net/npm/sigpro@latest/dist/sigpro.esm.min.js";
const App = () => section({ class: "container" }, [ const name = $("Developer");
h2(() => `Welcome, ${name()}`), const App = () =>
input({ section({ class: "container" }, [
type: "text", h2(() => `Welcome, ${name()}`),
class: "input input-bordered", input({
value: name, type: "text",
placeholder: "Type your name...", class: "input input-bordered",
}), value: name,
]); placeholder: "Type your name...",
mount(App, '#app'); }),
]);
mount(App, "#app");
</script> </script>
</body> </body>
</html> </html>
@@ -142,56 +109,14 @@ mount(App, '#app');
--- ---
## 3. Global by Design (Two Modes) ## 3. Why no build step?
SigPro gives you full control over global pollution. Because SigPro uses **native ES Modules** and standard JavaScript functions to generate the DOM, you don't actually _need_ a compiler like Babel or a transformer for JSX.
### Mode A: Classic (IIFE) Full Autoinjection
When you load the **IIFE full bundle** (`sigpro.min.js`) with a traditional `<script>` tag (no `type="module"`), the library automatically provides **everything**:
- Core functions (`$`, `$$`, `watch`, `h`, `when`, `each`, `router`, `mount`, `batch`) directly on `window` (also available as `SigPro.*`).
- Lowercase tag helpers (`div`, `span`, `button`, …) become global functions.
- Builtin XSS protection activated.
✅ Zero configuration just drop the script and start coding.
### Mode B: ESM (Modern) Explicit Activation
When you import the **ESM core** (`import { ... } from 'sigpro'`), **only the reactive core and router are available**. Tags and security are optin:
**Named imports** (for the core):
```javascript
import { $, h, mount, router } from 'sigpro';
```
No global pollution perfect for bundlers and large projects.
### Why two modes?
- **Legacy / nobuild**: Use the IIFE full script and get everything automatically.
- **Modern ESM**: Keep your global namespace clean, only activate helpers/security when needed, and benefit from treeshaking.
---
## 4. Why no build step?
Because SigPro uses **native ES Modules** and standard JavaScript functions to generate the DOM, you don't actually *need* a compiler like Babel or a transformer for JSX.
- **Development:** Just save and refresh. Pure JS, no "transpilation" required. - **Development:** Just save and refresh. Pure JS, no "transpilation" required.
- **Performance:** Extremely lightweight. Use any modern bundler (Vite, esbuild) only when you are ready to minify and tree-shake for production. - **Performance:** Extremely lightweight. Use any modern bundler (Vite, esbuild) only when you are ready to minify and tree-shake for production.
## 5. Why SigPro? (The Competitive Edge) ## 4. Key Advantages
SigPro stands out by removing the "Build Step" tax and the "Virtual DOM" overhead. It is the closest you can get to writing raw HTML/JS while maintaining modern reactivity.
| Feature | **SigPro** | **SolidJS** | **Svelte** | **React** | **Vue** |
| :----------------- | :--------------- | :----------- | :----------- | :---------- | :---------- |
| **Bundle Size** | **<3KB** | ~7KB | ~4KB | ~40KB+ | ~30KB |
| **DOM Strategy** | **Direct DOM** | Direct DOM | Compiled DOM | Virtual DOM | Virtual DOM |
| **Reactivity** | **Fine-grained** | Fine-grained | Compiled | Re-renders | Proxies |
| **Build Step** | **Optional** | Required | Required | Required | Optional |
| **Learning Curve** | **Minimal** | Medium | Low | High | Medium |
| **Initialization** | **Ultra-Fast** | Very Fast | Fast | Slow | Medium |
---
## 6. Key Advantages
- **Extreme Performance**: No Virtual DOM reconciliation. SigPro updates the specific node or attribute instantly when a signal changes. - **Extreme Performance**: No Virtual DOM reconciliation. SigPro updates the specific node or attribute instantly when a signal changes.
- **Fine-Grained Reactivity**: State changes only trigger updates where the data is actually used, not on the entire component. - **Fine-Grained Reactivity**: State changes only trigger updates where the data is actually used, not on the entire component.
@@ -201,8 +126,8 @@ SigPro stands out by removing the "Build Step" tax and the "Virtual DOM" overhea
--- ---
## 7. Summary ## 5. Summary
SigPro isn't just another framework; it's a bridge to the native web. By using standard ES Modules and functional DOM generation, you get the benefits of a modern reactive library with the weight of a utility script. SigPro isn't just another framework; it's a bridge to the native web. By using standard ES Modules and functional DOM generation, you get the benefits of a modern reactive library with the weight of a utility script.
**Because, in the end... why fight the web when we can embrace it?** **Because, in the end... why fight the web when we can embrace it?**