diff --git a/packages/sigpro/sigpro2.js b/packages/sigpro/sigpro2.js index 1f9391a..06bfd41 100644 --- a/packages/sigpro/sigpro2.js +++ b/packages/sigpro/sigpro2.js @@ -41,6 +41,13 @@ export const $e = (fn) => { 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); @@ -50,12 +57,11 @@ const h = (tag, props = {}, children = []) => { } 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; @@ -88,7 +94,27 @@ const h = (tag, props = {}, children = []) => { return el; }; -const tags = ['div', 'span', 'p', 'button', 'input', 'h1', 'h2', 'label', 'section', 'ul', 'li', 'a', 'header', 'footer', 'main', 'nav']; +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)) { @@ -107,3 +133,7 @@ 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)); + +window._storage = _storage; +window._router = _router; +window._render = _render;