Include Fragment for JSX
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
This commit is contained in:
131
docs/api/jsx.md
131
docs/api/jsx.md
@@ -1,4 +1,4 @@
|
|||||||
# Hyperscript & Tag Helpers
|
# Hyperscript & Tag Helpers & JSX Style
|
||||||
|
|
||||||
SigPro provides two complementary ways to create DOM elements:
|
SigPro provides two complementary ways to create DOM elements:
|
||||||
|
|
||||||
@@ -9,135 +9,6 @@ Both are reactive, auto‑cleanup, and support SVG, events, two‑way binding, a
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## `h( )` – Hyperscript Function
|
|
||||||
|
|
||||||
The `h` function is the **core DOM builder** of SigPro. Use it directly when you need a dynamic tag name or prefer an explicit style.
|
|
||||||
|
|
||||||
### Function Signature
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
h(
|
|
||||||
tag: string | Function,
|
|
||||||
props?: object | Node | any[],
|
|
||||||
children?: any
|
|
||||||
): Node
|
|
||||||
```
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| **`tag`** | `string` or `Function` | HTML tag name (e.g., `"div"`) or a component function. |
|
|
||||||
| **`props`** | `object` | Optional. Attributes, event handlers, refs, etc. |
|
|
||||||
| **`children`** | `any` | Optional. Text, nodes, arrays, or reactive functions. |
|
|
||||||
|
|
||||||
**Returns:** A DOM node (or array of nodes when the tag is a component that returns an array).
|
|
||||||
|
|
||||||
### Usage Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
// Basic element
|
|
||||||
h('div', {}, 'Hello world');
|
|
||||||
|
|
||||||
// With attributes and events
|
|
||||||
h('button', { class: 'btn', onclick: () => alert('clicked') }, 'Click me');
|
|
||||||
|
|
||||||
// Nested children
|
|
||||||
h('div', { class: 'container' }, [
|
|
||||||
h('h1', {}, 'Title'),
|
|
||||||
h('p', {}, 'Paragraph')
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Reactive child (function)
|
|
||||||
const count = $(0);
|
|
||||||
h('div', {}, [
|
|
||||||
h('p', {}, () => `Count: ${count()}`),
|
|
||||||
h('button', { onclick: () => count(count() + 1) }, '+1')
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Reactive attribute
|
|
||||||
const theme = $('dark');
|
|
||||||
h('div', { class: () => `box ${theme()}` }, 'Themed box');
|
|
||||||
|
|
||||||
// Two-way binding on input
|
|
||||||
const name = $('');
|
|
||||||
h('input', { type: 'text', value: name, placeholder: 'Your name' });
|
|
||||||
h('p', {}, () => `Hello, ${name()}`);
|
|
||||||
|
|
||||||
// Component as tag
|
|
||||||
const Button = (props, { children }) =>
|
|
||||||
h('button', { class: 'btn', onclick: props.onClick }, children);
|
|
||||||
|
|
||||||
h(Button, { onClick: () => alert('clicked') }, 'Click me');
|
|
||||||
|
|
||||||
// SVG (auto-namespace)
|
|
||||||
h('svg', { width: 100, height: 100 }, [
|
|
||||||
h('circle', { cx: 50, cy: 50, r: 40, fill: 'red' })
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Special Props
|
|
||||||
|
|
||||||
| Prop | Behaviour |
|
|
||||||
| :--- | :--- |
|
|
||||||
| **`ref`** | `ref: (el) => ...` or `ref: { current: null }` – direct DOM node access. |
|
|
||||||
| **`onEvent`** | Any prop starting with `on` (e.g., `onClick`) is an event listener – auto‑removed on cleanup. |
|
|
||||||
| **`value` / `checked`** | When a signal is passed, creates two‑way binding for form elements. |
|
|
||||||
| **`class`** | Use `class` (not `className`). Accepts a string or reactive function. |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Global Tag Helpers (Lowercase)
|
|
||||||
|
|
||||||
When you import SigPro (either via `import 'sigpro'` or the CDN), it automatically injects a helper function for **every standard HTML tag** directly onto `window`. These helpers are **lowercase** and work exactly like `h`, but with a cleaner syntax.
|
|
||||||
|
|
||||||
### Available Helpers
|
|
||||||
|
|
||||||
All standard HTML5 tags: `div`, `span`, `p`, `section`, `nav`, `header`, `footer`, `h1`…`h6`, `ul`, `ol`, `li`, `button`, `a`, `input`, `form`, `table`, `svg`, `circle`, etc.
|
|
||||||
|
|
||||||
### Usage Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
// Instead of h('div', ...)
|
|
||||||
div({ class: 'container' }, 'Content');
|
|
||||||
|
|
||||||
// Children only (skip props)
|
|
||||||
section([
|
|
||||||
h2('Title'),
|
|
||||||
p('Paragraph')
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Reactive attribute
|
|
||||||
const theme = $('light');
|
|
||||||
div({ class: () => `app-${theme()}` }, 'Themed');
|
|
||||||
|
|
||||||
// Two-way binding
|
|
||||||
const search = $('');
|
|
||||||
input({ type: 'text', value: search, placeholder: 'Search...' });
|
|
||||||
p(() => `You typed: ${search()}`);
|
|
||||||
|
|
||||||
// Dynamic children
|
|
||||||
const count = $(0);
|
|
||||||
div([
|
|
||||||
p(() => `Count: ${count()}`),
|
|
||||||
button({ onClick: () => count(count() + 1) }, '+1')
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Complete Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
const App = () =>
|
|
||||||
div({ class: 'app' }, [
|
|
||||||
h1('Welcome'),
|
|
||||||
input({ value: name, placeholder: 'Your name' }),
|
|
||||||
p(() => `Hello, ${name() || 'stranger'}!`),
|
|
||||||
button({ onClick: () => alert('Hi') }, 'Click me')
|
|
||||||
]);
|
|
||||||
|
|
||||||
mount(App, '#app');
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## JSX with SigPro
|
## JSX with SigPro
|
||||||
|
|
||||||
SigPro works seamlessly with JSX. You can use JSX as a compile‑time syntax sugar for `h` calls.
|
SigPro works seamlessly with JSX. You can use JSX as a compile‑time syntax sugar for `h` calls.
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ When you use the **IIFE bundle** (`sigpro.js` or `sigpro.min.js`) with a traditi
|
|||||||
```
|
```
|
||||||
|
|
||||||
### B. ESM (Modern JavaScript) – Explicit Activation
|
### 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 side‑effect module:
|
**ES module** (`import { ... } from 'sigpro'`) or full `import 'sigpro'`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import 'sigpro';
|
import 'sigpro';
|
||||||
@@ -38,7 +38,6 @@ import 'sigpro';
|
|||||||
const App = () => div({ class: "app" }, "Ready!");
|
const App = () => div({ class: "app" }, "Ready!");
|
||||||
```
|
```
|
||||||
|
|
||||||
> **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 side‑effect runs.
|
|
||||||
> If you prefer to avoid globals, you can always use `h('div', ...)` directly—it’s perfectly fine.
|
> If you prefer to avoid globals, you can always use `h('div', ...)` directly—it’s perfectly fine.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sigpro",
|
"name": "sigpro",
|
||||||
"version": "1.2.28",
|
"version": "1.2.30",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": {
|
"author": {
|
||||||
|
|||||||
@@ -497,6 +497,8 @@ router.to = p => window.location.hash = p.replace(/^#?\/?/, "#/")
|
|||||||
router.back = () => window.history.back()
|
router.back = () => window.history.back()
|
||||||
router.path = () => window.location.hash.replace(/^#/, "") || "/"
|
router.path = () => window.location.hash.replace(/^#/, "") || "/"
|
||||||
|
|
||||||
|
const Fragment = (props) => props.children;
|
||||||
|
|
||||||
const mount = (comp, target) => {
|
const mount = (comp, target) => {
|
||||||
const t = typeof target === "string" ? doc.querySelector(target) : target
|
const t = typeof target === "string" ? doc.querySelector(target) : target
|
||||||
if (!t) return
|
if (!t) return
|
||||||
@@ -508,10 +510,10 @@ const mount = (comp, target) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
Object.assign(window, { $, $$, watch, h, when, each, router, mount, batch, onUnmount, isArr, isFunc, isObj })
|
Object.assign(window, { $, $$, watch, h, Fragment, when, each, router, mount, batch, onUnmount, isArr, isFunc, isObj })
|
||||||
"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 h2 h3 h4 h5 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"
|
"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 h2 h3 h4 h5 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"
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.forEach(tag => { window[tag] = (props, children) => h(tag, props, children) })
|
.forEach(tag => { window[tag] = (props, children) => h(tag, props, children) })
|
||||||
}
|
}
|
||||||
|
|
||||||
export { $, $$, watch, batch, h, mount, when, each, router, onUnmount, isArr, isFunc, isObj }
|
export { $, $$, watch, batch, h, Fragment, mount, when, each, router, onUnmount, isArr, isFunc, isObj }
|
||||||
Reference in New Issue
Block a user