diff --git a/docs/api/html.md b/docs/api/html.md index 50a7a0a..5744a5a 100644 --- a/docs/api/html.md +++ b/docs/api/html.md @@ -11,20 +11,36 @@ $html(tagName: string, props?: Object, children?: any[] | any): HTMLElement | Parameter | Type | Required | Description | | :--- | :--- | :--- | :--- | | **`tagName`** | `string` | Yes | Valid HTML tag name (e.g., `"div"`, `"button"`). | -| **`props`** | `Object` | No | HTML attributes, event listeners, and reactive bindings. | +| **`props`** | `Object` | No | Attributes, Events, Two-way bindings, and **Refs**. | | **`children`** | `any` | No | Nested elements, text strings, or reactive functions. | --- ## Key Features -### 1. Attribute Handling +### 1. Manual DOM Access: `ref` +The `ref` property allows you to capture the underlying `HTMLElement` as soon as it is created. This is essential for integrating 3rd-party libraries (like AG Grid or Chart.js) or managing focus and measurements. + +* **Callback Ref**: A function that receives the `HTMLElement` immediately. +* **Object Ref**: An object with a `.current` property assigned to the `HTMLElement`. + +```javascript +// Auto-focus on mount +Input({ ref: (el) => el.focus() }); + +// Capturing a node for an external library +const gridDiv = { current: null }; +Div({ ref: gridDiv, class: "ag-theme-quartz" }); +``` + +### 2. Attribute Handling SigPro intelligently decides how to apply each property: * **Standard Props**: Applied via `setAttribute` or direct property assignment. * **Class Names**: Supports `class` or `className` interchangeably. * **Boolean Props**: Automatic handling for `checked`, `disabled`, `hidden`, etc. +* **Note**: The `ref` property is intercepted and **never** rendered as an attribute in the HTML. -### 2. Event Listeners +### 3. Event Listeners Events are defined by the `on` prefix. SigPro automatically registers the listener and ensures it is cleaned up when the element is destroyed. ```javascript @@ -33,7 +49,7 @@ Button({ }, "Click Me"); ``` -### 3. Reactive Attributes (One-Way) +### 4. Reactive Attributes (One-Way) If an attribute value is a **function** (like a Signal), `$html` creates an internal **`$watch`** to keep the DOM in sync with the state. ```javascript @@ -43,11 +59,9 @@ Div({ }); ``` -### 4. Smart Two-Way Binding (Automatic) +### 5. Smart Two-Way Binding (Automatic) SigPro automatically enables **bidirectional synchronization** when it detects a **Signal** assigned to a form-capable attribute (`value` or `checked`) on an input element (`input`, `textarea`, `select`). - - ```javascript // Syncs input value <-> signal automatically Input({ @@ -55,10 +69,9 @@ Input({ value: username // No special symbols needed! }) ``` - > **Note:** To use a Signal as **read-only** in an input, wrap it in an anonymous function: `value: () => username()`. -### 5. Reactive Children +### 6. Reactive Children Children can be static or dynamic. When a child is a function, SigPro creates a reactive boundary using `$watch` for that specific part of the DOM. ```javascript @@ -80,7 +93,7 @@ Every element created with `$html` is "self-aware" regarding its reactive depend ## Tag Constructors (The Shortcuts) -Instead of writing `$html("div", ...)` every time, SigPro provides PascalCase global functions for all standard HTML tags: +Instead of writing `$html("div", ...)` every time, SigPro provides PascalCase global functions for all standard HTML tags. These are direct mappings to the `$html` factory. ```javascript // This: diff --git a/sigpro/sigpro.js b/sigpro/sigpro.js index 73e8ee0..d99e1e4 100644 --- a/sigpro/sigpro.js +++ b/sigpro/sigpro.js @@ -226,6 +226,10 @@ el._cleanups = new Set(); for (let [k, v] of Object.entries(props)) { + if (k === "ref") { + typeof v === "function" ? v(el) : (v.current = el); + continue; + } const isSignal = typeof v === "function"; const isInput = ["INPUT", "TEXTAREA", "SELECT"].includes(el.tagName); const isBindAttr = (k === "value" || k === "checked");