From 47917ac5c8813e6ce0f88c883ddc295c249b3f97 Mon Sep 17 00:00:00 2001 From: natxocc Date: Sat, 21 Mar 2026 13:44:20 +0100 Subject: [PATCH] Actualizar src/sigpro.js --- src/sigpro.js | 126 ++++++++++++++++---------------------------------- 1 file changed, 40 insertions(+), 86 deletions(-) diff --git a/src/sigpro.js b/src/sigpro.js index 25b24fc..5ce0967 100644 --- a/src/sigpro.js +++ b/src/sigpro.js @@ -1,21 +1,17 @@ /** - * SigPro 2.0 - Complete Reactive Engine - * @author Gemini & User + * SigPro 2.0 - Integrated Reactive Engine */ (() => { - /** @type {Function|null} */ + /** @type {Function|null} Dependency tracker */ let activeEffect = null; /** - * Creates a Signal (State) or a Computed (Derived state). - * @template T - * @param {T|function():T} initial - Initial value or a computation function. - * @returns {{(newValue?: T|function(T):T): T}} A getter/setter function. + * Reactive Engine ($) + * Creates Signals, Computeds, or Effects. + * @param {any} initial - Value or reactive function. */ - const $ = (initial) => { - /** @type {Set} */ + window.$ = (initial) => { const subs = new Set(); - if (typeof initial === 'function') { let cached; const runner = () => { @@ -25,51 +21,39 @@ subs.forEach(s => s()); }; runner(); - return () => { - if (activeEffect) subs.add(activeEffect); - return cached; - }; + return () => { (activeEffect && subs.add(activeEffect)); return cached; }; } - return (...args) => { if (args.length) { const next = typeof args[0] === 'function' ? args[0](initial) : args[0]; - if (!Object.is(initial, next)) { - initial = next; - subs.forEach(s => s()); - } + if (!Object.is(initial, next)) { initial = next; subs.forEach(s => s()); } } - if (activeEffect) subs.add(activeEffect); + (activeEffect && subs.add(activeEffect)); return initial; }; }; /** - * Creates a reactive effect. - * @param {function():void} fn - The function to execute reactively. + * Hyperscript Engine ($$) + * @param {string} tag - HTML tag. + * @param {Object} [props] - Attributes/Events. + * @param {any} [children] - Content. */ - const _$ = (fn) => { - const effect = () => { - const prev = activeEffect; - activeEffect = effect; - try { fn(); } finally { activeEffect = prev; } - }; - effect(); - return effect; - }; - - /** - * Universal DOM Constructor (Hyperscript). - * @param {string} tag - HTML Tag name. - * @param {Object | HTMLElement | Array | string} [props] - Attributes or children. - * @param {Array | HTMLElement | string | function} [children] - Element children. - * @returns {HTMLElement} - */ - const $$ = (tag, props = {}, children = []) => { + window.$$ = (tag, props = {}, children = []) => { const el = document.createElement(tag); - if (typeof props !== 'object' || props instanceof Node || Array.isArray(props)) { - children = props; props = {}; + + // Logic: If props is NOT a plain object or is a Node/Array/Function, + // it's actually the children. + if ( + typeof props !== 'object' || + props instanceof Node || + Array.isArray(props) || + typeof props === 'function' + ) { + children = props; + props = {}; } + for (let [key, val] of Object.entries(props)) { if (key.startsWith('on')) { el.addEventListener(key.toLowerCase().slice(2), val); @@ -79,22 +63,20 @@ const ev = attr === 'checked' ? 'change' : 'input'; el.addEventListener(ev, e => val(attr === 'checked' ? e.target.checked : e.target.value)); } - _$(() => { + $(() => { const v = typeof val === 'function' ? val() : val; if (attr === 'value' || attr === 'checked') el[attr] = v; else if (typeof v === 'boolean') el.toggleAttribute(attr, v); else el.setAttribute(attr, v ?? ''); }); - } else { - el.setAttribute(key, val); - } + } else el.setAttribute(key, val); } - + const append = (c) => { if (Array.isArray(c)) return c.forEach(append); if (typeof c === 'function') { const node = document.createTextNode(''); - _$(() => { + $(() => { const res = c(); if (res instanceof Node) { if (node.parentNode) node.replaceWith(res); } else { node.textContent = res ?? ''; } @@ -108,61 +90,33 @@ }; /** - * Renders the application into a target element. - * @param {HTMLElement | function():HTMLElement} node - * @param {HTMLElement} [target] + * System Utilities (_) */ - const $render = (node, target = document.body) => { + window._render = (node, target = document.body) => { target.innerHTML = ''; target.appendChild(typeof node === 'function' ? node() : node); }; - /** - * Hash-based Reactive Router. - * @param {Array<{path: string, component: function|HTMLElement}>} routes - * @returns {HTMLElement} - */ - const $router = (routes) => { + window._router = (routes) => { const sPath = $(window.location.hash.replace(/^#/, "") || "/"); window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/")); - - return $$('div', { class: "router-view" }, [ + return div({ class: "sigpro-router" }, [ () => { const current = sPath(); - let params = {}; const route = routes.find(r => { const rP = r.path.split('/').filter(Boolean); const cP = current.split('/').filter(Boolean); if (rP.length !== cP.length) return false; - return rP.every((part, i) => { - if (part.startsWith(':')) { params[part.slice(1)] = cP[i]; return true; } - return part === cP[i]; - }); + return rP.every((part, i) => part.startsWith(':') || part === cP[i]); }) || routes.find(r => r.path === "*"); - - if (!route) return $$('h1', '404'); - return typeof route.component === 'function' ? route.component(params) : route.component; + return route ? (typeof route.component === 'function' ? route.component() : route.component) : h1("404"); } ]); }; - /** - * Registers a plugin into the SigPro ecosystem. - * @param {string} name - * @param {Object} exports - */ - const $use = (name, exports) => { - Object.assign(window, exports); - console.log(`%c[SigPro] Plugin Loaded: ${name}`, "color: #00ff7f; font-weight: bold;"); - }; - - // --- AUTO-INJECT STANDARD TAGS --- - const tags = ['div', 'span', 'p', 'button', 'h1', 'h2', 'h3', 'ul', 'li', 'a', 'label', 'section', 'nav', 'main', 'header', 'footer', 'input', 'img', 'form']; - const standardTags = {}; - tags.forEach(tag => { - standardTags[tag] = (p, c) => $$(tag, p, c); + // Auto-generate tags: div(), h1(), etc. + ['div', 'span', 'p', 'button', 'h1', 'h2', 'h3', 'ul', 'li', 'a', 'input', 'section', 'main'].forEach(t => { + window[t] = (p, c) => $$(t, p, c); }); - // Global Exports - Object.assign(window, { $, _$, $$, $render, $router, $use, ...standardTags }); -})(); +})(); \ No newline at end of file