This commit is contained in:
2026-03-23 03:05:39 +01:00
parent 8b742bd11a
commit 2e1617ebe2

View File

@@ -1,5 +1,5 @@
/** /**
* SigPro v2.0 * SigPro
*/ */
(() => { (() => {
let activeEffect = null; let activeEffect = null;
@@ -7,7 +7,6 @@
let isFlushScheduled = false; let isFlushScheduled = false;
let flushCount = 0; let flushCount = 0;
// --- Motor de Batching con Protección (v1 + v2) ---
const flushQueue = () => { const flushQueue = () => {
isFlushScheduled = false; isFlushScheduled = false;
flushCount++; flushCount++;
@@ -21,7 +20,6 @@
effectQueue.clear(); effectQueue.clear();
effects.forEach(fn => fn()); effects.forEach(fn => fn());
// Resetear contador al final del microtask
queueMicrotask(() => flushCount = 0); queueMicrotask(() => flushCount = 0);
}; };
@@ -36,29 +34,26 @@
const $ = (initial, key) => { const $ = (initial, key) => {
const subs = new Set(); const subs = new Set();
// 1. Objetos Reactivos (v2)
if (initial?.constructor === Object && !key) { if (initial?.constructor === Object && !key) {
const store = {}; const store = {};
for (let k in initial) store[k] = $(initial[k]); for (let k in initial) store[k] = $(initial[k]);
return store; return store;
} }
// 2. Efectos y Computados con Limpieza (v1 + v2)
if (typeof initial === 'function') { if (typeof initial === 'function') {
let cached, running = false; let cached, running = false;
const cleanups = new Set(); const cleanups = new Set();
const runner = () => { const runner = () => {
if (runner.el && !runner.el.isConnected) return; // GC: v2 if (runner.el && !runner.el.isConnected) return;
if (running) return; if (running) return;
// Ejecutar limpiezas previas (v1)
cleanups.forEach(fn => fn()); cleanups.forEach(fn => fn());
cleanups.clear(); cleanups.clear();
const prev = activeEffect; const prev = activeEffect;
activeEffect = runner; activeEffect = runner;
activeEffect.onCleanup = (fn) => cleanups.add(fn); // Registro de limpieza activeEffect.onCleanup = (fn) => cleanups.add(fn);
running = true; running = true;
try { try {
@@ -79,13 +74,11 @@
}; };
} }
// 3. Persistencia (v2)
if (key) { if (key) {
const saved = localStorage.getItem(key); const saved = localStorage.getItem(key);
if (saved !== null) try { initial = JSON.parse(saved); } catch (e) { } if (saved !== null) try { initial = JSON.parse(saved); } catch (e) { }
} }
// 4. Señal Atómica
return (...args) => { return (...args) => {
if (args.length) { if (args.length) {
const next = typeof args[0] === 'function' ? args[0](initial) : args[0]; const next = typeof args[0] === 'function' ? args[0](initial) : args[0];
@@ -103,7 +96,6 @@
}; };
}; };
// --- Motor de Renderizado con Modificadores de v1 ---
$.html = (tag, props = {}, content = []) => { $.html = (tag, props = {}, content = []) => {
const el = document.createElement(tag); const el = document.createElement(tag);
if (props instanceof Node || Array.isArray(props) || typeof props !== 'object') { if (props instanceof Node || Array.isArray(props) || typeof props !== 'object') {
@@ -179,12 +171,9 @@
const tags = ['div', 'span', 'p', 'h1', 'h2', 'ul', 'li', 'button', 'input', 'label', 'form', 'section', 'a', 'img']; const tags = ['div', 'span', 'p', 'h1', 'h2', 'ul', 'li', 'button', 'input', 'label', 'form', 'section', 'a', 'img'];
tags.forEach(t => window[t] = (p, c) => $.html(t, p, c)); tags.forEach(t => window[t] = (p, c) => $.html(t, p, c));
// --- Router mejorado ---
$.router = (routes) => { $.router = (routes) => {
// Señal persistente del path actual
const sPath = $(window.location.hash.replace(/^#/, "") || "/"); const sPath = $(window.location.hash.replace(/^#/, "") || "/");
// Listener nativo
window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/")); window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/"));
const container = div({ class: "router-outlet" }); const container = div({ class: "router-outlet" });
@@ -193,7 +182,6 @@
const cur = sPath(); const cur = sPath();
const cP = cur.split('/').filter(Boolean); const cP = cur.split('/').filter(Boolean);
// Buscamos la ruta (incluyendo parámetros :id y wildcard *)
const route = routes.find(r => { const route = routes.find(r => {
const rP = r.path.split('/').filter(Boolean); const rP = r.path.split('/').filter(Boolean);
return rP.length === cP.length && rP.every((p, i) => p.startsWith(':') || p === cP[i]); return rP.length === cP.length && rP.every((p, i) => p.startsWith(':') || p === cP[i]);
@@ -201,7 +189,6 @@
if (!route) return container.replaceChildren(h1("404 - Not Found")); if (!route) return container.replaceChildren(h1("404 - Not Found"));
// Extraer parámetros dinámicos
const params = {}; const params = {};
route.path.split('/').filter(Boolean).forEach((p, i) => { route.path.split('/').filter(Boolean).forEach((p, i) => {
if (p.startsWith(':')) params[p.slice(1)] = cP[i]; if (p.startsWith(':')) params[p.slice(1)] = cP[i];
@@ -209,7 +196,6 @@
const res = typeof route.component === 'function' ? route.component(params) : route.component; const res = typeof route.component === 'function' ? route.component(params) : route.component;
// Renderizado Seguro con replaceChildren (v1 spirit)
if (res instanceof Promise) { if (res instanceof Promise) {
const loader = span("Cargando..."); const loader = span("Cargando...");
container.replaceChildren(loader); container.replaceChildren(loader);
@@ -219,13 +205,12 @@
} }
}; };
routeEff.el = container; // Seguridad de SigPro v2 routeEff.el = container;
$(routeEff); $(routeEff);
return container; return container;
}; };
// Vinculamos el método .go
$.router.go = (path) => { $.router.go = (path) => {
const target = path.startsWith('/') ? path : `/${path}`; const target = path.startsWith('/') ? path : `/${path}`;
window.location.hash = target; window.location.hash = target;
@@ -237,4 +222,5 @@
}; };
window.$ = $; window.$ = $;
})(); })();
export const { $ } = window;