Update new version
This commit is contained in:
@@ -40,13 +40,13 @@ export default defineConfig({
|
||||
text: 'API Reference',
|
||||
items: [
|
||||
{ text: 'Quick Start', link: '/api/quick' },
|
||||
{ text: '$', link: '/api/signal' },
|
||||
{ text: '$.watch', link: '/api/watch' },
|
||||
{ text: '$.if', link: '/api/if' },
|
||||
{ text: '$.for', link: '/api/for' },
|
||||
{ text: '$.router', link: '/api/router' },
|
||||
{ text: '$.mount', link: '/api/mount' },
|
||||
{ text: '$.html', link: '/api/html' },
|
||||
{ text: '$ signals', link: '/api/signal' },
|
||||
{ text: '$watch', link: '/api/watch' },
|
||||
{ text: '$if', link: '/api/if' },
|
||||
{ text: '$for', link: '/api/for' },
|
||||
{ text: '$router', link: '/api/router' },
|
||||
{ text: '$mount', link: '/api/mount' },
|
||||
{ text: '$html', link: '/api/html' },
|
||||
{ text: 'Tags', link: '/api/tags' },
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# ♻️ Reactive Lists: `$.for( )`
|
||||
# ♻️ Reactive Lists: `$for( )`
|
||||
|
||||
The `$.for` function is a high-performance list renderer. It maps an array (or a Signal containing an array) to DOM nodes. Unlike a simple `.map()`, `$.for` is **keyed**, meaning it only updates, moves, or deletes the specific items that changed.
|
||||
The `$for` function is a high-performance list renderer. It maps an array (or a Signal containing an array) to DOM nodes. Unlike a simple `.map()`, `$for` is **keyed**, meaning it only updates, moves, or deletes the specific items that changed.
|
||||
|
||||
## 🛠️ Function Signature
|
||||
|
||||
```typescript
|
||||
$.for(
|
||||
$for(
|
||||
source: Signal<any[]> | Function | any[],
|
||||
render: (item: any, index: number) => HTMLElement,
|
||||
keyFn: (item: any, index: number) => string | number
|
||||
@@ -34,7 +34,7 @@ const users = $([
|
||||
]);
|
||||
|
||||
Ul({ class: "list" }, [
|
||||
$.for(users,
|
||||
$for(users,
|
||||
(user) => Li({ class: "p-2" }, user.name),
|
||||
(user) => user.id
|
||||
)
|
||||
@@ -48,7 +48,7 @@ If your array contains simple strings or numbers, you can use the value itself o
|
||||
const tags = $(["Tech", "JS", "Web"]);
|
||||
|
||||
Div({ class: "flex gap-1" }, [
|
||||
$.for(tags, (tag) => Badge(tag), (tag) => tag)
|
||||
$for(tags, (tag) => Badge(tag), (tag) => tag)
|
||||
]);
|
||||
```
|
||||
|
||||
@@ -56,7 +56,7 @@ Div({ class: "flex gap-1" }, [
|
||||
|
||||
## 🏗️ How it Works (The Reconciliation)
|
||||
|
||||
When the `source` signal changes, `$.for` performs the following steps:
|
||||
When the `source` signal changes, `$for` performs the following steps:
|
||||
|
||||
1. **Key Diffing**: It compares the new keys with the previous ones stored in an internal `Map`.
|
||||
2. **Node Reuse**: If a key already exists, the DOM node is **reused** and moved to its new position. No new elements are created.
|
||||
@@ -69,13 +69,13 @@ When the `source` signal changes, `$.for` performs the following steps:
|
||||
## 💡 Performance Tips
|
||||
|
||||
* **Stable Keys**: Never use `Math.random()` as a key. This will force SigPro to destroy and recreate the entire list on every update, killing performance.
|
||||
* **Component Encapsulation**: If each item in your list has its own complex internal state, `$.for` ensures that state is preserved even if the list is reordered, as long as the key remains the same.
|
||||
* **Component Encapsulation**: If each item in your list has its own complex internal state, `$for` ensures that state is preserved even if the list is reordered, as long as the key remains the same.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Summary Comparison
|
||||
|
||||
| Feature | Standard `Array.map` | SigPro `$.for` |
|
||||
| Feature | Standard `Array.map` | SigPro `$for` |
|
||||
| :--- | :--- | :--- |
|
||||
| **Re-render** | Re-renders everything | Only updates changes |
|
||||
| **DOM Nodes** | Re-created every time | **Reused via Keys** |
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# 🏗️ The DOM Factory: `$.html( )`
|
||||
# 🏗️ The DOM Factory: `$html( )`
|
||||
|
||||
`$.html` is the internal engine that creates, attributes, and attaches reactivity to DOM elements. It uses `$.watch` to maintain a live, high-performance link between your Signals and the Document Object Model.
|
||||
`$html` is the internal engine that creates, attributes, and attaches reactivity to DOM elements. It uses `$.watch` to maintain a live, high-performance link between your Signals and the Document Object Model.
|
||||
|
||||
## 🛠 Function Signature
|
||||
|
||||
```typescript
|
||||
$.html(tagName: string, props?: Object, children?: any[] | any): HTMLElement
|
||||
$html(tagName: string, props?: Object, children?: any[] | any): HTMLElement
|
||||
```
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
@@ -34,7 +34,7 @@ Button({
|
||||
```
|
||||
|
||||
### 3. 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.
|
||||
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
|
||||
Div({
|
||||
@@ -72,7 +72,7 @@ Div({}, [
|
||||
---
|
||||
|
||||
## 🧹 Memory Management (Internal)
|
||||
Every element created with `$.html` is "self-aware" regarding its reactive dependencies.
|
||||
Every element created with `$html` is "self-aware" regarding its reactive dependencies.
|
||||
* **`._cleanups`**: A hidden `Set` attached to the element that stores all `stop()` functions from its internal `$.watch` calls and event listeners.
|
||||
* **Lifecycle**: When an element is removed by a Controller (`$.if`, `$.for`, or `$.router`), SigPro performs a recursive **"sweep"** to execute these cleanups, ensuring **zero memory leaks**.
|
||||
|
||||
@@ -80,12 +80,12 @@ Every element created with `$.html` is "self-aware" regarding its reactive depen
|
||||
|
||||
## 💡 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:
|
||||
|
||||
```javascript
|
||||
// This:
|
||||
Div({ class: "wrapper" }, [ Span("Hello") ])
|
||||
|
||||
// Is exactly equivalent to:
|
||||
$.html("div", { class: "wrapper" }, [ $.html("span", {}, "Hello") ])
|
||||
$html("div", { class: "wrapper" }, [ $html("span", {}, "Hello") ])
|
||||
```
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
# 🔀 Reactive Branching: `$.if( )`
|
||||
# 🔀 Reactive Branching: `$if( )`
|
||||
|
||||
The `$.if` function is a reactive control flow operator. It manages the conditional rendering of components, ensuring that only the active branch exists in the DOM and in memory.
|
||||
The `$if` function is a reactive control flow operator. It manages the conditional rendering of components, ensuring that only the active branch exists in the DOM and in memory.
|
||||
|
||||
## 🛠️ Function Signature
|
||||
|
||||
```typescript
|
||||
$.if(
|
||||
$if(
|
||||
condition: Signal<boolean> | Function,
|
||||
thenVal: Component | Node,
|
||||
otherwiseVal?: Component | Node
|
||||
@@ -34,7 +34,7 @@ const isVisible = $(false);
|
||||
Div([
|
||||
Button({ onclick: () => isVisible(!isVisible()) }, "Toggle Message"),
|
||||
|
||||
$.if(isVisible,
|
||||
$if(isVisible,
|
||||
P("Now you see me!"),
|
||||
P("Now you don't...")
|
||||
)
|
||||
@@ -42,10 +42,10 @@ Div([
|
||||
```
|
||||
|
||||
### 2. Lazy Component Loading
|
||||
Unlike using a hidden class (CSS `display: none`), `$.if` is **lazy**. The branch that isn't active **is never created**. This saves memory and initial processing time.
|
||||
Unlike using a hidden class (CSS `display: none`), `$if` is **lazy**. The branch that isn't active **is never created**. This saves memory and initial processing time.
|
||||
|
||||
```javascript
|
||||
$.if(() => user.isLogged(),
|
||||
$if(() => user.isLogged(),
|
||||
() => Dashboard(), // Only executed if logged in
|
||||
() => LoginGate() // Only executed if guest
|
||||
)
|
||||
@@ -55,7 +55,7 @@ $.if(() => user.isLogged(),
|
||||
|
||||
## 🧹 Automatic Cleanup
|
||||
|
||||
One of the core strengths of `$.if` is its integrated **Cleanup** logic. SigPro ensures that when a branch is swapped out, it is completely purged.
|
||||
One of the core strengths of `$if` is its integrated **Cleanup** logic. SigPro ensures that when a branch is swapped out, it is completely purged.
|
||||
|
||||
1. **Stop Watchers**: All `$.watch` calls inside the inactive branch are permanently stopped.
|
||||
2. **Unbind Events**: Event listeners attached via `$.html` are removed.
|
||||
@@ -70,7 +70,7 @@ One of the core strengths of `$.if` is its integrated **Cleanup** logic. SigPro
|
||||
* **Function Wrappers**: If your branches are heavy (e.g., they contain complex components), wrap them in a function `() => MyComponent()`. This prevents the component from being initialized until the condition actually meets its requirement.
|
||||
* **Logical Expressions**: You can pass a complex computed function as the condition:
|
||||
```javascript
|
||||
$.if(() => count() > 10 && status() === 'ready',
|
||||
$if(() => count() > 10 && status() === 'ready',
|
||||
Span("Threshold reached!")
|
||||
)
|
||||
```
|
||||
@@ -79,7 +79,7 @@ One of the core strengths of `$.if` is its integrated **Cleanup** logic. SigPro
|
||||
|
||||
## 🏗️ Technical Comparison
|
||||
|
||||
| Feature | Standard CSS `hidden` | SigPro `$.if` |
|
||||
| Feature | Standard CSS `hidden` | SigPro `$if` |
|
||||
| :--- | :--- | :--- |
|
||||
| **DOM Presence** | Always present | Only if active |
|
||||
| **Reactivity** | Still processing in background | **Paused/Destroyed** |
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# 🔌 Application Mounter: `$.mount( )`
|
||||
# 🔌 Application Mounter: `$mount( )`
|
||||
|
||||
The `$.mount` function is the entry point of your reactive world. It bridges the gap between your SigPro logic and the browser's Real DOM by injecting a component into the document and initializing its reactive lifecycle.
|
||||
The `$mount` function is the entry point of your reactive world. It bridges the gap between your SigPro logic and the browser's Real DOM by injecting a component into the document and initializing its reactive lifecycle.
|
||||
|
||||
## 🛠️ Function Signature
|
||||
|
||||
```typescript
|
||||
$.mount(node: Function | HTMLElement, target?: string | HTMLElement): RuntimeObject
|
||||
$mount(node: Function | HTMLElement, target?: string | HTMLElement): RuntimeObject
|
||||
```
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
@@ -27,7 +27,7 @@ import { $ } from './sigpro.js';
|
||||
import App from './App.js';
|
||||
|
||||
// Mounts your main App component
|
||||
$.mount(App, '#app-root');
|
||||
$mount(App, '#app-root');
|
||||
```
|
||||
|
||||
### 2. Reactive "Islands"
|
||||
@@ -42,17 +42,17 @@ const Counter = () => {
|
||||
};
|
||||
|
||||
// Mount only the counter into a specific sidebar div
|
||||
$.mount(Counter, '#sidebar-widget');
|
||||
$mount(Counter, '#sidebar-widget');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 How it Works (Lifecycle & Cleanup)
|
||||
|
||||
When `$.mount` is executed, it performs these critical steps to ensure a leak-free environment:
|
||||
When `$mount` is executed, it performs these critical steps to ensure a leak-free environment:
|
||||
|
||||
1. **Duplicate Detection**: If you call `$.mount` on a target that already has a SigPro instance, it automatically calls `.destroy()` on the previous instance. This prevents "Zombie Effects" from stacking in memory.
|
||||
2. **Internal Scoping**: It executes the component function inside an internal **Reactive Owner**. This captures every `$.watch` and event listener created during the render.
|
||||
1. **Duplicate Detection**: If you call `$mount` on a target that already has a SigPro instance, it automatically calls `.destroy()` on the previous instance. This prevents "Zombie Effects" from stacking in memory.
|
||||
2. **Internal Scoping**: It executes the component function inside an internal **Reactive Owner**. This captures every `$watch` and event listener created during the render.
|
||||
3. **Target Injection**: It clears the target using `replaceChildren()` and appends the new component.
|
||||
4. **Runtime Creation**: It returns a control object:
|
||||
* `container`: The actual DOM element created.
|
||||
@@ -62,10 +62,10 @@ When `$.mount` is executed, it performs these critical steps to ensure a leak-fr
|
||||
|
||||
## 🛑 Manual Unmounting
|
||||
|
||||
While SigPro handles most cleanups automatically (via `$.If`, `$.For`, and `$.router`), you can manually destroy any mounted instance. This is vital for imperatively managed UI like **Toasts** or **Modals**.
|
||||
While SigPro handles most cleanups automatically (via `$if`, `$for`, and `$router`), you can manually destroy any mounted instance. This is vital for imperatively managed UI like **Toasts** or **Modals**.
|
||||
|
||||
```javascript
|
||||
const instance = $.mount(MyToast, '#toast-container');
|
||||
const instance = $mount(MyToast, '#toast-container');
|
||||
|
||||
// Later, to remove the toast and kill its reactivity:
|
||||
instance.destroy();
|
||||
@@ -77,9 +77,9 @@ instance.destroy();
|
||||
|
||||
| Goal | Code Pattern |
|
||||
| :--- | :--- |
|
||||
| **Mount to body** | `$.mount(App)` |
|
||||
| **Mount to CSS Selector** | `$.mount(App, '#root')` |
|
||||
| **Mount to DOM Node** | `$.mount(App, myElement)` |
|
||||
| **Clean & Re-mount** | Calling `$.mount` again on the same target |
|
||||
| **Total Cleanup** | `const app = $.mount(App); app.destroy();` |
|
||||
| **Mount to body** | `$mount(App)` |
|
||||
| **Mount to CSS Selector** | `$mount(App, '#root')` |
|
||||
| **Mount to DOM Node** | `$mount(App, myElement)` |
|
||||
| **Clean & Re-mount** | Calling `$mount` again on the same target |
|
||||
| **Total Cleanup** | `const app = $mount(App); app.destroy();` |
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ SigPro is a high-performance micro-framework that updates the **Real DOM** surgi
|
||||
| :--- | :--- | :--- |
|
||||
| **`$(val, key?)`** | `(any, string?) => Signal` | Creates a **Signal**. If `key` is provided, it persists in `localStorage`. |
|
||||
| **`$(fn)`** | `(function) => Computed` | Creates a **Computed Signal** that auto-updates when its dependencies change. |
|
||||
| **`$.watch(fn)`** | `(function) => stopFn` | **Automatic Mode:** Tracks any signal touched inside. Returns a stop function. |
|
||||
| **`$.watch(deps, fn)`** | `(Array, function) => stopFn` | **Explicit Mode:** Only runs when signals in `deps` change. Used for Cleanup. |
|
||||
| **`$.html(tag, props, kids)`** | `(string, obj, any) => Element` | The low-level DOM factory. Attaches `._cleanups` to every element. |
|
||||
| **`$.if(cond, then, else?)`** | `(Signal, fn, fn?) => Node` | Reactive conditional. Automatically destroys the "else" branch memory. |
|
||||
| **`$.for(list, itemFn)`** | `(Signal, fn) => Node` | Optimized list renderer. Manages individual item lifecycles. |
|
||||
| **`$.router(routes)`** | `(Array) => Element` | Hash-based SPA router. Uses Explicit Watch to prevent memory leaks. |
|
||||
| **`$.mount(node, target)`** | `(any, string\|Node) => Runtime` | Entry point. Creates a root instance with `.destroy()` capabilities. |
|
||||
| **`$watch(fn)`** | `(function) => stopFn` | **Automatic Mode:** Tracks any signal touched inside. Returns a stop function. |
|
||||
| **`$watch(deps, fn)`** | `(Array, function) => stopFn` | **Explicit Mode:** Only runs when signals in `deps` change. Used for Cleanup. |
|
||||
| **`$html(tag, props, kids)`** | `(string, obj, any) => Element` | The low-level DOM factory. Attaches `._cleanups` to every element. |
|
||||
| **`$if(cond, then, else?)`** | `(Signal, fn, fn?) => Node` | Reactive conditional. Automatically destroys the "else" branch memory. |
|
||||
| **`$for(list, itemFn)`** | `(Signal, fn) => Node` | Optimized list renderer. Manages individual item lifecycles. |
|
||||
| **`$router(routes)`** | `(Array) => Element` | Hash-based SPA router. Uses Explicit Watch to prevent memory leaks. |
|
||||
| **`$mount(node, target)`** | `(any, string\|Node) => Runtime` | Entry point. Creates a root instance with `.destroy()` capabilities. |
|
||||
|
||||
---
|
||||
|
||||
@@ -32,7 +32,7 @@ Tag({ attributes }, [children])
|
||||
| Pattern | Code Example | Behavior |
|
||||
| :--- | :--- | :--- |
|
||||
| **Static** | `class: "text-red"` | Standard HTML attribute string. |
|
||||
| **Reactive** | `disabled: isLoading` | Updates automatically via internal `$.watch`. |
|
||||
| **Reactive** | `disabled: isLoading` | Updates automatically via internal `$watch`. |
|
||||
| **Two-way** | `$value: username` | **Binding Operator**: Syncs input $\leftrightarrow$ signal both ways. |
|
||||
| **Text** | `P({}, () => count())` | Updates text node surgically without re-rendering the `P`. |
|
||||
| **Boolean** | `hidden: isHidden` | Toggles the attribute based on signal truthiness. |
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
# 🚦 Routing: `$.router( )` & `$.go( )`
|
||||
# 🚦 Routing: `$router()` & Utilities
|
||||
|
||||
SigPro includes a built-in, lightweight **Hash Router** to create Single Page Applications (SPA). It manages the URL state, matches components to paths, and handles the lifecycle of your pages automatically.
|
||||
|
||||
## 🛠 Router Signature
|
||||
|
||||
```typescript
|
||||
$.router(routes: Route[]): HTMLElement
|
||||
$router(routes: Route[]): HTMLElement
|
||||
```
|
||||
|
||||
### Route Object
|
||||
| Property | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| **`path`** | `string` | The URL fragment (e.g., `"/home"`, `"/user/:id"`, or `"*"`). |
|
||||
| **`component`** | `Function` | A function that returns a Tag or a `$.view`. |
|
||||
| **`path`** | `string` | The URL fragment (e.g., `"/"`, `"/user/:id"`, or `"*"`). |
|
||||
| **`component`** | `Function` | A function that returns a Node, a String, or a reactive View. |
|
||||
|
||||
---
|
||||
|
||||
## 📖 Usage Patterns
|
||||
|
||||
### 1. Defining Routes
|
||||
The router returns a `div` element with the class `.router-outlet`. When the hash changes, the router destroys the previous view and mounts the new one inside this container.
|
||||
The `$router` returns a `div` element with the class `.router-outlet`. When the hash changes, the router destroys the previous view and mounts the new one inside this container.
|
||||
|
||||
```javascript
|
||||
const App = () => Div({ class: "app-layout" }, [
|
||||
Navbar(),
|
||||
// The router outlet is placed here
|
||||
$.router([
|
||||
$router([
|
||||
{ path: "/", component: Home },
|
||||
{ path: "/profile/:id", component: UserProfile },
|
||||
{ path: "*", component: NotFound }
|
||||
{ path: "/profile/:id", component: (params) => UserProfile(params.id) },
|
||||
{ path: "*", component: () => H1("404 Not Found") }
|
||||
])
|
||||
]);
|
||||
```
|
||||
|
||||
### 2. Dynamic Segments (`:id`)
|
||||
When a path contains a colon (e.g., `:id`), the router parses that segment and passes it as an object to the component function.
|
||||
The router automatically parses URL parameters (like `:id`) and passes them as an object to the component function. You can also access them globally via `$router.params()`.
|
||||
|
||||
```javascript
|
||||
// If the URL is #/profile/42
|
||||
@@ -45,43 +45,52 @@ const UserProfile = (params) => {
|
||||
|
||||
---
|
||||
|
||||
## 🏎 Programmatic Navigation: `$.go( )`
|
||||
## 🏎 Navigation Utilities
|
||||
|
||||
To navigate between pages without using an `<a>` tag, use `$.go`. This function updates the browser's hash, which in turn triggers the router to swap components.
|
||||
SigPro provides a set of programmatic methods to control the history and read the state.
|
||||
|
||||
### Signature
|
||||
```typescript
|
||||
$.go(path: string): void
|
||||
### `$router.to(path)`
|
||||
Navigates to a specific path. It automatically formats the hash (e.g., `/home` becomes `#/home`).
|
||||
```javascript
|
||||
Button({ onclick: () => $router.to("/dashboard") }, "Go to Dashboard")
|
||||
```
|
||||
|
||||
### Examples
|
||||
### `$router.back()`
|
||||
Goes back to the previous page in the browser history.
|
||||
```javascript
|
||||
// Navigate to a static path
|
||||
Button({ onclick: () => $.go("/") }, "Home")
|
||||
Button({ onclick: () => $router.back() }, "Back")
|
||||
```
|
||||
|
||||
// Navigate to a dynamic path
|
||||
Button({
|
||||
onclick: () => $.go(`/profile/${user.id}`)
|
||||
}, "View Profile")
|
||||
### `$router.path()`
|
||||
Returns the current path (without the `#`).
|
||||
```javascript
|
||||
$watch(() => {
|
||||
console.log("Current path is:", $router.path());
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Technical Behavior
|
||||
|
||||
* **Automatic Cleanup**: Every time you navigate, the router calls `.destroy()` on the previous `$.view`. This ensures that all **signals, effects, and event listeners** from the old page are purged from memory.
|
||||
* **Automatic Cleanup**: Every time you navigate, the router calls `.destroy()` on the previous view. This ensures that all **signals, effects, and event listeners** from the old page are purged from memory.
|
||||
* **Reactive Params**: `$router.params` is a signal (`$`). You can react to parameter changes without re-mounting the entire router outlet.
|
||||
* **Hash-Based**: By using `window.location.hash`, SigPro works out-of-the-box on any static hosting (like GitHub Pages or Vercel) without needing server-side redirects.
|
||||
* **Initial Load**: On the first execution, `$.router` automatically reads the current hash or defaults to `/` if empty.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Styling the Outlet
|
||||
Since the router returns a standard DOM element, you can style the transition or the container easily:
|
||||
The router returns a standard `div` with the `.router-outlet` class. You can easily style it or add transitions:
|
||||
|
||||
```css
|
||||
.router-outlet {
|
||||
flex: 1;
|
||||
padding: 2rem;
|
||||
animation: fadeIn 0.2s ease-in;
|
||||
display: block;
|
||||
min-height: 100vh;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
```
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
```
|
||||
@@ -1,12 +1,12 @@
|
||||
# 🎨 Global Tag Helpers
|
||||
|
||||
In **SigPro**, you don't need to manually type `$.html('div', ...)` for every element. To keep your code declarative and readable, the engine automatically generates **Global Helper Functions** for all standard HTML5 tags upon initialization.
|
||||
In **SigPro**, you don't need to manually type `$html('div', ...)` for every element. To keep your code declarative and readable, the engine automatically generates **Global Helper Functions** for all standard HTML5 tags upon initialization.
|
||||
|
||||
## 1. How it Works
|
||||
|
||||
SigPro iterates through a manifest of standard HTML tags and attaches a wrapper function for each one directly to the `window` object. This creates a specialized **DSL** (Domain Specific Language) that looks like a template engine but is **100% standard JavaScript**.
|
||||
|
||||
* **Under the hood:** `$.html('button', { onclick: ... }, 'Click')`
|
||||
* **Under the hood:** `$html('button', { onclick: ... }, 'Click')`
|
||||
* **SigPro Style:** `Button({ onclick: ... }, 'Click')`
|
||||
|
||||
---
|
||||
@@ -51,10 +51,10 @@ Section([
|
||||
|
||||
## 4. Reactive Power
|
||||
|
||||
These helpers are natively wired into SigPro's **`$.watch`** engine.
|
||||
These helpers are natively wired into SigPro's **`$watch`** engine.
|
||||
|
||||
### Reactive Attributes (One-Way)
|
||||
Simply pass a Signal (function) to any attribute. SigPro creates an internal `$.watch` to keep the DOM in sync.
|
||||
Simply pass a Signal (function) to any attribute. SigPro creates an internal `$watch` to keep the DOM in sync.
|
||||
```javascript
|
||||
const theme = $("light");
|
||||
|
||||
@@ -80,12 +80,12 @@ 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 the "backwards" synchronization.
|
||||
|
||||
### Dynamic Flow & Cleanup
|
||||
Combine tags with Core controllers. SigPro automatically cleans up the `$.watch` instances and event listeners when nodes are removed from the DOM.
|
||||
Combine tags with Core controllers. SigPro automatically cleans up the `$watch` instances and event listeners when nodes are removed from the DOM.
|
||||
```javascript
|
||||
const items = $(["Apple", "Banana", "Cherry"]);
|
||||
|
||||
Ul({ class: "list-disc" }, [
|
||||
$.for(items, (item) => Li(item), (item) => item)
|
||||
$for(items, (item) => Li(item), (item) => item)
|
||||
]);
|
||||
```
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# ⚡ Reactivity Control: `$.watch( )`
|
||||
# ⚡ Reactivity Control: `$watch( )`
|
||||
|
||||
The `$.watch` function is the reactive engine of SigPro. It allows you to execute code automatically when signals change. `$.watch` is **polymorphic**: it can track dependencies automatically or follow an explicit list.
|
||||
The `$watch` function is the reactive engine of SigPro. It allows you to execute code automatically when signals change. `$watch` is **polymorphic**: it can track dependencies automatically or follow an explicit list.
|
||||
|
||||
## 🛠 Function Signature
|
||||
|
||||
```typescript
|
||||
// Automatic Mode (Magic Tracking)
|
||||
$.watch(callback: Function): StopFunction
|
||||
$watch(callback: Function): StopFunction
|
||||
|
||||
// Explicit Mode (Isolated Dependencies)
|
||||
$.watch(deps: Signal[], callback: Function): StopFunction
|
||||
$watch(deps: Signal[], callback: Function): StopFunction
|
||||
```
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
@@ -29,7 +29,7 @@ Any signal you "touch" inside the callback becomes a dependency. SigPro tracks t
|
||||
```javascript
|
||||
const count = $(0);
|
||||
|
||||
$.watch(() => {
|
||||
$watch(() => {
|
||||
// Re-runs every time 'count' changes
|
||||
console.log(`Count is: ${count()}`);
|
||||
});
|
||||
@@ -42,7 +42,7 @@ This mode **isolates** execution. The callback only triggers when the signals in
|
||||
const sPath = $("/home");
|
||||
const user = $("Admin");
|
||||
|
||||
$.watch([sPath], () => {
|
||||
$watch([sPath], () => {
|
||||
// Only triggers when 'sPath' changes.
|
||||
// Changes to 'user' will NOT trigger this, preventing accidental re-renders.
|
||||
console.log(`Navigating to ${sPath()} as ${user()}`);
|
||||
@@ -53,11 +53,11 @@ $.watch([sPath], () => {
|
||||
If your logic creates timers, event listeners, or other reactive effects, SigPro tracks them as "children" of the current watch. When the watcher re-runs or stops, it kills everything inside automatically.
|
||||
|
||||
```javascript
|
||||
$.watch(() => {
|
||||
$watch(() => {
|
||||
const timer = setInterval(() => console.log("Tick"), 1000);
|
||||
|
||||
// Register a manual cleanup if needed
|
||||
// Or simply rely on SigPro to kill nested $.watch() calls
|
||||
// Or simply rely on SigPro to kill nested $watch() calls
|
||||
return () => clearInterval(timer);
|
||||
});
|
||||
```
|
||||
@@ -68,7 +68,7 @@ $.watch(() => {
|
||||
Call the returned function to manually kill the watcher. This is essential for manual DOM injections (like Toasts) or long-lived background processes.
|
||||
|
||||
```javascript
|
||||
const stop = $.watch(() => console.log(count()));
|
||||
const stop = $watch(() => console.log(count()));
|
||||
|
||||
// Later...
|
||||
stop(); // The link between the signal and this code is physically severed.
|
||||
@@ -83,7 +83,7 @@ SigPro batches updates. If you update multiple signals in the same execution blo
|
||||
const a = $(0);
|
||||
const b = $(0);
|
||||
|
||||
$.watch(() => console.log(a(), b()));
|
||||
$watch(() => console.log(a(), b()));
|
||||
|
||||
// This triggers only ONE re-run.
|
||||
a(1);
|
||||
|
||||
@@ -66,7 +66,7 @@ export const App = () => {
|
||||
import { $ } from 'sigpro';
|
||||
import { App } from './App.js';
|
||||
|
||||
$.mount(App, '#app');
|
||||
$mount(App, '#app');
|
||||
```
|
||||
|
||||
```html [Classic (Direct CDN)]
|
||||
@@ -91,7 +91,7 @@ $.mount(App, '#app');
|
||||
})
|
||||
]);
|
||||
|
||||
$.mount(App, '#app');
|
||||
$mount(App, '#app');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# Buttons
|
||||
|
||||
The **SigPro** Button component wraps [DaisyUI 5](https://daisyui.com/components/button/) styles with native reactive logic.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
<button class="btn btn-primary btn-secondary btn-accent btn-neutral btn-info btn-lg btn-sm btn-xs">Test</button>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
onMounted(() => {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const init = () => {
|
||||
// 1. Esperamos a que el Core ($) y los helpers (Button, Div) existan
|
||||
if (!window.$ || !window.Button || !window.Input) {
|
||||
setTimeout(init, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Usamos las funciones tal cual las crea tu Core (con Mayúscula inicial)
|
||||
const { $, Button, Input, Div, P, Span } = window;
|
||||
const Mount = $.mount;
|
||||
const HTML = $.html;
|
||||
// --- DEMO REACTIVA ---
|
||||
const nombre = $('Mundo');
|
||||
|
||||
return Mount(
|
||||
Div({ class: 'flex flex-col gap-4' }, [
|
||||
// Usamos el helper Input de tu librería
|
||||
Input({
|
||||
class: 'input input-bordered input-primary w-full max-w-xs',
|
||||
value: nombre, // Tu Core maneja el binding si es una señal
|
||||
placeholder: 'Escribe tu nombre...'
|
||||
}),
|
||||
|
||||
// El P y el Span también son helpers de tu Core
|
||||
P({ class: 'text-xl' }, [
|
||||
'Hola ',
|
||||
Span({ class: 'text-primary font-bold' }, nombre),
|
||||
'!'
|
||||
])
|
||||
]),
|
||||
'#demo-input-simple'
|
||||
);
|
||||
};
|
||||
|
||||
init();
|
||||
})
|
||||
</script>
|
||||
@@ -17,7 +17,7 @@ To ensure all components render correctly with their reactive themes and states,
|
||||
Unlike **Tag Helpers** (which are just functional mirrors of HTML tags), SigPro UI Components are smart abstractions:
|
||||
|
||||
* **Stateful**: They manage complex internal states (like date ranges, search filtering, or API lifecycles).
|
||||
* **Reactive**: Attributes prefixed with `$` are automatically tracked via `$.watch`.
|
||||
* **Reactive**: Attributes prefixed with `$` are automatically tracked via `$watch`.
|
||||
* **Self-Sane**: They automatically use `._cleanups` to destroy observers or event listeners when removed from the DOM.
|
||||
* **Themed**: Fully compatible with the DaisyUI v5 theme system and Tailwind v4 utility classes.
|
||||
|
||||
@@ -85,7 +85,7 @@ Datepicker({
|
||||
```
|
||||
|
||||
### D. Imperative Toasts & Modals
|
||||
Trigger complex UI elements from your logic. These components use `$.mount` internally to ensure they are properly cleaned up from memory after they close.
|
||||
Trigger complex UI elements from your logic. These components use `$mount` internally to ensure they are properly cleaned up from memory after they close.
|
||||
|
||||
```javascript
|
||||
// Show a notification (Self-destroying after 3s)
|
||||
@@ -107,7 +107,7 @@ Modal({
|
||||
|
||||
## 4. Internationalization (i18n)
|
||||
|
||||
The UI library comes with a built-in locale system. It currently supports `es` and `en`.
|
||||
The UI library comes with a built-in locale system.
|
||||
|
||||
```javascript
|
||||
// Set the global UI language
|
||||
@@ -117,11 +117,4 @@ SetLocale("en");
|
||||
const t = tt("confirm");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Best Practices
|
||||
|
||||
* **Use `$` for Reactivity**: If a property starts with `$`, the component expects a Signal (e.g., `$value: mySignal`).
|
||||
* **Automatic Cleaning**: You don't need to manually destroy these components if they are inside a `$.If` or `$.For`. SigPro's core will "sweep" their internal watchers automatically.
|
||||
* **Manual Cleanups**: If you build custom components using `setInterval` or third-party observers, always add the stop functions to the element's `._cleanups` Set.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user