From c4c6f8cbfd55d7f40981e0d7b5e4f0c3d310497c Mon Sep 17 00:00:00 2001 From: Natxo <1172351+natxocc@users.noreply.github.com> Date: Sat, 21 Mar 2026 01:02:49 +0100 Subject: [PATCH] Update sigpro2.js --- packages/sigpro/sigpro2.js | 248 ++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 129 deletions(-) diff --git a/packages/sigpro/sigpro2.js b/packages/sigpro/sigpro2.js index 06bfd41..99eeeed 100644 --- a/packages/sigpro/sigpro2.js +++ b/packages/sigpro/sigpro2.js @@ -1,139 +1,129 @@ -let activeEffect = null; +(() => { + let activeEffect = null; -export const $ = (initial) => { - const subs = new Set(); - - if (typeof initial === 'function') { - let cached; - const runner = () => { - const prev = activeEffect; - activeEffect = runner; - try { cached = initial(); } finally { activeEffect = prev; } - subs.forEach(s => s()); - }; - runner(); - return () => { - if (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; + window.$ = (initial) => { + const subs = new Set(); + if (typeof initial === 'function') { + let cached; + const runner = () => { + const prev = activeEffect; + activeEffect = runner; + try { cached = initial(); } finally { activeEffect = prev; } subs.forEach(s => s()); - } + }; + runner(); + return () => { + if (activeEffect) subs.add(activeEffect); + return cached; + }; } - if (activeEffect) subs.add(activeEffect); - return initial; - }; -}; - -export const $e = (fn) => { - const effect = () => { - const prev = activeEffect; - activeEffect = effect; - try { fn(); } finally { activeEffect = prev; } - }; - effect(); - return effect; -}; - -export const _storage = (key, initial, storage = localStorage) => { - const saved = storage.getItem(key); - const signal = $((saved !== null) ? JSON.parse(saved) : initial); - $e(() => storage.setItem(key, JSON.stringify(signal()))); - return signal; -}; - -const h = (tag, props = {}, children = []) => { - const el = document.createElement(tag); - - for (let [key, val] of Object.entries(props)) { - if (key.startsWith('on')) { - el.addEventListener(key.toLowerCase().slice(2), val); - } - else if (key.startsWith('$')) { - const attr = key.slice(1); - // Two-way binding - if ((attr === 'value' || attr === 'checked') && typeof val === 'function') { - const ev = attr === 'checked' ? 'change' : 'input'; - el.addEventListener(ev, e => val(attr === 'checked' ? e.target.checked : e.target.value)); - } - $e(() => { - 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); - } - } - - const append = (c) => { - if (Array.isArray(c)) return c.forEach(append); - if (typeof c === 'function') { - const node = document.createTextNode(''); - $e(() => { - const res = c(); - if (res instanceof Node) { - if (node.parentNode) node.replaceWith(res); - } else { - node.textContent = res ?? ''; + 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()); } - }); - return el.appendChild(node); - } - el.appendChild(c instanceof Node ? c : document.createTextNode(c ?? '')); + } + if (activeEffect) subs.add(activeEffect); + return initial; + }; }; - append(children); - return el; -}; -export const _router = (routes) => { - const path = $(window.location.hash.replace(/^#/, "") || "/"); - window.addEventListener("hashchange", () => path(window.location.hash.replace(/^#/, "") || "/")); - - return _div({ class: "router-container" }, [ - () => { - const current = path(); - const route = routes.find(r => r.path === current) || routes.find(r => r.path === "*"); - return route ? route.component() : _h1("404"); - } - ]); -}; - -export const _render = (node, target = document.body) => { - target.innerHTML = ''; - const element = typeof node === 'function' ? node() : node; - target.appendChild(element); - return element; -}; - -const tags = ['div', 'span', 'p', 'button', 'input', 'h1', 'h2', 'label', 'section', 'ul', 'li', 'a', 'header', 'footer']; -tags.forEach(tag => { - window[`_${tag}`] = (props, children) => { - if (typeof props !== 'object' || props instanceof Node || Array.isArray(props)) { - return h(tag, {}, props); - } - return h(tag, props, children); + window.$e = (fn) => { + const effect = () => { + const prev = activeEffect; + activeEffect = effect; + try { fn(); } finally { activeEffect = prev; } + }; + effect(); + return effect; }; -}); -window.Row = (props, children) => _div({ - ...((typeof props === 'object' && !Array.isArray(props)) ? props : {}), - style: `display:flex; flex-direction:row; gap:10px; ${props?.style || ''}` -}, (Array.isArray(props) ? props : children)); + const h = (tag, props = {}, children = []) => { + const el = document.createElement(tag); + for (let [key, val] of Object.entries(props)) { + if (key.startsWith('on')) { + el.addEventListener(key.toLowerCase().slice(2), val); + } else if (key.startsWith('$')) { + const attr = key.slice(1); + if ((attr === 'value' || attr === 'checked') && typeof val === 'function') { + const ev = attr === 'checked' ? 'change' : 'input'; + el.addEventListener(ev, e => val(attr === 'checked' ? e.target.checked : e.target.value)); + } + $e(() => { + 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); + } + } + const append = (c) => { + if (Array.isArray(c)) return c.forEach(append); + if (typeof c === 'function') { + const node = document.createTextNode(''); + $e(() => { + const res = c(); + if (res instanceof Node) { + if (node.parentNode) node.replaceWith(res); + } else { + node.textContent = res ?? ''; + } + }); + return el.appendChild(node); + } + el.appendChild(c instanceof Node ? c : document.createTextNode(c ?? '')); + }; + append(children); + return el; + }; -window.Col = (props, children) => _div({ - ...((typeof props === 'object' && !Array.isArray(props)) ? props : {}), - style: `display:flex; flex-direction:column; gap:10px; ${props?.style || ''}` -}, (Array.isArray(props) ? props : children)); + const tags = ['div', 'span', 'p', 'button', 'input', 'h1', 'h2', 'label', 'section', 'ul', 'li', 'a', 'header', 'footer', 'nav', 'main']; + tags.forEach(tag => { + window[`_${tag}`] = (props, children) => { + if (typeof props !== 'object' || props instanceof Node || Array.isArray(props)) { + return h(tag, {}, props); + } + return h(tag, props, children); + }; + }); -window._storage = _storage; -window._router = _router; -window._render = _render; + window._storage = (key, initial, storage = localStorage) => { + const saved = storage.getItem(key); + const signal = $((saved !== null) ? JSON.parse(saved) : initial); + $e(() => storage.setItem(key, JSON.stringify(signal()))); + return signal; + }; + + window._router = (routes) => { + const path = $(window.location.hash.replace(/^#/, "") || "/"); + window.addEventListener("hashchange", () => path(window.location.hash.replace(/^#/, "") || "/")); + return _div({ class: "router-container" }, [ + () => { + const current = path(); + const route = routes.find(r => r.path === current) || routes.find(r => r.path === "*"); + return route ? route.component() : _h1("404"); + } + ]); + }; + + window._render = (node, target = document.body) => { + target.innerHTML = ''; + const element = typeof node === 'function' ? node() : node; + target.appendChild(element); + return element; + }; + + window.Row = (props, children) => _div({ + ...((typeof props === 'object' && !Array.isArray(props)) ? props : {}), + style: `display:flex; flex-direction:row; gap:10px; ${props?.style || ''}` + }, (Array.isArray(props) ? props : children)); + + window.Col = (props, children) => _div({ + ...((typeof props === 'object' && !Array.isArray(props)) ? props : {}), + style: `display:flex; flex-direction:column; gap:10px; ${props?.style || ''}` + }, (Array.isArray(props) ? props : children)); +})();