From 087a5a3c6e751a65bc2c841098a1d170549f0062 Mon Sep 17 00:00:00 2001 From: natxocc Date: Sat, 4 Apr 2026 14:24:32 +0200 Subject: [PATCH] Include build ESM --- dist/sigpro.esm.js | 434 +++++++++++++++++++++++++++++++++++++++++ dist/sigpro.esm.min.js | 1 + dist/sigpro.js | 97 ++++++--- dist/sigpro.min.js | 2 +- package.json | 17 +- 5 files changed, 515 insertions(+), 36 deletions(-) create mode 100644 dist/sigpro.esm.js create mode 100644 dist/sigpro.esm.min.js diff --git a/dist/sigpro.esm.js b/dist/sigpro.esm.js new file mode 100644 index 0000000..39f9b7d --- /dev/null +++ b/dist/sigpro.esm.js @@ -0,0 +1,434 @@ +// sigpro/index.js +var activeEffect = null; +var currentOwner = null; +var effectQueue = new Set; +var isFlushing = false; +var MOUNTED_NODES = new WeakMap; +var flush = () => { + if (isFlushing) + return; + isFlushing = true; + while (effectQueue.size > 0) { + const sorted = Array.from(effectQueue).sort((a, b) => (a.depth || 0) - (b.depth || 0)); + effectQueue.clear(); + for (const eff of sorted) + if (!eff._deleted) + eff(); + } + isFlushing = false; +}; +var track = (subs) => { + if (activeEffect && !activeEffect._deleted) { + subs.add(activeEffect); + activeEffect._deps.add(subs); + } +}; +var trigger = (subs) => { + for (const eff of subs) { + if (eff === activeEffect || eff._deleted) + continue; + if (eff._isComputed) { + eff.markDirty(); + if (eff._subs) + trigger(eff._subs); + } else { + effectQueue.add(eff); + } + } + if (!isFlushing) + queueMicrotask(flush); +}; +var sweep = (node) => { + if (node._cleanups) { + node._cleanups.forEach((f) => f()); + node._cleanups.clear(); + } + node.childNodes?.forEach(sweep); +}; +var _view = (fn) => { + const cleanups = new Set; + const prev = currentOwner; + const container = document.createElement("div"); + container.style.display = "contents"; + currentOwner = { cleanups }; + try { + const res = fn({ onCleanup: (f) => cleanups.add(f) }); + const process = (n) => { + if (!n) + return; + if (n._isRuntime) { + cleanups.add(n.destroy); + container.appendChild(n.container); + } else if (Array.isArray(n)) + n.forEach(process); + else + container.appendChild(n instanceof Node ? n : document.createTextNode(String(n))); + }; + process(res); + } finally { + currentOwner = prev; + } + return { + _isRuntime: true, + container, + destroy: () => { + cleanups.forEach((f) => f()); + sweep(container); + container.remove(); + } + }; +}; +var $ = (initial, key = null) => { + if (typeof initial === "function") { + const subs2 = new Set; + let cached, dirty = true; + const effect = () => { + if (effect._deleted) + return; + effect._deps.forEach((s) => s.delete(effect)); + effect._deps.clear(); + const prev = activeEffect; + activeEffect = effect; + try { + const val = initial(); + if (!Object.is(cached, val) || dirty) { + cached = val; + dirty = false; + trigger(subs2); + } + } finally { + activeEffect = prev; + } + }; + effect._deps = new Set; + effect._isComputed = true; + effect._subs = subs2; + effect._deleted = false; + effect.markDirty = () => dirty = true; + effect.stop = () => { + effect._deleted = true; + effect._deps.forEach((s) => s.delete(effect)); + subs2.clear(); + }; + if (currentOwner) + currentOwner.cleanups.add(effect.stop); + return () => { + if (dirty) + effect(); + track(subs2); + return cached; + }; + } + let value = initial; + if (key) { + try { + const saved = localStorage.getItem(key); + if (saved !== null) + value = JSON.parse(saved); + } catch (e) { + console.warn("SigPro: LocalStorage locked", e); + } + } + const subs = new Set; + return (...args) => { + if (args.length) { + const next = typeof args[0] === "function" ? args[0](value) : args[0]; + if (!Object.is(value, next)) { + value = next; + if (key) + localStorage.setItem(key, JSON.stringify(value)); + trigger(subs); + } + } + track(subs); + return value; + }; +}; +var $watch = (target, fn) => { + const isExplicit = Array.isArray(target); + const callback = isExplicit ? fn : target; + const depsInput = isExplicit ? target : null; + if (typeof callback !== "function") + return () => {}; + const owner = currentOwner; + const runner = () => { + if (runner._deleted) + return; + runner._deps.forEach((s) => s.delete(runner)); + runner._deps.clear(); + runner._cleanups.forEach((c) => c()); + runner._cleanups.clear(); + const prevEffect = activeEffect; + const prevOwner = currentOwner; + activeEffect = runner; + currentOwner = { cleanups: runner._cleanups }; + runner.depth = prevEffect ? prevEffect.depth + 1 : 0; + try { + if (isExplicit) { + activeEffect = null; + callback(); + activeEffect = runner; + depsInput.forEach((d) => typeof d === "function" && d()); + } else { + callback(); + } + } finally { + activeEffect = prevEffect; + currentOwner = prevOwner; + } + }; + runner._deps = new Set; + runner._cleanups = new Set; + runner._deleted = false; + runner.stop = () => { + if (runner._deleted) + return; + runner._deleted = true; + effectQueue.delete(runner); + runner._deps.forEach((s) => s.delete(runner)); + runner._cleanups.forEach((c) => c()); + if (owner) + owner.cleanups.delete(runner.stop); + }; + if (owner) + owner.cleanups.add(runner.stop); + runner(); + return runner.stop; +}; +var $html = (tag, props = {}, content = []) => { + if (props instanceof Node || Array.isArray(props) || typeof props !== "object") { + content = props; + props = {}; + } + const svgTags = ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "defs", "text", "tspan", "use"]; + const isSVG = svgTags.includes(tag); + const el = isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); + const _sanitize = (key, val) => (key === "src" || key === "href") && String(val).toLowerCase().includes("javascript:") ? "#" : val; + el._cleanups = new Set; + const boolAttrs = ["disabled", "checked", "required", "readonly", "selected", "multiple", "autofocus"]; + for (let [key, val] of Object.entries(props)) { + if (key === "ref") { + typeof val === "function" ? val(el) : val.current = el; + continue; + } + const isSignal = typeof val === "function", isInput = ["INPUT", "TEXTAREA", "SELECT"].includes(el.tagName), isBindAttr = key === "value" || key === "checked"; + if (isInput && isBindAttr && isSignal) { + el._cleanups.add($watch(() => { + const currentVal = val(); + if (el[key] !== currentVal) + el[key] = currentVal; + })); + const eventName = key === "checked" ? "change" : "input", handler = (event) => val(event.target[key]); + el.addEventListener(eventName, handler); + el._cleanups.add(() => el.removeEventListener(eventName, handler)); + } else if (key.startsWith("on")) { + const eventName = key.slice(2).toLowerCase().split(".")[0], handler = (event) => val(event); + el.addEventListener(eventName, handler); + el._cleanups.add(() => el.removeEventListener(eventName, handler)); + } else if (isSignal) { + el._cleanups.add($watch(() => { + const currentVal = _sanitize(key, val()); + if (key === "class") { + el.className = currentVal || ""; + } else if (boolAttrs.includes(key)) { + if (currentVal) { + el.setAttribute(key, ""); + el[key] = true; + } else { + el.removeAttribute(key); + el[key] = false; + } + } else { + if (currentVal == null) { + el.removeAttribute(key); + } else if (isSVG && typeof currentVal === "number") { + el.setAttribute(key, currentVal); + } else { + el.setAttribute(key, currentVal); + } + } + })); + } else { + if (boolAttrs.includes(key)) { + if (val) { + el.setAttribute(key, ""); + el[key] = true; + } else { + el.removeAttribute(key); + el[key] = false; + } + } else { + el.setAttribute(key, _sanitize(key, val)); + } + } + } + const append = (child) => { + if (Array.isArray(child)) + return child.forEach(append); + if (child instanceof Node) { + el.appendChild(child); + } else if (typeof child === "function") { + const marker = document.createTextNode(""); + el.appendChild(marker); + let nodes = []; + el._cleanups.add($watch(() => { + const res = child(), next = (Array.isArray(res) ? res : [res]).map((i) => i?._isRuntime ? i.container : i instanceof Node ? i : document.createTextNode(i ?? "")); + nodes.forEach((n) => { + sweep?.(n); + n.remove(); + }); + next.forEach((n) => marker.parentNode?.insertBefore(n, marker)); + nodes = next; + })); + } else + el.appendChild(document.createTextNode(child ?? "")); + }; + append(content); + return el; +}; +var $if = (condition, thenVal, otherwiseVal = null, transition = null) => { + const marker = document.createTextNode(""); + const container = $html("div", { style: "display:contents" }, [marker]); + let current = null, last = null; + $watch(() => { + const state = !!(typeof condition === "function" ? condition() : condition); + if (state === last) + return; + last = state; + if (current && !state && transition?.out) { + transition.out(current.container, () => { + current.destroy(); + current = null; + }); + } else { + if (current) + current.destroy(); + current = null; + } + if (state || !state && otherwiseVal) { + const branch = state ? thenVal : otherwiseVal; + if (branch) { + current = _view(() => typeof branch === "function" ? branch() : branch); + container.insertBefore(current.container, marker); + if (state && transition?.in) + transition.in(current.container); + } + } + }); + return container; +}; +$if.not = (condition, thenVal, otherwiseVal) => $if(() => !(typeof condition === "function" ? condition() : condition), thenVal, otherwiseVal); +var $for = (source, render, keyFn, tag = "div", props = { style: "display:contents" }) => { + const marker = document.createTextNode(""); + const container = $html(tag, props, [marker]); + let cache = new Map; + $watch(() => { + const items = (typeof source === "function" ? source() : source) || []; + const newCache = new Map; + const newOrder = []; + for (let i = 0;i < items.length; i++) { + const item = items[i]; + const key = keyFn ? keyFn(item, i) : i; + let run = cache.get(key); + if (!run) { + run = _view(() => render(item, i)); + } else { + cache.delete(key); + } + newCache.set(key, run); + newOrder.push(key); + } + cache.forEach((run) => { + run.destroy(); + run.container.remove(); + }); + let anchor = marker; + for (let i = newOrder.length - 1;i >= 0; i--) { + const run = newCache.get(newOrder[i]); + if (run.container.nextSibling !== anchor) { + container.insertBefore(run.container, anchor); + } + anchor = run.container; + } + cache = newCache; + }); + return container; +}; +var $router = (routes) => { + const sPath = $(window.location.hash.replace(/^#/, "") || "/"); + window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/")); + const outlet = $html("div", { class: "router-outlet" }); + let current = null; + $watch([sPath], async () => { + const path = sPath(); + const route = routes.find((r) => { + const rp = r.path.split("/").filter(Boolean), pp = path.split("/").filter(Boolean); + return rp.length === pp.length && rp.every((p, i) => p.startsWith(":") || p === pp[i]); + }) || routes.find((r) => r.path === "*"); + if (route) { + let comp = route.component; + if (typeof comp === "function" && comp.toString().includes("import")) { + comp = (await comp()).default || await comp(); + } + const params = {}; + route.path.split("/").filter(Boolean).forEach((p, i) => { + if (p.startsWith(":")) + params[p.slice(1)] = path.split("/").filter(Boolean)[i]; + }); + if (current) + current.destroy(); + if ($router.params) + $router.params(params); + current = _view(() => { + try { + return typeof comp === "function" ? comp(params) : comp; + } catch (e) { + return $html("div", { class: "p-4 text-error" }, "Error loading view"); + } + }); + outlet.appendChild(current.container); + } + }); + return outlet; +}; +$router.params = $({}); +$router.to = (path) => window.location.hash = path.replace(/^#?\/?/, "#/"); +$router.back = () => window.history.back(); +$router.path = () => window.location.hash.replace(/^#/, "") || "/"; +var $mount = (component, target) => { + const el = typeof target === "string" ? document.querySelector(target) : target; + if (!el) + return; + if (MOUNTED_NODES.has(el)) + MOUNTED_NODES.get(el).destroy(); + const instance = _view(typeof component === "function" ? component : () => component); + el.replaceChildren(instance.container); + MOUNTED_NODES.set(el, instance); + return instance; +}; +var SigProCore = { $, $watch, $html, $if, $for, $router, $mount }; +if (typeof window !== "undefined") { + const install = (registry) => { + Object.keys(registry).forEach((key) => { + window[key] = registry[key]; + }); + const tags = `div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer address ul ol li dl dt dd a em strong small i b u mark time sub sup pre code blockquote details summary dialog form label input textarea select button option fieldset legend table thead tbody tfoot tr th td caption img video audio canvas svg iframe picture source progress meter`.split(/\s+/); + tags.forEach((tagName) => { + const helperName = tagName.charAt(0).toUpperCase() + tagName.slice(1); + if (!(helperName in window)) { + window[helperName] = (props, content) => $html(tagName, props, content); + } + }); + window.SigPro = Object.freeze(registry); + }; + install(SigProCore); +} +export { + $watch, + $router, + $mount, + $if, + $html, + $for, + $ +}; diff --git a/dist/sigpro.esm.min.js b/dist/sigpro.esm.min.js new file mode 100644 index 0000000..5d234a1 --- /dev/null +++ b/dist/sigpro.esm.min.js @@ -0,0 +1 @@ +var p=null,w=null,b=new Set,S=!1,N=new WeakMap,B=()=>{if(S)return;S=!0;while(b.size>0){let s=Array.from(b).sort((r,a)=>(r.depth||0)-(a.depth||0));b.clear();for(let r of s)if(!r._deleted)r()}S=!1},k=(s)=>{if(p&&!p._deleted)s.add(p),p._deps.add(s)},x=(s)=>{for(let r of s){if(r===p||r._deleted)continue;if(r._isComputed){if(r.markDirty(),r._subs)x(r._subs)}else b.add(r)}if(!S)queueMicrotask(B)},O=(s)=>{if(s._cleanups)s._cleanups.forEach((r)=>r()),s._cleanups.clear();s.childNodes?.forEach(O)},A=(s)=>{let r=new Set,a=w,c=document.createElement("div");c.style.display="contents",w={cleanups:r};try{let i=s({onCleanup:(e)=>r.add(e)}),n=(e)=>{if(!e)return;if(e._isRuntime)r.add(e.destroy),c.appendChild(e.container);else if(Array.isArray(e))e.forEach(n);else c.appendChild(e instanceof Node?e:document.createTextNode(String(e)))};n(i)}finally{w=a}return{_isRuntime:!0,container:c,destroy:()=>{r.forEach((i)=>i()),O(c),c.remove()}}},T=(s,r=null)=>{if(typeof s==="function"){let i=new Set,n,e=!0,o=()=>{if(o._deleted)return;o._deps.forEach((t)=>t.delete(o)),o._deps.clear();let f=p;p=o;try{let t=s();if(!Object.is(n,t)||e)n=t,e=!1,x(i)}finally{p=f}};if(o._deps=new Set,o._isComputed=!0,o._subs=i,o._deleted=!1,o.markDirty=()=>e=!0,o.stop=()=>{o._deleted=!0,o._deps.forEach((f)=>f.delete(o)),i.clear()},w)w.cleanups.add(o.stop);return()=>{if(e)o();return k(i),n}}let a=s;if(r)try{let i=localStorage.getItem(r);if(i!==null)a=JSON.parse(i)}catch(i){console.warn("SigPro: LocalStorage locked",i)}let c=new Set;return(...i)=>{if(i.length){let n=typeof i[0]==="function"?i[0](a):i[0];if(!Object.is(a,n)){if(a=n,r)localStorage.setItem(r,JSON.stringify(a));x(c)}}return k(c),a}};var _=(s,r)=>{let a=Array.isArray(s),c=a?r:s,i=a?s:null;if(typeof c!=="function")return()=>{};let n=w,e=()=>{if(e._deleted)return;e._deps.forEach((t)=>t.delete(e)),e._deps.clear(),e._cleanups.forEach((t)=>t()),e._cleanups.clear();let o=p,f=w;p=e,w={cleanups:e._cleanups},e.depth=o?o.depth+1:0;try{if(a)p=null,c(),p=e,i.forEach((t)=>typeof t==="function"&&t());else c()}finally{p=o,w=f}};if(e._deps=new Set,e._cleanups=new Set,e._deleted=!1,e.stop=()=>{if(e._deleted)return;if(e._deleted=!0,b.delete(e),e._deps.forEach((o)=>o.delete(e)),e._cleanups.forEach((o)=>o()),n)n.cleanups.delete(e.stop)},n)n.cleanups.add(e.stop);return e(),e.stop},E=(s,r={},a=[])=>{if(r instanceof Node||Array.isArray(r)||typeof r!=="object")a=r,r={};let i=["svg","path","circle","rect","line","polyline","polygon","g","defs","text","tspan","use"].includes(s),n=i?document.createElementNS("http://www.w3.org/2000/svg",s):document.createElement(s),e=(t,d)=>(t==="src"||t==="href")&&String(d).toLowerCase().includes("javascript:")?"#":d;n._cleanups=new Set;let o=["disabled","checked","required","readonly","selected","multiple","autofocus"];for(let[t,d]of Object.entries(r)){if(t==="ref"){typeof d==="function"?d(n):d.current=n;continue}let m=typeof d==="function";if(["INPUT","TEXTAREA","SELECT"].includes(n.tagName)&&(t==="value"||t==="checked")&&m){n._cleanups.add(_(()=>{let g=d();if(n[t]!==g)n[t]=g}));let l=t==="checked"?"change":"input",y=(g)=>d(g.target[t]);n.addEventListener(l,y),n._cleanups.add(()=>n.removeEventListener(l,y))}else if(t.startsWith("on")){let l=t.slice(2).toLowerCase().split(".")[0],y=(g)=>d(g);n.addEventListener(l,y),n._cleanups.add(()=>n.removeEventListener(l,y))}else if(m)n._cleanups.add(_(()=>{let l=e(t,d());if(t==="class")n.className=l||"";else if(o.includes(t))if(l)n.setAttribute(t,""),n[t]=!0;else n.removeAttribute(t),n[t]=!1;else if(l==null)n.removeAttribute(t);else if(i&&typeof l==="number")n.setAttribute(t,l);else n.setAttribute(t,l)}));else if(o.includes(t))if(d)n.setAttribute(t,""),n[t]=!0;else n.removeAttribute(t),n[t]=!1;else n.setAttribute(t,e(t,d))}let f=(t)=>{if(Array.isArray(t))return t.forEach(f);if(t instanceof Node)n.appendChild(t);else if(typeof t==="function"){let d=document.createTextNode("");n.appendChild(d);let m=[];n._cleanups.add(_(()=>{let u=t(),h=(Array.isArray(u)?u:[u]).map((l)=>l?._isRuntime?l.container:l instanceof Node?l:document.createTextNode(l??""));m.forEach((l)=>{O?.(l),l.remove()}),h.forEach((l)=>d.parentNode?.insertBefore(l,d)),m=h}))}else n.appendChild(document.createTextNode(t??""))};return f(a),n},C=(s,r,a=null,c=null)=>{let i=document.createTextNode(""),n=E("div",{style:"display:contents"},[i]),e=null,o=null;return _(()=>{let f=!!(typeof s==="function"?s():s);if(f===o)return;if(o=f,e&&!f&&c?.out)c.out(e.container,()=>{e.destroy(),e=null});else{if(e)e.destroy();e=null}if(f||!f&&a){let t=f?r:a;if(t){if(e=A(()=>typeof t==="function"?t():t),n.insertBefore(e.container,i),f&&c?.in)c.in(e.container)}}}),n};C.not=(s,r,a)=>C(()=>!(typeof s==="function"?s():s),r,a);var L=(s,r,a,c="div",i={style:"display:contents"})=>{let n=document.createTextNode(""),e=E(c,i,[n]),o=new Map;return _(()=>{let f=(typeof s==="function"?s():s)||[],t=new Map,d=[];for(let u=0;ur(h,u));else o.delete(l);t.set(l,y),d.push(l)}o.forEach((u)=>{u.destroy(),u.container.remove()});let m=n;for(let u=d.length-1;u>=0;u--){let h=t.get(d[u]);if(h.container.nextSibling!==m)e.insertBefore(h.container,m);m=h.container}o=t}),e},v=(s)=>{let r=T(window.location.hash.replace(/^#/,"")||"/");window.addEventListener("hashchange",()=>r(window.location.hash.replace(/^#/,"")||"/"));let a=E("div",{class:"router-outlet"}),c=null;return _([r],async()=>{let i=r(),n=s.find((e)=>{let o=e.path.split("/").filter(Boolean),f=i.split("/").filter(Boolean);return o.length===f.length&&o.every((t,d)=>t.startsWith(":")||t===f[d])})||s.find((e)=>e.path==="*");if(n){let e=n.component;if(typeof e==="function"&&e.toString().includes("import"))e=(await e()).default||await e();let o={};if(n.path.split("/").filter(Boolean).forEach((f,t)=>{if(f.startsWith(":"))o[f.slice(1)]=i.split("/").filter(Boolean)[t]}),c)c.destroy();if(v.params)v.params(o);c=A(()=>{try{return typeof e==="function"?e(o):e}catch(f){return E("div",{class:"p-4 text-error"},"Error loading view")}}),a.appendChild(c.container)}}),a};v.params=T({});v.to=(s)=>window.location.hash=s.replace(/^#?\/?/,"#/");v.back=()=>window.history.back();v.path=()=>window.location.hash.replace(/^#/,"")||"/";var $=(s,r)=>{let a=typeof r==="string"?document.querySelector(r):r;if(!a)return;if(N.has(a))N.get(a).destroy();let c=A(typeof s==="function"?s:()=>s);return a.replaceChildren(c.container),N.set(a,c),c},P={$:T,$watch:_,$html:E,$if:C,$for:L,$router:v,$mount:$};if(typeof window<"u")((r)=>{Object.keys(r).forEach((c)=>{window[c]=r[c]}),"div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer address ul ol li dl dt dd a em strong small i b u mark time sub sup pre code blockquote details summary dialog form label input textarea select button option fieldset legend table thead tbody tfoot tr th td caption img video audio canvas svg iframe picture source progress meter".split(/\s+/).forEach((c)=>{let i=c.charAt(0).toUpperCase()+c.slice(1);if(!(i in window))window[i]=(n,e)=>E(c,n,e)}),window.SigPro=Object.freeze(r)})(P);export{_ as $watch,v as $router,$ as $mount,C as $if,E as $html,L as $for,T as $}; diff --git a/dist/sigpro.js b/dist/sigpro.js index 0df1fa9..a0cb8c8 100644 --- a/dist/sigpro.js +++ b/dist/sigpro.js @@ -241,8 +241,12 @@ content = props; props = {}; } - const el = document.createElement(tag), _sanitize = (key, val) => (key === "src" || key === "href") && String(val).toLowerCase().includes("javascript:") ? "#" : val; + const svgTags = ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "defs", "text", "tspan", "use"]; + const isSVG = svgTags.includes(tag); + const el = isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); + const _sanitize = (key, val) => (key === "src" || key === "href") && String(val).toLowerCase().includes("javascript:") ? "#" : val; el._cleanups = new Set; + const boolAttrs = ["disabled", "checked", "required", "readonly", "selected", "multiple", "autofocus"]; for (let [key, val] of Object.entries(props)) { if (key === "ref") { typeof val === "function" ? val(el) : val.current = el; @@ -265,13 +269,38 @@ } else if (isSignal) { el._cleanups.add($watch(() => { const currentVal = _sanitize(key, val()); - if (key === "class") + if (key === "class") { el.className = currentVal || ""; - else - currentVal == null ? el.removeAttribute(key) : el.setAttribute(key, currentVal); + } else if (boolAttrs.includes(key)) { + if (currentVal) { + el.setAttribute(key, ""); + el[key] = true; + } else { + el.removeAttribute(key); + el[key] = false; + } + } else { + if (currentVal == null) { + el.removeAttribute(key); + } else if (isSVG && typeof currentVal === "number") { + el.setAttribute(key, currentVal); + } else { + el.setAttribute(key, currentVal); + } + } })); } else { - el.setAttribute(key, _sanitize(key, val)); + if (boolAttrs.includes(key)) { + if (val) { + el.setAttribute(key, ""); + el[key] = true; + } else { + el.removeAttribute(key); + el[key] = false; + } + } else { + el.setAttribute(key, _sanitize(key, val)); + } } } const append = (child) => { @@ -286,7 +315,7 @@ el._cleanups.add($watch(() => { const res = child(), next = (Array.isArray(res) ? res : [res]).map((i) => i?._isRuntime ? i.container : i instanceof Node ? i : document.createTextNode(i ?? "")); nodes.forEach((n) => { - sweep(n); + sweep?.(n); n.remove(); }); next.forEach((n) => marker.parentNode?.insertBefore(n, marker)); @@ -298,65 +327,73 @@ append(content); return el; }; - var $if = (condition, thenVal, otherwiseVal = null) => { + var $if = (condition, thenVal, otherwiseVal = null, transition = null) => { const marker = document.createTextNode(""); const container = $html("div", { style: "display:contents" }, [marker]); let current = null, last = null; $watch(() => { const state = !!(typeof condition === "function" ? condition() : condition); - if (state !== last) { - last = state; + if (state === last) + return; + last = state; + if (current && !state && transition?.out) { + transition.out(current.container, () => { + current.destroy(); + current = null; + }); + } else { if (current) current.destroy(); + current = null; + } + if (state || !state && otherwiseVal) { const branch = state ? thenVal : otherwiseVal; if (branch) { current = _view(() => typeof branch === "function" ? branch() : branch); container.insertBefore(current.container, marker); + if (state && transition?.in) + transition.in(current.container); } } }); return container; }; $if.not = (condition, thenVal, otherwiseVal) => $if(() => !(typeof condition === "function" ? condition() : condition), thenVal, otherwiseVal); - var $for = (source, render, keyFn) => { - const marker = document.createComment("sigpro-for-end"); + var $for = (source, render, keyFn, tag = "div", props = { style: "display:contents" }) => { + const marker = document.createTextNode(""); + const container = $html(tag, props, [marker]); let cache = new Map; $watch(() => { const items = (typeof source === "function" ? source() : source) || []; - const parent = marker.parentNode; - if (!parent) - return; const newCache = new Map; const newOrder = []; for (let i = 0;i < items.length; i++) { const item = items[i]; const key = keyFn ? keyFn(item, i) : i; - let cached = cache.get(key); - if (!cached) { - const view = _view(() => render(item, i)); - const node = view.container.firstElementChild || view.container.firstChild; - cached = { node, destroy: view.destroy }; + let run = cache.get(key); + if (!run) { + run = _view(() => render(item, i)); } else { cache.delete(key); } - newCache.set(key, cached); - newOrder.push(cached.node); + newCache.set(key, run); + newOrder.push(key); } - cache.forEach((c) => { - c.destroy(); - c.node.remove(); + cache.forEach((run) => { + run.destroy(); + run.container.remove(); }); - let currentAnchor = marker; + let anchor = marker; for (let i = newOrder.length - 1;i >= 0; i--) { - const node = newOrder[i]; - if (node.nextSibling !== currentAnchor) { - parent.insertBefore(node, currentAnchor); + const run = newCache.get(newOrder[i]); + if (run.container.nextSibling !== anchor) { + container.insertBefore(run.container, anchor); } - currentAnchor = node; + anchor = run.container; } cache = newCache; }); - return marker; + return container; }; var $router = (routes) => { const sPath = $(window.location.hash.replace(/^#/, "") || "/"); diff --git a/dist/sigpro.min.js b/dist/sigpro.min.js index e757e29..23118e5 100644 --- a/dist/sigpro.min.js +++ b/dist/sigpro.min.js @@ -1 +1 @@ -(()=>{var{defineProperty:M,getOwnPropertyNames:w,getOwnPropertyDescriptor:k}=Object,y=Object.prototype.hasOwnProperty;var b=new WeakMap,g=(K)=>{var J=b.get(K),Z;if(J)return J;if(J=M({},"__esModule",{value:!0}),K&&typeof K==="object"||typeof K==="function")w(K).map((q)=>!y.call(J,q)&&M(J,q,{get:()=>K[q],enumerable:!(Z=k(K,q))||Z.enumerable}));return b.set(K,J),J};var v=(K,J)=>{for(var Z in J)M(K,Z,{get:J[Z],enumerable:!0,configurable:!0,set:(q)=>J[Z]=()=>q})};var d={};v(d,{$watch:()=>Q,$router:()=>x,$mount:()=>$,$if:()=>T,$html:()=>C,$for:()=>E,$:()=>_});var U=null,L=null,P=new Set,A=!1,S=new WeakMap,m=()=>{if(A)return;A=!0;while(P.size>0){let K=Array.from(P).sort((J,Z)=>(J.depth||0)-(Z.depth||0));P.clear();for(let J of K)if(!J._deleted)J()}A=!1},O=(K)=>{if(U&&!U._deleted)K.add(U),U._deps.add(K)},V=(K)=>{for(let J of K){if(J===U||J._deleted)continue;if(J._isComputed){if(J.markDirty(),J._subs)V(J._subs)}else P.add(J)}if(!A)queueMicrotask(m)},N=(K)=>{if(K._cleanups)K._cleanups.forEach((J)=>J()),K._cleanups.clear();K.childNodes?.forEach(N)},F=(K)=>{let J=new Set,Z=L,q=document.createElement("div");q.style.display="contents",L={cleanups:J};try{let W=K({onCleanup:(j)=>J.add(j)}),Y=(j)=>{if(!j)return;if(j._isRuntime)J.add(j.destroy),q.appendChild(j.container);else if(Array.isArray(j))j.forEach(Y);else q.appendChild(j instanceof Node?j:document.createTextNode(String(j)))};Y(W)}finally{L=Z}return{_isRuntime:!0,container:q,destroy:()=>{J.forEach((W)=>W()),N(q),q.remove()}}},_=(K,J=null)=>{if(typeof K==="function"){let W=new Set,Y,j=!0,X=()=>{if(X._deleted)return;X._deps.forEach((G)=>G.delete(X)),X._deps.clear();let z=U;U=X;try{let G=K();if(!Object.is(Y,G)||j)Y=G,j=!1,V(W)}finally{U=z}};if(X._deps=new Set,X._isComputed=!0,X._subs=W,X._deleted=!1,X.markDirty=()=>j=!0,X.stop=()=>{X._deleted=!0,X._deps.forEach((z)=>z.delete(X)),W.clear()},L)L.cleanups.add(X.stop);return()=>{if(j)X();return O(W),Y}}let Z=K;if(J)try{let W=localStorage.getItem(J);if(W!==null)Z=JSON.parse(W)}catch(W){console.warn("SigPro: LocalStorage locked",W)}let q=new Set;return(...W)=>{if(W.length){let Y=typeof W[0]==="function"?W[0](Z):W[0];if(!Object.is(Z,Y)){if(Z=Y,J)localStorage.setItem(J,JSON.stringify(Z));V(q)}}return O(q),Z}},Q=(K,J)=>{let Z=Array.isArray(K),q=Z?J:K,W=Z?K:null;if(typeof q!=="function")return()=>{};let Y=L,j=()=>{if(j._deleted)return;j._deps.forEach((G)=>G.delete(j)),j._deps.clear(),j._cleanups.forEach((G)=>G()),j._cleanups.clear();let X=U,z=L;U=j,L={cleanups:j._cleanups},j.depth=X?X.depth+1:0;try{if(Z)U=null,q(),U=j,W.forEach((G)=>typeof G==="function"&&G());else q()}finally{U=X,L=z}};if(j._deps=new Set,j._cleanups=new Set,j._deleted=!1,j.stop=()=>{if(j._deleted)return;if(j._deleted=!0,P.delete(j),j._deps.forEach((X)=>X.delete(j)),j._cleanups.forEach((X)=>X()),Y)Y.cleanups.delete(j.stop)},Y)Y.cleanups.add(j.stop);return j(),j.stop},C=(K,J={},Z=[])=>{if(J instanceof Node||Array.isArray(J)||typeof J!=="object")Z=J,J={};let q=document.createElement(K),W=(j,X)=>(j==="src"||j==="href")&&String(X).toLowerCase().includes("javascript:")?"#":X;q._cleanups=new Set;for(let[j,X]of Object.entries(J)){if(j==="ref"){typeof X==="function"?X(q):X.current=q;continue}let z=typeof X==="function";if(["INPUT","TEXTAREA","SELECT"].includes(q.tagName)&&(j==="value"||j==="checked")&&z){q._cleanups.add(Q(()=>{let H=X();if(q[j]!==H)q[j]=H}));let B=j==="checked"?"change":"input",I=(H)=>X(H.target[j]);q.addEventListener(B,I),q._cleanups.add(()=>q.removeEventListener(B,I))}else if(j.startsWith("on")){let B=j.slice(2).toLowerCase().split(".")[0],I=(H)=>X(H);q.addEventListener(B,I),q._cleanups.add(()=>q.removeEventListener(B,I))}else if(z)q._cleanups.add(Q(()=>{let B=W(j,X());if(j==="class")q.className=B||"";else B==null?q.removeAttribute(j):q.setAttribute(j,B)}));else q.setAttribute(j,W(j,X))}let Y=(j)=>{if(Array.isArray(j))return j.forEach(Y);if(j instanceof Node)q.appendChild(j);else if(typeof j==="function"){let X=document.createTextNode("");q.appendChild(X);let z=[];q._cleanups.add(Q(()=>{let G=j(),R=(Array.isArray(G)?G:[G]).map((B)=>B?._isRuntime?B.container:B instanceof Node?B:document.createTextNode(B??""));z.forEach((B)=>{N(B),B.remove()}),R.forEach((B)=>X.parentNode?.insertBefore(B,X)),z=R}))}else q.appendChild(document.createTextNode(j??""))};return Y(Z),q},T=(K,J,Z=null)=>{let q=document.createTextNode(""),W=C("div",{style:"display:contents"},[q]),Y=null,j=null;return Q(()=>{let X=!!(typeof K==="function"?K():K);if(X!==j){if(j=X,Y)Y.destroy();let z=X?J:Z;if(z)Y=F(()=>typeof z==="function"?z():z),W.insertBefore(Y.container,q)}}),W};T.not=(K,J,Z)=>T(()=>!(typeof K==="function"?K():K),J,Z);var E=(K,J,Z)=>{let q=document.createComment("sigpro-for-end"),W=new Map;return Q(()=>{let Y=(typeof K==="function"?K():K)||[],j=q.parentNode;if(!j)return;let X=new Map,z=[];for(let R=0;RJ(B,R));H={node:D.container.firstElementChild||D.container.firstChild,destroy:D.destroy}}else W.delete(I);X.set(I,H),z.push(H.node)}W.forEach((R)=>{R.destroy(),R.node.remove()});let G=q;for(let R=z.length-1;R>=0;R--){let B=z[R];if(B.nextSibling!==G)j.insertBefore(B,G);G=B}W=X}),q},x=(K)=>{let J=_(window.location.hash.replace(/^#/,"")||"/");window.addEventListener("hashchange",()=>J(window.location.hash.replace(/^#/,"")||"/"));let Z=C("div",{class:"router-outlet"}),q=null;return Q([J],async()=>{let W=J(),Y=K.find((j)=>{let X=j.path.split("/").filter(Boolean),z=W.split("/").filter(Boolean);return X.length===z.length&&X.every((G,R)=>G.startsWith(":")||G===z[R])})||K.find((j)=>j.path==="*");if(Y){let j=Y.component;if(typeof j==="function"&&j.toString().includes("import"))j=(await j()).default||await j();let X={};if(Y.path.split("/").filter(Boolean).forEach((z,G)=>{if(z.startsWith(":"))X[z.slice(1)]=W.split("/").filter(Boolean)[G]}),q)q.destroy();if(x.params)x.params(X);q=F(()=>{try{return typeof j==="function"?j(X):j}catch(z){return C("div",{class:"p-4 text-error"},"Error loading view")}}),Z.appendChild(q.container)}}),Z};x.params=_({});x.to=(K)=>window.location.hash=K.replace(/^#?\/?/,"#/");x.back=()=>window.history.back();x.path=()=>window.location.hash.replace(/^#/,"")||"/";var $=(K,J)=>{let Z=typeof J==="string"?document.querySelector(J):J;if(!Z)return;if(S.has(Z))S.get(Z).destroy();let q=F(typeof K==="function"?K:()=>K);return Z.replaceChildren(q.container),S.set(Z,q),q},h={$:_,$watch:Q,$html:C,$if:T,$for:E,$router:x,$mount:$};if(typeof window<"u")((J)=>{Object.keys(J).forEach((q)=>{window[q]=J[q]}),"div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer address ul ol li dl dt dd a em strong small i b u mark time sub sup pre code blockquote details summary dialog form label input textarea select button option fieldset legend table thead tbody tfoot tr th td caption img video audio canvas svg iframe picture source progress meter".split(/\s+/).forEach((q)=>{let W=q.charAt(0).toUpperCase()+q.slice(1);if(!(W in window))window[W]=(Y,j)=>C(q,Y,j)}),window.SigPro=Object.freeze(J)})(h);})(); +(()=>{var{defineProperty:C,getOwnPropertyNames:I,getOwnPropertyDescriptor:M}=Object,R=Object.prototype.hasOwnProperty;var B=new WeakMap,j=(s)=>{var t=B.get(s),c;if(t)return t;if(t=C({},"__esModule",{value:!0}),s&&typeof s==="object"||typeof s==="function")I(s).map((o)=>!R.call(t,o)&&C(t,o,{get:()=>s[o],enumerable:!(c=M(s,o))||c.enumerable}));return B.set(s,t),t};var W=(s,t)=>{for(var c in t)C(s,c,{get:t[c],enumerable:!0,configurable:!0,set:(o)=>t[c]=()=>o})};var z={};W(z,{$watch:()=>_,$router:()=>v,$mount:()=>P,$if:()=>A,$html:()=>g,$for:()=>$,$:()=>x});var p=null,w=null,b=new Set,S=!1,O=new WeakMap,q=()=>{if(S)return;S=!0;while(b.size>0){let s=Array.from(b).sort((t,c)=>(t.depth||0)-(c.depth||0));b.clear();for(let t of s)if(!t._deleted)t()}S=!1},L=(s)=>{if(p&&!p._deleted)s.add(p),p._deps.add(s)},T=(s)=>{for(let t of s){if(t===p||t._deleted)continue;if(t._isComputed){if(t.markDirty(),t._subs)T(t._subs)}else b.add(t)}if(!S)queueMicrotask(q)},k=(s)=>{if(s._cleanups)s._cleanups.forEach((t)=>t()),s._cleanups.clear();s.childNodes?.forEach(k)},N=(s)=>{let t=new Set,c=w,o=document.createElement("div");o.style.display="contents",w={cleanups:t};try{let i=s({onCleanup:(e)=>t.add(e)}),r=(e)=>{if(!e)return;if(e._isRuntime)t.add(e.destroy),o.appendChild(e.container);else if(Array.isArray(e))e.forEach(r);else o.appendChild(e instanceof Node?e:document.createTextNode(String(e)))};r(i)}finally{w=c}return{_isRuntime:!0,container:o,destroy:()=>{t.forEach((i)=>i()),k(o),o.remove()}}},x=(s,t=null)=>{if(typeof s==="function"){let i=new Set,r,e=!0,a=()=>{if(a._deleted)return;a._deps.forEach((n)=>n.delete(a)),a._deps.clear();let f=p;p=a;try{let n=s();if(!Object.is(r,n)||e)r=n,e=!1,T(i)}finally{p=f}};if(a._deps=new Set,a._isComputed=!0,a._subs=i,a._deleted=!1,a.markDirty=()=>e=!0,a.stop=()=>{a._deleted=!0,a._deps.forEach((f)=>f.delete(a)),i.clear()},w)w.cleanups.add(a.stop);return()=>{if(e)a();return L(i),r}}let c=s;if(t)try{let i=localStorage.getItem(t);if(i!==null)c=JSON.parse(i)}catch(i){console.warn("SigPro: LocalStorage locked",i)}let o=new Set;return(...i)=>{if(i.length){let r=typeof i[0]==="function"?i[0](c):i[0];if(!Object.is(c,r)){if(c=r,t)localStorage.setItem(t,JSON.stringify(c));T(o)}}return L(o),c}};var _=(s,t)=>{let c=Array.isArray(s),o=c?t:s,i=c?s:null;if(typeof o!=="function")return()=>{};let r=w,e=()=>{if(e._deleted)return;e._deps.forEach((n)=>n.delete(e)),e._deps.clear(),e._cleanups.forEach((n)=>n()),e._cleanups.clear();let a=p,f=w;p=e,w={cleanups:e._cleanups},e.depth=a?a.depth+1:0;try{if(c)p=null,o(),p=e,i.forEach((n)=>typeof n==="function"&&n());else o()}finally{p=a,w=f}};if(e._deps=new Set,e._cleanups=new Set,e._deleted=!1,e.stop=()=>{if(e._deleted)return;if(e._deleted=!0,b.delete(e),e._deps.forEach((a)=>a.delete(e)),e._cleanups.forEach((a)=>a()),r)r.cleanups.delete(e.stop)},r)r.cleanups.add(e.stop);return e(),e.stop},g=(s,t={},c=[])=>{if(t instanceof Node||Array.isArray(t)||typeof t!=="object")c=t,t={};let i=["svg","path","circle","rect","line","polyline","polygon","g","defs","text","tspan","use"].includes(s),r=i?document.createElementNS("http://www.w3.org/2000/svg",s):document.createElement(s),e=(n,d)=>(n==="src"||n==="href")&&String(d).toLowerCase().includes("javascript:")?"#":d;r._cleanups=new Set;let a=["disabled","checked","required","readonly","selected","multiple","autofocus"];for(let[n,d]of Object.entries(t)){if(n==="ref"){typeof d==="function"?d(r):d.current=r;continue}let m=typeof d==="function";if(["INPUT","TEXTAREA","SELECT"].includes(r.tagName)&&(n==="value"||n==="checked")&&m){r._cleanups.add(_(()=>{let E=d();if(r[n]!==E)r[n]=E}));let l=n==="checked"?"change":"input",y=(E)=>d(E.target[n]);r.addEventListener(l,y),r._cleanups.add(()=>r.removeEventListener(l,y))}else if(n.startsWith("on")){let l=n.slice(2).toLowerCase().split(".")[0],y=(E)=>d(E);r.addEventListener(l,y),r._cleanups.add(()=>r.removeEventListener(l,y))}else if(m)r._cleanups.add(_(()=>{let l=e(n,d());if(n==="class")r.className=l||"";else if(a.includes(n))if(l)r.setAttribute(n,""),r[n]=!0;else r.removeAttribute(n),r[n]=!1;else if(l==null)r.removeAttribute(n);else if(i&&typeof l==="number")r.setAttribute(n,l);else r.setAttribute(n,l)}));else if(a.includes(n))if(d)r.setAttribute(n,""),r[n]=!0;else r.removeAttribute(n),r[n]=!1;else r.setAttribute(n,e(n,d))}let f=(n)=>{if(Array.isArray(n))return n.forEach(f);if(n instanceof Node)r.appendChild(n);else if(typeof n==="function"){let d=document.createTextNode("");r.appendChild(d);let m=[];r._cleanups.add(_(()=>{let u=n(),h=(Array.isArray(u)?u:[u]).map((l)=>l?._isRuntime?l.container:l instanceof Node?l:document.createTextNode(l??""));m.forEach((l)=>{k?.(l),l.remove()}),h.forEach((l)=>d.parentNode?.insertBefore(l,d)),m=h}))}else r.appendChild(document.createTextNode(n??""))};return f(c),r},A=(s,t,c=null,o=null)=>{let i=document.createTextNode(""),r=g("div",{style:"display:contents"},[i]),e=null,a=null;return _(()=>{let f=!!(typeof s==="function"?s():s);if(f===a)return;if(a=f,e&&!f&&o?.out)o.out(e.container,()=>{e.destroy(),e=null});else{if(e)e.destroy();e=null}if(f||!f&&c){let n=f?t:c;if(n){if(e=N(()=>typeof n==="function"?n():n),r.insertBefore(e.container,i),f&&o?.in)o.in(e.container)}}}),r};A.not=(s,t,c)=>A(()=>!(typeof s==="function"?s():s),t,c);var $=(s,t,c,o="div",i={style:"display:contents"})=>{let r=document.createTextNode(""),e=g(o,i,[r]),a=new Map;return _(()=>{let f=(typeof s==="function"?s():s)||[],n=new Map,d=[];for(let u=0;ut(h,u));else a.delete(l);n.set(l,y),d.push(l)}a.forEach((u)=>{u.destroy(),u.container.remove()});let m=r;for(let u=d.length-1;u>=0;u--){let h=n.get(d[u]);if(h.container.nextSibling!==m)e.insertBefore(h.container,m);m=h.container}a=n}),e},v=(s)=>{let t=x(window.location.hash.replace(/^#/,"")||"/");window.addEventListener("hashchange",()=>t(window.location.hash.replace(/^#/,"")||"/"));let c=g("div",{class:"router-outlet"}),o=null;return _([t],async()=>{let i=t(),r=s.find((e)=>{let a=e.path.split("/").filter(Boolean),f=i.split("/").filter(Boolean);return a.length===f.length&&a.every((n,d)=>n.startsWith(":")||n===f[d])})||s.find((e)=>e.path==="*");if(r){let e=r.component;if(typeof e==="function"&&e.toString().includes("import"))e=(await e()).default||await e();let a={};if(r.path.split("/").filter(Boolean).forEach((f,n)=>{if(f.startsWith(":"))a[f.slice(1)]=i.split("/").filter(Boolean)[n]}),o)o.destroy();if(v.params)v.params(a);o=N(()=>{try{return typeof e==="function"?e(a):e}catch(f){return g("div",{class:"p-4 text-error"},"Error loading view")}}),c.appendChild(o.container)}}),c};v.params=x({});v.to=(s)=>window.location.hash=s.replace(/^#?\/?/,"#/");v.back=()=>window.history.back();v.path=()=>window.location.hash.replace(/^#/,"")||"/";var P=(s,t)=>{let c=typeof t==="string"?document.querySelector(t):t;if(!c)return;if(O.has(c))O.get(c).destroy();let o=N(typeof s==="function"?s:()=>s);return c.replaceChildren(o.container),O.set(c,o),o},D={$:x,$watch:_,$html:g,$if:A,$for:$,$router:v,$mount:P};if(typeof window<"u")((t)=>{Object.keys(t).forEach((o)=>{window[o]=t[o]}),"div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer address ul ol li dl dt dd a em strong small i b u mark time sub sup pre code blockquote details summary dialog form label input textarea select button option fieldset legend table thead tbody tfoot tr th td caption img video audio canvas svg iframe picture source progress meter".split(/\s+/).forEach((o)=>{let i=o.charAt(0).toUpperCase()+o.slice(1);if(!(i in window))window[i]=(r,e)=>g(o,r,e)}),window.SigPro=Object.freeze(t)})(D);})(); diff --git a/package.json b/package.json index b05802e..72ab650 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,13 @@ "type": "module", "license": "MIT", "main": "./index.js", - "module": "./index.js", + "module": "./dist/sigpro.esm.min.js", "unpkg": "./dist/sigpro.min.js", "jsdelivr": "./dist/sigpro.min.js", "exports": { ".": { - "import": "./index.js", + "import": "./dist/sigpro.esm.min.js", + "require": "./index.js", "script": "./dist/sigpro.js", "types": "./sigpro/sigpro.d.ts" }, @@ -33,9 +34,15 @@ "url": "https://github.com/natxocc/sigpro/issues" }, "scripts": { - "build": "bun build ./index.js --bundle --outfile=./dist/sigpro.js --format=iife --global-name=SigPro && bun build ./index.js --bundle --outfile=./dist/sigpro.min.js --bundle --format=iife --global-name=SigPro --minify", - "prepublishOnly": "bun run build", - "docs": "bun x serve docs" + "clean": "rm -rf dist", + "prebuild": "npm run clean", + "build:iife": "bun build ./index.js --bundle --outfile=./dist/sigpro.js --format=iife --global-name=SigPro", + "build:iife:min": "bun build ./index.js --bundle --outfile=./dist/sigpro.min.js --format=iife --global-name=SigPro --minify", + "build:esm": "bun build ./index.js --bundle --outfile=./dist/sigpro.esm.js --format=esm", + "build:esm:min": "bun build ./index.js --bundle --outfile=./dist/sigpro.esm.min.js --format=esm --minify", + "build": "npm run build:iife && npm run build:iife:min && npm run build:esm && npm run build:esm:min", + "docs": "bun x serve docs", + "prepublishOnly": "npm run build" }, "keywords": [ "signals",