Update Sigpro
This commit is contained in:
@@ -21,40 +21,48 @@ $.html(tagName: string, props?: Object, children?: any[] | any): HTMLElement
|
||||
### 1. Attribute Handling
|
||||
SigPro intelligently decides how to apply each property:
|
||||
* **Standard Props**: Applied via `setAttribute` or direct property assignment.
|
||||
* **Boolean Props**: Uses `toggleAttribute` (e.g., `checked`, `disabled`, `hidden`).
|
||||
* **Class Names**: Supports `class` or `className` interchangeably.
|
||||
* **Boolean Props**: Automatic handling for `checked`, `disabled`, `hidden`, etc.
|
||||
|
||||
### 2. Event Listeners & Modifiers
|
||||
Events are defined by the `on` prefix. SigPro supports **Dot Notation** for common event operations:
|
||||
### 2. 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
|
||||
$.html("button", {
|
||||
// e.preventDefault() is called automatically
|
||||
"onsubmit.prevent": (e) => save(e),
|
||||
|
||||
// e.stopPropagation() is called automatically
|
||||
"onclick.stop": () => console.log("No bubbling"),
|
||||
|
||||
// { once: true } listener option
|
||||
"onclick.once": () => console.log("Runs only once")
|
||||
Button({
|
||||
onclick: (e) => console.log("Clicked!", e),
|
||||
}, "Click Me");
|
||||
```
|
||||
|
||||
### 3. Reactive Attributes
|
||||
### 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.
|
||||
|
||||
```javascript
|
||||
$.html("div", {
|
||||
Div({
|
||||
// Updates the class whenever 'theme()' changes
|
||||
class: () => theme() === "dark" ? "bg-black" : "bg-white"
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Reactive Children
|
||||
### 4. 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({
|
||||
type: "text",
|
||||
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
|
||||
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
|
||||
$.html("div", {}, [
|
||||
Div({}, [
|
||||
H1("Static Title"),
|
||||
// Only this text node re-renders when 'count' changes
|
||||
() => `Current count: ${count()}`
|
||||
@@ -63,27 +71,16 @@ $.html("div", {}, [
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Two-Way Binding Operator (`$`)
|
||||
|
||||
When a property starts with `$`, `$.html` enables bidirectional synchronization. This is primarily used for form inputs.
|
||||
|
||||
```javascript
|
||||
$.html("input", {
|
||||
type: "text",
|
||||
$value: username // Syncs input value <-> signal
|
||||
});
|
||||
```
|
||||
|
||||
## 🧹 Memory Management (Internal)
|
||||
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**.
|
||||
* **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**.
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tag Constructors (The Shortcuts)
|
||||
|
||||
Instead of writing `$.html("div", ...)` every time, SigPro provides PascalCase global functions:
|
||||
Instead of writing `$.html("div", ...)` every time, SigPro provides PascalCase global functions for all standard HTML tags:
|
||||
|
||||
```javascript
|
||||
// This:
|
||||
|
||||
@@ -13,7 +13,7 @@ SigPro iterates through a manifest of standard HTML tags and attaches a wrapper
|
||||
|
||||
## 2. The Complete Global Registry
|
||||
|
||||
The following functions are injected into the global scope (using **PascalCase** to prevent naming collisions with common JS variables) and are ready to use:
|
||||
The following functions are injected into the global scope using **PascalCase** to prevent naming collisions with common JS variables:
|
||||
|
||||
| Category | Available Global Functions |
|
||||
| :--- | :--- |
|
||||
@@ -24,8 +24,6 @@ The following functions are injected into the global scope (using **PascalCase**
|
||||
| **Tables** | `Table`, `Thead`, `Tbody`, `Tr`, `Th`, `Td`, `Tfoot`, `Caption` |
|
||||
| **Media** | `Img`, `Canvas`, `Video`, `Audio`, `Svg`, `Iframe`, `Picture`, `Source` |
|
||||
|
||||
> **The SigPro Philosophy:** Tags are not "magic strings" handled by a compiler. They are **functional constructors**. Every time you call `Div()`, you execute a pure JS function that returns a real, reactive DOM element.
|
||||
|
||||
---
|
||||
|
||||
## 3. Usage Patterns (Smart Arguments)
|
||||
@@ -33,7 +31,6 @@ The following functions are injected into the global scope (using **PascalCase**
|
||||
SigPro tag helpers are flexible. They automatically detect if you are passing attributes, children, or both.
|
||||
|
||||
### A. Attributes + Children
|
||||
The standard way to build structured UI.
|
||||
```javascript
|
||||
Div({ class: 'container', id: 'main' }, [
|
||||
H1("Welcome to SigPro"),
|
||||
@@ -42,7 +39,7 @@ Div({ class: 'container', id: 'main' }, [
|
||||
```
|
||||
|
||||
### B. Children Only (The "Skipper")
|
||||
If you don't need attributes, you can skip the object and pass the content (string, array, or function) directly as the first argument.
|
||||
If you don't need attributes, you can pass the content directly as the first argument.
|
||||
```javascript
|
||||
Section([
|
||||
H2("Clean Syntax"),
|
||||
@@ -50,85 +47,79 @@ Section([
|
||||
]);
|
||||
```
|
||||
|
||||
### C. Primitive Content
|
||||
For simple tags, just pass a string or a number.
|
||||
```javascript
|
||||
H1("Hello World");
|
||||
Span(42);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Reactive Power
|
||||
|
||||
These helpers are natively wired into SigPro's **`$.watch`** engine. No manual effect management is needed; the lifecycle is tied to the DOM node.
|
||||
These helpers are natively wired into SigPro's **`$.watch`** engine.
|
||||
|
||||
### Reactive Attributes
|
||||
### Reactive Attributes (One-Way)
|
||||
Simply pass a Signal (function) to any attribute. SigPro creates an internal `$.watch` to keep the DOM in sync.
|
||||
```javascript
|
||||
const theme = $("light");
|
||||
|
||||
Div({
|
||||
// Updates 'class' automatically via internal $.watch
|
||||
class: () => `app-box ${theme()}`
|
||||
}, "Themeable Box");
|
||||
```
|
||||
|
||||
### The Binding Operator (`$`)
|
||||
Use the `$` prefix for **Two-Way Binding** on inputs. This bridges the Signal and the Input element bi-directionally.
|
||||
### Smart Two-Way Binding (Automatic)
|
||||
SigPro automatically bridges the **Signal** and the **Input** element bi-directionally when you assign a Signal to `value` or `checked`. No special operators are required.
|
||||
|
||||
```javascript
|
||||
const search = $("");
|
||||
|
||||
// UI updates Signal AND Signal updates UI automatically
|
||||
Input({
|
||||
type: "text",
|
||||
placeholder: "Search...",
|
||||
$value: search // UI updates Signal AND Signal updates UI
|
||||
value: search
|
||||
});
|
||||
```
|
||||
|
||||
> **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 for high-performance rendering. SigPro automatically cleans up the `$.watch` instances when nodes are removed.
|
||||
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))
|
||||
$.for(items, (item) => Li(item), (item) => item)
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
::: danger
|
||||
## ⚠️ Important: Naming Conventions
|
||||
|
||||
Since SigPro injects these helpers into the global `window` object, follow these rules to avoid bugs:
|
||||
|
||||
1. **Avoid Shadowing**: Don't name your local variables like the tags (e.g., `const Div = ...`). This will "hide" the SigPro helper.
|
||||
2. **Custom Components**: Always use **PascalCase** for your own component functions (e.g., `UserCard`, `NavMenu`) to distinguish them from the built-in Tag Helpers and maintain architectural clarity.
|
||||
1. **Avoid Shadowing**: Don't name your local variables like the tags (e.g., `const Div = ...`). This will "hide" the global SigPro helper.
|
||||
2. **Custom Components**: Always use **PascalCase** for your own component functions (e.g., `UserCard`, `NavMenu`) to distinguish them from built-in Tag Helpers.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 5. Logic to UI Comparison
|
||||
|
||||
Here is how a dynamic **User Status** component translates from SigPro logic to the final DOM structure, handled by the engine.
|
||||
Here is how a dynamic **User Status** component translates from SigPro logic to the final DOM structure.
|
||||
|
||||
```javascript
|
||||
// SigPro Component
|
||||
const UserStatus = (name, $online) => (
|
||||
const UserStatus = (name, online) => (
|
||||
Div({ class: 'flex items-center gap-2' }, [
|
||||
Span({
|
||||
// Boolean toggle for 'hidden' attribute
|
||||
hidden: () => !$online(),
|
||||
hidden: () => !online(),
|
||||
class: 'w-3 h-3 bg-green-500 rounded-full'
|
||||
}),
|
||||
P({
|
||||
// Reactive text content via automatic $.watch
|
||||
class: () => $online() ? "text-bold" : "text-gray-400"
|
||||
class: () => online() ? "text-bold" : "text-gray-400"
|
||||
}, name)
|
||||
])
|
||||
);
|
||||
```
|
||||
|
||||
| State (`$online`) | Rendered HTML | Memory Management |
|
||||
| State (`online`) | Rendered HTML | Memory Management |
|
||||
| :--- | :--- | :--- |
|
||||
| **`true`** | `<div class="flex..."><span class="w-3..."></span><p class="text-bold">John</p></div>` | Watcher active |
|
||||
| **`false`** | `<div class="flex..."><span hidden class="w-3..."></span><p class="text-gray-400">John</p></div>` | Attribute synced |
|
||||
|
||||
|
||||
51
src/docs/ui/buttons.md
Normal file
51
src/docs/ui/buttons.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# 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>
|
||||
Reference in New Issue
Block a user