diff --git a/docs/README.md b/docs/README.md index 3cd1182..6d0bfff 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,42 +1,55 @@
SigPro Logo

SigPro

Atomic Unified Reactive Engine
"The efficiency of direct DOM manipulation with the elegance of functional reactivity."
-

FUNCTIONAL

No strings. No templates. Pure JS function calls for instant DOM mounting.

ATOMIC

Fine-grained signals update exactly what changes. No V-DOM diffing overhead.

ULTRA-THIN

Sub-2KB runtime. Infinitely smaller bundle than React, Vue or even Svelte.

COMPILER-FREE

Standard Vanilla JS. What you write is what the browser executes. Period.

+

FUNCTIONAL

No strings. No templates. Pure JS function calls for instant DOM mounting.

ATOMIC

Fine‑grained signals update exactly what changes. No V‑DOM diffing overhead.

ULTRA‑THIN

Sub‑2KB runtime. Infinitely smaller bundle than React, Vue or even Svelte.

COMPILER‑FREE

Standard Vanilla JS. What you write is what the browser executes. Period.

-## Functional DOM Construction +

Functional DOM Construction

SigPro replaces slow "Template Parsing" with High‑Efficiency Function Calls. While other frameworks force the browser to parse strings of HTML or execute complex JSX transformations, SigPro uses a direct functional approach.

-SigPro replaces the slow "Template Parsing" with **High-Efficiency Function Calls**. + + + + + + + + +
FeatureStandard HTML / JSXSigPro Functional
Syntax<div>Hello</div>div("Hello") (or h('div', "Hello"))
ProcessingParse → Diff → PatchDirect API Call
OverheadHigh (V‑DOM / Parser)Zero
ReactivityComponent‑wideAtomic (Node‑level)
-While other frameworks force the browser to parse strings of HTML or execute complex JSX transformations, SigPro uses a direct functional approach: +

Less Code, More Power

+

By sharing a minuscule runtime, your final application bundle is infinitely smaller.

+ -| Feature | Standard HTML / JSX | SigPro Functional | -| :--- | :--- | :--- | -| **Syntax** | `
Hello
` | `Div("Hello")` | -| **Processing** | Parse → Diff → Patch | Direct API Call | -| **Overhead** | High (V-DOM / Parser) | **Zero** | -| **Reactivity** | Component-wide | **Atomic (Node-level)** | +

Two Ways to Use SigPro (v1.2.19+)

+

🎯 Modern ESM (recommended): Import only the functions you need – zero global pollution.

+
import { $, div, button, mount } from 'sigpro';
+const count = $(0);
+mount(() => div([ button({ onclick: () => count(count()+1) }, count) ]), '#app');
+

🌍 Classic Global (IIFE): Load the script and everything is automatically on window – no imports needed.

+
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
+<script>
+const count = $(0);
+mount(() => div([ button({ onclick: () => count(count()+1) }, count) ]), '#app');
+</script>
+

🔧 ESM + Global injection: If you want the global helpers but still use type="module", call sigpro().

+
<script type="module">
+import { sigpro } from 'https://cdn.jsdelivr.net/npm/sigpro@1.2.19/+esm';
+sigpro();   // now $, div, button, etc. are global
+</script>
-### Less Code, More Power -By sharing a miniscule runtime, your final application bundle is **infinitely smaller**. +

Precision Engineering

+

1. Functional Efficiency

+

div(), button(), span()… These aren't just wrappers; they are pre‑optimized constructors. When you call div({ class: 'btn' }, "Click"), SigPro creates the element and attaches its reactive listeners in a single, surgical operation.

-* **React/Vue:** You ship a heavy orchestrator (~30-90KB) just to say "Hello World". -* **Solid/Svelte:** You still depend on a compilation step that generates extra boilerplate. -* **SigPro:** You ship **Pure Vanilla JS**. The runtime is so small that it often costs less than a single high-res icon. +

2. The "No‑Bundle" Bundle

+

Because SigPro is so small, it is the only engine where the more code you write, the more the efficiency gap grows. While others grow linearly with components and framework overhead, SigPro stays flat, leveraging the native power of modern browser engines.

---- +

3. Shared Runtime

+

All components share the same atomic engine. One signal can update a single character in a paragraph across 100 components without ever re‑evaluating the component functions themselves.

+
-## Precision Engineering - -### 1. Functional Efficiency -`Div()`, `Button()`, `Span()`... These aren't just wrappers; they are pre-optimized constructors. When you call `Div({ class: 'btn' }, "Click")`, SigPro creates the element and attaches its reactive listeners in a single, surgical operation. - -### 2. The "No-Bundle" Bundle -Because SigPro is so small, it is the only engine where **the more code you write, the more the efficiency gap grows**. While others grow linearly with components and framework overhead, SigPro stays flat, leveraging the native power of modern browser engines. - -### 3. Shared Runtime -All components share the same atomic engine. One signal can update a single character in a paragraph across 100 components without ever re-evaluating the component functions themselves. - ---- - -

Kill the Bloat.

Stop shipping 100KB of "Framework" for 2KB of business logic. SigPro gives you the tools to build ultra-fast, modern apps with True Vanilla Performance.

+

Kill the Bloat.

Stop shipping 100KB of "Framework" for 2KB of business logic. SigPro gives you the tools to build ultra‑fast, modern apps with True Vanilla Performance.

Precision Reactive Engine — NatxoCC
diff --git a/docs/api/each.md b/docs/api/each.md index a28467d..b573e0e 100644 --- a/docs/api/each.md +++ b/docs/api/each.md @@ -8,7 +8,7 @@ The `each` function is a high‑performance keyed list renderer. It maps a react each( source: Signal | (() => any[]) | any[], itemFn: (item: any, index: number) => Node | (() => Node), - keyFn?: (item: any, index: number) => string | number + keyField?: string ): HTMLElement ``` @@ -16,7 +16,7 @@ each( | :--- | :--- | :--- | :--- | | **`source`** | `Signal`, `() => any[]`, or `any[]` | Yes | The reactive array to iterate over. | | **`itemFn`** | `(item, index) => Node` | Yes | Returns a DOM node (or a function that returns a node) for each item. | -| **`keyFn`** | `(item, index) => string/number` | No | Extracts a unique key. Default: `item?.id ?? index`. | +| **`keyField`** | `string` | No | Name of the property to use as unique key (e.g., `"id"`). Default: `item?.id ?? index`. | **Returns:** A `div` with `style="display: contents"` that contains the live list. @@ -26,7 +26,7 @@ each( ### 1. Basic Keyed List (Recommended) -Always provide a unique `id` as the key. This allows SigPro to reuse DOM nodes when the list is reordered or filtered. +Pass the name of the property that contains the unique identifier (e.g., `"id"`). This allows SigPro to reuse DOM nodes when the list is reordered or filtered. ```javascript const users = $([ @@ -37,14 +37,14 @@ const users = $([ ul({ class: "list" }, [ each(users, (user) => li({ class: "p-2" }, user.name), - (user) => user.id // stable unique key + "id" // ← use property "id" as stable key ) ]); ``` ### 2. Automatic Key (Simple Lists) -If you omit the `keyFn`, `each` defaults to `item?.id ?? index`. For primitive arrays or objects without an `id`, the index is used. +If you omit the `keyField`, `each` defaults to `item?.id ?? index`. For primitive arrays or objects without an `id`, the index is used. ```javascript const tags = $(["Tech", "JS", "Web"]); @@ -55,7 +55,20 @@ div({ class: "flex gap-1" }, [ ]); ``` -### 3. Dynamic Content Using Functions +### 3. Using a Different Property Name + +If your unique identifier is not called `id` (e.g., `_id`, `userId`, `slug`), just pass the property name as the third parameter: + +```javascript +const products = $([ + { _id: 101, name: "Laptop" }, + { _id: 102, name: "Mouse" } +]); + +each(products, (item) => li(item.name), "_id"); +``` + +### 4. Dynamic Content Using Functions If your `itemFn` returns a **function**, that function is re‑executed every time the item’s data changes (but the node is reused). @@ -69,11 +82,11 @@ each(todos, input({ type: "checkbox", checked: () => todo.done, onInput: e => todo.done = e.target.checked }), span(() => todo.done ? s(todo.text) : todo.text) ]), - (todo) => todo.id + "id" ); ``` -### 4. Source as a Plain Array or Function +### 5. Source as a Plain Array or Function `source` can be a plain array (non‑reactive) or a function that returns an array – it will still react to changes if signals are read inside the function. @@ -86,7 +99,7 @@ const filteredTodos = () => { return all; }; -each(filteredTodos, (todo) => li(todo.text), (todo) => todo.id); +each(filteredTodos, (todo) => li(todo.text), "id"); ``` --- @@ -95,7 +108,7 @@ each(filteredTodos, (todo) => li(todo.text), (todo) => todo.id); When the `source` changes, `each`: -1. **Compares keys** between the old and new items using the `keyFn`. +1. **Compares keys** between the old and new items using the specified `keyField` (or `item.id` / index). 2. **Reuses existing DOM nodes** for keys that stay the same. 3. **Moves nodes** if order changed (no recreation). 4. **Creates new nodes** for new keys. @@ -107,8 +120,8 @@ When the `source` changes, `each`: ## Performance Tips -- **Stable keys** – Use a real `id` (like a database primary key). Avoid `Math.random()` or array `index` for lists that can be reordered. -- **State preservation** – If a list item contains an input or a local state, using a stable key ensures that state is preserved even when the list is filtered or sorted. +- **Stable keys** – Use a property that never changes (like a database primary key). Avoid `Math.random()` or array `index` for lists that can be reordered. +- **State preservation** – If a list item contains an input or local state, using a stable key ensures that state is preserved even when the list is filtered or sorted. - **Lazy item functions** – If an item is expensive to render, wrap it in a function: `() => ExpensiveComponent(item)`. The component is only created when the item actually appears in the DOM. --- @@ -151,7 +164,7 @@ const App = () => span(`${item.name} – $${item.price}`), button({ onClick: () => removeItem(item.id) }, "X") ]), - (item) => item.id + "id" ) ) ]); diff --git a/docs/api/fx.md b/docs/api/fx.md index 1c07ebe..855a74f 100644 --- a/docs/api/fx.md +++ b/docs/api/fx.md @@ -31,6 +31,8 @@ fx( **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 diff --git a/docs/api/global.md b/docs/api/global.md index d357ec4..c29dcc2 100644 --- a/docs/api/global.md +++ b/docs/api/global.md @@ -2,6 +2,8 @@ SigPro leverages the native power and efficiency of **signals** to create robust global stores with **zero complexity**. While other frameworks force you into heavy libraries and rigid boilerplate (Redux, Pinia, or Svelte stores), SigPro treats “the store” as a simple architectural choice: **defining a signal outside of a component.** +> **Availability:** `$` (and other core functions) are exported from the SigPro module. In **ESM** you must import them (`import { $ } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, `$` is automatically available on `window`. The examples below assume `$` is already in scope (via import or global). + ## Modular Organization (Zero Constraints) You are not restricted to a single `store.js`. You can organize your state by **feature**, **domain**, or **page**. Since a SigPro store is just a standard JavaScript module exporting signals, you can name your files whatever you like (`auth.js`, `cart.js`, `settings.js`) to keep your logic clean. @@ -12,7 +14,7 @@ Creating a dedicated file allows you to export only what you need. This modulari ```javascript // auth.js -import { $ } from 'sigpro'; // or just rely on global `$` after import +import { $ } from 'sigpro'; // A simple global signal export const user = $({ name: "Guest", loggedIn: false }); @@ -136,4 +138,4 @@ const TodoApp = () => ]); mount(TodoApp, "#app"); -``` +``` \ No newline at end of file diff --git a/docs/api/h.md b/docs/api/h.md index 9cc2295..812dbe0 100644 --- a/docs/api/h.md +++ b/docs/api/h.md @@ -2,6 +2,8 @@ The `h` function is the **core DOM builder** of SigPro. It creates DOM elements from a tag name, props, and children. While the global tag helpers (`div()`, `button()`, etc.) are built on top of `h`, you may need `h` directly for dynamic tag names or when you prefer an explicit function style. +> **Availability:** `h` and all tag helpers (`div`, `button`, etc.) are exported from the SigPro module. In **ESM** you must import them (`import { h, div, button } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, `h` and all tag helpers are automatically available on `window`. The examples below assume the functions are already in scope. + ## Function Signature ```typescript @@ -120,16 +122,16 @@ h('svg', { width: 100, height: 100 }, [ --- -## `h` vs Global Tag Helpers +## `h` vs Tag Helpers -| Feature | `h('div', ...)` | `div(...)` | +| Feature | `h('div', ...)` | `div(...)` (tag helper) | | :--- | :--- | :--- | | **Dynamic tag names** | ✅ `h(tagName, ...)` | ❌ Must know tag name at write time | | **Explicit style** | More verbose | Cleaner, DSL‑like | -| **Tree shaking** | Same | Same (helpers are generated once) | +| **Availability** | Import or global | Import or global (same) | | **Performance** | Identical | Identical (helpers call `h` internally) | -> **Recommendation:** Use global tag helpers (`div()`, `button()`, etc.) for most cases – they are shorter and more readable. Use `h` directly only when the tag name is dynamic (e.g., `h(props.tag, ...)`). +> **Recommendation:** Use tag helpers (`div()`, `button()`, etc.) for most cases – they are shorter and more readable. Use `h` directly only when the tag name is dynamic (e.g., `h(props.tag, ...)`). Remember that in ESM you need to import the helpers or call `sigpro()` to make them global. --- @@ -155,5 +157,5 @@ mount(App, '#app'); - `h` is the low‑level DOM builder used internally by all tag helpers. - It supports reactive attributes, reactive children, two‑way binding, event listeners, and SVG. -- Use `h` directly when you need a **dynamic tag name**; otherwise, prefer the convenient global helpers. -- Components written with `h` are fully reactive and automatically cleaned up. \ No newline at end of file +- Use `h` directly when you need a **dynamic tag name**; otherwise, prefer the convenient tag helpers (import them or inject globally). +- Components written with `h` are fully reactive and automatically cleaned up. diff --git a/docs/api/jsx.md b/docs/api/jsx.md index a0d71c6..fc9fffe 100644 --- a/docs/api/jsx.md +++ b/docs/api/jsx.md @@ -1,14 +1,3 @@ -Aquí tienes el archivo `h.md` actualizado, que ahora incluye: - -- La función `h` (hyperscript) -- Los helpers globales de etiquetas (lowercase) -- Una nueva sección sobre **JSX con SigPro** (configuración, ejemplos y alternativas como `htm`). - -El documento está en inglés, como los originales, y listo para integrarse en tu documentación. - ---- - -```markdown # Hyperscript & Tag Helpers SigPro provides two complementary ways to create DOM elements: @@ -318,6 +307,3 @@ mount(App, '#app'); | **`htm`** | Optional | `` html`
...
` `` | Buildless but HTML‑like syntax | > **Tip:** All approaches are fully reactive, support two‑way binding, events, SVG, and automatic cleanup. Choose the one that fits your workflow. -``` - -``` \ No newline at end of file diff --git a/docs/api/mount.md b/docs/api/mount.md index 0847dc5..0b03f6d 100644 --- a/docs/api/mount.md +++ b/docs/api/mount.md @@ -17,6 +17,8 @@ mount(component: Function | Node, target: string | HTMLElement): RuntimeObject - `container`: The actual DOM element created by the renderer. - `destroy()`: A method to completely unmount and clean up the application. +> **Availability:** `mount` is exported from the SigPro module. In **ESM** you must import it (`import { mount } 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 @@ -145,4 +147,4 @@ setTimeout(() => runtime.destroy(), 10000); | Manual destruction | `const app = mount(App, '#app'); app.destroy();` | | Auto‑replace on same target | Just call `mount` again – SigPro handles cleanup. | -> **Note:** The function name is `mount` (lowercase). It is exported from SigPro and also available globally after importing the library. The target must exist in the DOM at the time of mounting. \ No newline at end of file +> **Note:** The target must exist in the DOM at the time of mounting. \ No newline at end of file diff --git a/docs/api/quick.md b/docs/api/quick.md index 4deaa7c..1219568 100644 --- a/docs/api/quick.md +++ b/docs/api/quick.md @@ -1,10 +1,12 @@ -# ⚡ SigPro 1.2.18 – Complete API Reference +# ⚡ SigPro – Complete API Reference SigPro is a **Real‑DOM first** reactive micro‑framework. No virtual DOM, no diffing overhead – it updates the DOM directly with surgical precision. Built‑in 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 use globally as window.$ etc. +// 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 (` +- Or in ESM, call `sigpro()` after importing: `import { sigpro } from 'sigpro'; sigpro();` + +After that, you can write `div()`, `span()`, etc. directly, without any import. + 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`. --- @@ -128,8 +138,8 @@ Reactive conditional rendering. `condition` can be a boolean, a signal, or any f ```javascript when( () => user.loggedIn(), - () => Div({}, 'Welcome back!'), - () => Button({ onClick: () => login() }, 'Login') + () => div({}, 'Welcome back!'), + () => button({ onClick: () => login() }, 'Login') ) ``` @@ -152,19 +162,7 @@ When the array changes, elements are added, removed, or reordered with minimal D --- -## 💥 Effects & Lifecycle - -### `onUnmount(fn)` - -Inside a component (function called from `h`), registers a cleanup function that runs when that component is removed from the DOM. - -```javascript -const Timer = () => { - const interval = setInterval(() => console.log('tick'), 1000) - onUnmount(() => clearInterval(interval)) - return Div({}, 'Timer running') -} -``` +## 💥 Batch ### `batch(fn)` @@ -178,16 +176,6 @@ batch(() => { }) ``` -### `untrack(fn)` - -Run a function without tracking any signal reads. - -```javascript -const logCount = () => { - untrack(() => console.log('count is', count())) -} -``` - --- ## ✨ Animations – `fx(options, child)` @@ -218,14 +206,14 @@ Hash‑based SPA router. Returns a DOM node that renders the current route. ```javascript const routes = [ - { path: '/', component: () => Div({}, 'Home') }, - { path: '/user/:id', component: (params) => Div({}, `User ${params.id}`) }, - { path: '*', component: () => Div({}, '404') } + { 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'), +const App = () => div({}, [ + a({ href: '#/' }, 'Home'), + a({ href: '#/user/42' }, 'User 42'), router(routes) ]) ``` @@ -312,11 +300,11 @@ import { $, watch, h, 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') + div({ class: 'counter' }, [ + h1({}, () => `Count: ${count()}`), + button({ onClick: () => count(count() + 1) }, '+'), + button({ onClick: () => count(count() - 1) }, '-'), + button({ onClick: () => count(0) }, 'Reset') ]) mount(App, '#app') @@ -332,22 +320,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: +Or assign globally (after calling `sigpro()` or using the classic script): ```javascript window.myReactive = $ -``` - -All functions are also exposed on the global `window` object when included via ` + +``` + +### 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 + ``` --- -## 2. The Complete Global Registry +## 2. The Complete List of Tag Helpers -The following functions are injected into the global scope using **lowercase** names to match HTML tags: +All helpers are **lowercase** and follow HTML5 tag names. You can use them globally (after injection) or import them individually. -| Category | Available Global Functions | +| 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` | @@ -26,26 +51,24 @@ The following functions are injected into the global scope using **lowercase** n | **Tables** | `table`, `thead`, `tbody`, `tr`, `th`, `td`, `tfoot`, `caption` | | **Media** | `img`, `canvas`, `video`, `audio`, `svg`, `iframe`, `picture`, `source` | -Full list includes: `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 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`. --- ## 3. Usage Patterns -SigPro tag helpers are flexible. They automatically detect if you are passing attributes, children, or both. - ### A. Attributes + Children ```javascript div({ class: 'container', id: 'main' }, [ h1("Welcome to SigPro"), - p("The zero-VDOM framework.") + p("The zero‑VDOM framework.") ]); ``` ### B. Children Only -If you don't need attributes, you can pass the content directly as the first argument. +If you don't need attributes, pass the content directly as the first argument. ```javascript section([ @@ -74,7 +97,7 @@ div({ ### Two‑Way Binding (Automatic) -SigPro automatically bridges the **signal** and the **input element** bidirectionally when you assign a signal to `value` or `checked`. +Assign a **signal** directly to `value` or `checked` on form inputs – SigPro automatically bridges the signal and the input element bidirectionally. ```javascript const search = $(""); @@ -86,11 +109,11 @@ input({ }); ``` -> **Pro Tip:** If you want an input to be **read‑only** but still reactive, wrap the signal in an anonymous function: `value: () => search()`. This prevents backward synchronization. +> **Pro Tip:** To make an input **read‑only** 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 re‑executed whenever any signal inside changes, and the DOM will be patched surgically. +You can pass a **function as a child** – it will be re‑executed whenever any signal inside changes, and the DOM will be patched surgically. ```javascript const count = $(0); @@ -103,9 +126,9 @@ div([ --- -## 5. Custom Components with `h()` +## 5. Custom Components with `h()` or Tag Helpers -While the global tag helpers cover all standard HTML tags, you can create reusable components using the `h` function directly (or by returning the result of tag helpers). +While the tag helpers cover all standard HTML tags, you can create reusable components using them directly. ### Basic Component @@ -151,7 +174,7 @@ const Timer = () => { | Use case | Recommendation | | :--- | :--- | -| Standard tags (`div`, `span`, `button`) | Use global helpers: `div()`, `span()`, `button()` | +| 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`) | @@ -162,13 +185,17 @@ const Timer = () => { ## 7. Complete Example ```javascript +// In a modern ESM environment (recommended) +import { div, h1, input, p, button, mount, $ } from 'sigpro'; + +const nameSignal = $(''); + const App = () => div({ class: "app" }, [ h1("Welcome"), input({ placeholder: "Your name", - value: nameSignal, - onInput: (e) => nameSignal(e.target.value) + value: nameSignal }), p(() => `Hello, ${nameSignal() || "stranger"}!`), button({ onClick: () => alert("Clicked") }, "Click me") @@ -177,27 +204,41 @@ const App = () => mount(App, '#app'); ``` ---- +Or using the classic script (auto‑global): -
-
-

Important Notes

-
    -
  • Naming: All tag helpers are lowercase. There are no PascalCase helpers (Div, Button).
  • -
  • Global availability: After importing SigPro (via import 'sigpro' or CDN), all helpers are on window. You can use them anywhere without importing.
  • -
  • Custom components: Use PascalCase for your own component functions to visually distinguish them from built‑in tags (e.g., UserCard).
  • -
-
-
+```html + + +``` --- -## 8. Summary +## 8. Important Notes + +- **Naming:** All tag helpers are **lowercase** – no PascalCase helpers (`Div`, `Button`). +- **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. +- **Custom components:** Use **PascalCase** for your own component functions (e.g., `UserCard`) to visually distinguish them from built‑in tags. + +--- + +## 9. Summary | Feature | Description | | :--- | :--- | | **Tag helpers** | Lowercase functions for every HTML element (e.g., `div()`, `button()`). | +| **Availability** | Auto‑global in IIFE; in ESM use named imports or `sigpro()`. | | **Reactive attributes** | Pass a function to any attribute to keep it synced. | | **Two‑way binding** | Assign a signal directly to `value` or `checked` on form elements. | | **Dynamic children** | Pass a function as a child for live updating content. | -| **Auto‑cleanup** | All effects, events, and children are disposed when the element is removed. | \ No newline at end of file +| **Auto‑cleanup** | All effects, events, and children are disposed when the element is removed. | diff --git a/docs/api/watch.md b/docs/api/watch.md index 0813723..b92ec83 100644 --- a/docs/api/watch.md +++ b/docs/api/watch.md @@ -20,6 +20,8 @@ watch(deps: Signal[], callback: (values: any[]) => void): StopFunction **Returns:** A `StopFunction` that, when called, destroys the watcher and releases memory. +> **Availability:** `watch` is exported from the SigPro module. In **ESM** you must import it (`import { watch } 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 @@ -95,7 +97,7 @@ This is achieved via `queueMicrotask`, ensuring optimal performance. ## Key Points -- **Function name:** `watch` (lowercase) – exported from SigPro and also available globally. +- **Function name:** `watch` (lowercase) – exported from SigPro and also available globally (depending on environment). - **Auto mode:** `watch(fn)` – automatically tracks any signals read inside `fn`. - **Explicit mode:** `watch([sig1, sig2], (values) => {...})` – only re‑runs when listed signals change; callback receives an array of their new values. - **Stop function:** returned by both modes; call it to dispose the effect and its children. @@ -119,5 +121,4 @@ watch([count, step], ([newCount, newStep]) => { count(5); // logs: auto + explicit step(2); // logs: explicit only (auto does not track step) -``` - +``` \ No newline at end of file diff --git a/docs/api/when.md b/docs/api/when.md index 702f66c..aa6c0b4 100644 --- a/docs/api/when.md +++ b/docs/api/when.md @@ -20,7 +20,7 @@ when( **Returns:** A `div` with `style="display:contents"` that acts as an anchor for the dynamic content. This element is part of the DOM and will be replaced/updated automatically. -> **Note:** The function name is `when` (lowercase). It is exported from SigPro and also available globally after importing. +> **Availability:** `when` is exported from the SigPro module. In **ESM** you must import it (`import { when } 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. --- @@ -129,4 +129,4 @@ const App = () => ]); mount(App, '#app'); -``` +``` \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 10488a6..2e34b30 100644 --- a/docs/index.html +++ b/docs/index.html @@ -67,40 +67,5 @@ - diff --git a/docs/install.md b/docs/install.md index c543ee3..4831572 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,4 +1,4 @@ -# Installation & Setup (SigPro 1.2.18) +# Installation & Setup SigPro is designed to be drop-in ready. Whether you are building a complex application with a bundler or a simple reactive widget in a single HTML file, SigPro scales with your needs. @@ -42,14 +42,40 @@ bun add sigpro ``` +
```html +``` + +
+ + +
+ +```html + + + ``` @@ -63,31 +89,26 @@ bun add sigpro SigPro uses **lowercase** Tag Helpers (e.g., `div`, `button`) to keep the syntax close to raw HTML, while still being pure JavaScript functions.
- +
```javascript -// File: App.js -import 'sigpro'; // auto-installs globals +// App.js – Using named imports (recommended) +import { $, h1, button, div, mount } from 'sigpro'; export const App = () => { const count = $(0); - - // Tag helpers like div, h1, button are available globally (lowercase) return div({ class: "card p-4" }, [ h1(() => `Count is: ${count()}`), button( - { - class: "btn btn-primary", - onclick: () => count(count() + 1), - }, + { class: "btn btn-primary", onclick: () => count(count() + 1) }, "Increment" ), ]); }; -// File: main.js -import 'sigpro'; +// main.js +import { mount } from 'sigpro'; import { App } from './App.js'; mount(App, '#app'); @@ -104,23 +125,19 @@ mount(App, '#app');
- + @@ -132,26 +149,42 @@ mount(App, '#app'); --- -## 3. Global by Design +## 3. Global by Design (Two Modes) -One of SigPro's core strengths is its **Global API**, which eliminates "Import Hell" while remaining ESM-compatible. +SigPro gives you full control over global pollution. -- **The "Zero-Config" Import:** By simply adding `import 'sigpro'` (or importing from the CDN), the framework automatically "hydrates" the global `window` object. - - **Core Functions:** You get immediate access to `$`, `$$`, `watch`, `h`, `when`, `each`, `fx`, `router`, `req`, `mount`, `batch` anywhere in your scripts. - - **Auto-Installation:** This happens instantly upon import thanks to its built-in self‑installation, making it "Plug & Play" for both local projects and CDN usage. +### Mode A: Classic (IIFE) – Auto‑injection +When you load the **IIFE bundle** (`sigpro.js`) with a traditional `