Megacompact f1

This commit is contained in:
2026-05-09 16:06:54 +02:00
parent 645f9b42b0
commit a0701422f5
13 changed files with 1430 additions and 1843 deletions

View File

@@ -3,7 +3,7 @@ Blazing fast, zero-overhead, vanilla JS renderer with atomic reactivity.
# `SigPro` # `SigPro`
[![npm version](https://img.shields.io/npm/v/sigpro.svg)](https://www.npmjs.com/package/sigpro) [![npm version](https://img.shields.io/npm/v/sigpro.svg)](https://www.npmjs.com/package/sigpro)
![js size](https://img.shields.io/badge/js_size-2.8_kB_brotli-blue) ![js size](https://img.shields.io/badge/js_size-2.7_kB_brotli-blue)
[![license](https://img.shields.io/npm/l/sigpro)](https://github.com/natxocc/sigpro/blob/main/LICENSE) [![license](https://img.shields.io/npm/l/sigpro)](https://github.com/natxocc/sigpro/blob/main/LICENSE)
[**Explore the Docs →**](https://sigpro.natxocc.com/#/) [**Explore the Docs →**](https://sigpro.natxocc.com/#/)

595
dist/sigpro.esm.js vendored
View File

@@ -1,443 +1,384 @@
// src/sigpro.js // src/sigpro.js
var isFunc = (f) => typeof f === "function"; var isFunc = (f) => typeof f == "function";
var isObj = (o) => o && typeof o === "object"; var isObj = (o) => o && typeof o == "object";
var isArr = Array.isArray; var isArr = Array.isArray;
var doc = typeof document !== "undefined" ? document : null; var doc = typeof document < "u" ? document : null;
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n)); var txt = (s) => doc.createTextNode(s == null ? "" : String(s));
var activeEffect = null; var toNd = (n) => n?._rt ? n._cnt : n instanceof Node ? n : txt(n);
var activeOwner = null; var Fragment = (p) => p.children;
var isFlushing = false; var val = (v) => isFunc(v) ? v() : v;
var batchDepth = 0; var aEff = null;
var effectQueue = new Set; var aOwn = null;
var MOUNTED_NODES = new WeakMap; var isFlushing = 0;
var bDepth = 0;
var eQ = new Set;
var MOUNTED = new WeakMap;
var SVG_NS = "http://www.w3.org/2000/svg"; var SVG_NS = "http://www.w3.org/2000/svg";
var XLINK_NS = "http://www.w3.org/1999/xlink"; var XLINK = "http://www.w3.org/1999/xlink";
var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")); var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","));
var dispose = (eff) => { var DANG_ATTR = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]);
if (!eff || eff._disposed) var clr = (s) => {
if (s) {
s.forEach((f) => f());
s.clear();
}
};
var dispose = (e) => {
if (!e || e._x)
return; return;
eff._disposed = true; e._x = 1;
const stack = [eff]; let st = [e], c;
while (stack.length) { while (c = st.pop()) {
const e = stack.pop(); clr(c._c);
if (e._cleanups) { if (c._ch) {
e._cleanups.forEach((fn) => fn()); c._ch.forEach((x) => st.push(x));
e._cleanups.clear(); c._ch.clear();
} }
if (e._children) { if (c._d) {
e._children.forEach((child) => stack.push(child)); c._d.forEach((d) => d.delete(c));
e._children.clear(); c._d.clear();
}
if (e._deps) {
e._deps.forEach((depSet) => depSet.delete(e));
e._deps.clear();
} }
} }
}; };
var onUnmount = (fn) => { var onUnmount = (f) => aOwn && (aOwn._c ||= new Set).add(f);
if (activeOwner) var untrack = (f) => {
(activeOwner._cleanups ||= new Set).add(fn); let p = aEff;
}; aEff = null;
var untrack = (fn) => {
const p = activeEffect;
activeEffect = null;
try { try {
return fn(); return f();
} finally { } finally {
activeEffect = p; aEff = p;
} }
}; };
var createEffect = (fn, isComputed = false) => { var createEffect = (f, isC = 0) => {
const effect = () => { const e = () => {
if (effect._disposed) if (e._x)
return; return;
if (effect._deps) if (e._d)
effect._deps.forEach((s) => s.delete(effect)); e._d.forEach((s) => s.delete(e));
if (effect._cleanups) { clr(e._c);
effect._cleanups.forEach((c) => c()); let pE = aEff, pO = aOwn;
effect._cleanups.clear(); aEff = aOwn = e;
}
const prevEffect = activeEffect;
const prevOwner = activeOwner;
activeEffect = activeOwner = effect;
try { try {
return effect._result = fn(); return e._res = f();
} catch (e) { } catch (err) {
console.error("[SigPro]", e); console.error("[SigPro]", err);
} finally { } finally {
activeEffect = prevEffect; aEff = pE;
activeOwner = prevOwner; aOwn = pO;
} }
}; };
effect._deps = effect._cleanups = effect._children = null; e._d = e._c = e._ch = null;
effect._disposed = false; e._x = 0;
effect._isComputed = isComputed; e._iC = isC;
effect._depth = activeEffect ? activeEffect._depth + 1 : 0; e._dp = aEff ? aEff._dp + 1 : 0;
effect._mounts = []; e._m = [];
effect._parent = activeOwner; e._p = aOwn;
if (activeOwner) if (aOwn)
(activeOwner._children ||= new Set).add(effect); (aOwn._ch ||= new Set).add(e);
return effect; return e;
}; };
var flush = () => { var flush = () => {
if (isFlushing) if (isFlushing)
return; return;
isFlushing = true; isFlushing = 1;
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth); let q = [...eQ].sort((a, b) => a._dp - b._dp);
effectQueue.clear(); eQ.clear();
for (const e of sorted) for (let e of q)
if (!e._disposed) if (!e._x)
e(); e();
isFlushing = false; isFlushing = 0;
}; };
var batch = (fn) => { var batch = (f) => {
batchDepth++; bDepth++;
try { try {
return fn(); return f();
} finally { } finally {
batchDepth--; if (!--bDepth && eQ.size && !isFlushing)
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing)
flush(); flush();
} }
}; };
var trackUpdate = (subs, trigger = false) => { var trkUpd = (s, trg = 0) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trg && aEff && !aEff._x) {
subs.add(activeEffect); s.add(aEff);
(activeEffect._deps ||= new Set).add(subs); (aEff._d ||= new Set).add(s);
} else if (trigger && subs.size > 0) { } else if (trg && s.size) {
let hasQueue = false; let q = 0;
for (const e of subs) { for (let e of s) {
if (e === activeEffect || e._disposed) if (e === aEff || e._x)
continue; continue;
if (e._isComputed) { if (e._iC) {
e._dirty = true; e._dt = 1;
if (e._subs) if (e._sb)
trackUpdate(e._subs, true); trkUpd(e._sb, 1);
} else { } else {
effectQueue.add(e); eQ.add(e);
hasQueue = true; q = 1;
} }
} }
if (hasQueue && !isFlushing && batchDepth === 0) if (q && !isFlushing && !bDepth)
queueMicrotask(flush); queueMicrotask(flush);
} }
}; };
var $ = (val, key = null) => { var $ = (v, k = null) => {
const subs = new Set; let s = new Set;
if (isFunc(val)) { if (isFunc(v)) {
let cache; let c, cp = () => {
const computed = () => { if (cp._dt) {
if (computed._dirty) { let p = aEff;
const prev = activeEffect; aEff = cp;
activeEffect = computed;
try { try {
const next = val(); let n = v();
if (!Object.is(cache, next)) { if (!Object.is(c, n)) {
cache = next; c = n;
trackUpdate(subs, true); trkUpd(s, 1);
} }
} finally { } finally {
activeEffect = prev; aEff = p;
} }
computed._dirty = false; cp._dt = 0;
} }
trackUpdate(subs); trkUpd(s);
return cache; return c;
}; };
computed._isComputed = true; cp._iC = cp._dt = 1;
computed._subs = subs; cp._sb = s;
computed._dirty = true; cp._d = null;
computed._deps = null; cp._x = 0;
computed._disposed = false; return cp;
return computed;
} }
if (key) if (k)
try { try {
val = JSON.parse(localStorage.getItem(key)) ?? val; v = JSON.parse(localStorage.getItem(k)) ?? v;
} catch (e) {} } catch (e) {}
return (...args) => { return (...a) => {
if (args.length) { if (a.length) {
const next = isFunc(args[0]) ? args[0](val) : args[0]; let n = isFunc(a[0]) ? a[0](v) : a[0];
if (!Object.is(val, next)) { if (!Object.is(v, n)) {
val = next; v = n;
if (key) if (k)
localStorage.setItem(key, JSON.stringify(val)); localStorage.setItem(k, JSON.stringify(v));
trackUpdate(subs, true); trkUpd(s, 1);
} }
} }
trackUpdate(subs); trkUpd(s);
return val; return v;
}; };
}; };
var watch = (sources, cb) => { var watch = (src, cb) => {
if (cb === undefined) { let e = createEffect(cb ? () => {
const effect2 = createEffect(sources); let v = isArr(src) ? src.map((s) => s()) : src();
effect2(); untrack(() => cb(v));
return () => dispose(effect2); } : src);
} e();
const effect = createEffect(() => { return () => dispose(e);
const vals = isArr(sources) ? sources.map((s) => s()) : sources();
untrack(() => cb(vals));
});
effect();
return () => dispose(effect);
}; };
var cleanupNode = (node) => { var clnNd = (n) => {
if (!node) if (!n)
return; return;
if (node._cleanups) { clr(n._c);
node._cleanups.forEach((fn) => fn()); if (n._oE)
node._cleanups.clear(); dispose(n._oE);
} if (n.childNodes)
if (node._ownerEffect) n.childNodes.forEach(clnNd);
dispose(node._ownerEffect);
if (node.childNodes)
node.childNodes.forEach((n) => cleanupNode(n));
}; };
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; var valAtt = (k, v) => v == null || v === false ? null : (DANG_ATTR.has(k) || k.startsWith("on")) && /^\s*(javascript|data|vbscript):/i.test(String(v)) ? "#" : v;
var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); var h = (tag, prp = {}, ch = []) => {
var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on"); if (prp instanceof Node || isArr(prp) || !isObj(prp)) {
var validateAttr = (key, val) => { ch = prp;
if (val == null || val === false) prp = {};
return null;
if (isDangerousAttr(key)) {
const sVal = String(val);
if (DANGEROUS_PROTOCOL.test(sVal))
return "#";
}
return val;
};
var h = (tag, props = {}, children = []) => {
if (props instanceof Node || isArr(props) || !isObj(props)) {
children = props;
props = {};
} }
if (isFunc(tag)) { if (isFunc(tag)) {
const effect = createEffect(() => { let e = createEffect(() => e._res = tag(prp, { children: ch, emit: (ev, ...a) => prp[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...a) }));
const result2 = tag(props, { e();
children, if (e._res == null)
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
});
effect._result = result2;
return result2;
});
effect();
const result = effect._result;
if (result == null)
return null; return null;
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result)); let nd = e._res instanceof Node || isArr(e._res) && e._res.every((n) => n instanceof Node) ? e._res : txt(e._res);
const attach = (n) => { let att = (n) => {
if (isObj(n) && !n._isRuntime) { if (isObj(n) && !n._rt) {
n._mounts = effect._mounts || []; n._m = e._m || [];
n._cleanups = effect._cleanups || new Set; n._c = e._c || new Set;
n._ownerEffect = effect; n._oE = e;
} }
}; };
isArr(node) ? node.forEach(attach) : attach(node); isArr(nd) ? nd.forEach(att) : att(nd);
return node; return nd;
} }
const isSVG = SVG_TAGS.has(tag); let isS = SVG_TAGS.has(tag), el = isS ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag);
const el = isSVG ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag); el._c = new Set;
el._cleanups = new Set; for (let k in prp) {
for (const k of Object.keys(props)) { let v = prp[k];
let v = props[k];
if (k === "ref") { if (k === "ref") {
isFunc(v) ? v(el) : v.current = el; isFunc(v) ? v(el) : v.current = el;
continue; continue;
} }
if (isSVG && k.startsWith("xlink:")) { if (isS && k.startsWith("xlink:")) {
const cleanVal = validateAttr(k.slice(6), v); let cv = valAtt(k.slice(6), v);
cleanVal == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal); cv == null ? el.removeAttributeNS(XLINK, k.slice(6)) : el.setAttributeNS(XLINK, k.slice(6), cv);
continue; continue;
} }
if (k.startsWith("on")) { if (k.startsWith("on")) {
const ev = k.slice(2).toLowerCase(); let ev = k.slice(2).toLowerCase();
el.addEventListener(ev, v); el.addEventListener(ev, v);
const off = () => el.removeEventListener(ev, v); let off = () => el.removeEventListener(ev, v);
el._cleanups.add(off); el._c.add(off);
onUnmount(off); onUnmount(off);
} else if (isFunc(v)) { } else if (isFunc(v)) {
const effect = createEffect(() => { let e = createEffect(() => {
const val = validateAttr(k, v()); let r = valAtt(k, v());
if (k === "class") if (k === "class")
el.className = val || ""; el.className = r || "";
else if (val == null) else if (r == null)
el.removeAttribute(k); el.removeAttribute(k);
else if (k === "style" && typeof val === "string") else if (k === "style" && typeof r == "string")
el.setAttribute("style", val); el.setAttribute("style", r);
else if (k in el && !isSVG) else if (k in el && !isS)
el[k] = val; el[k] = r;
else else
el.setAttribute(k, val === true ? "" : val); el.setAttribute(k, r === true ? "" : r);
}); });
effect(); e();
el._cleanups.add(() => dispose(effect)); el._c.add(() => dispose(e));
onUnmount(() => dispose(effect)); onUnmount(() => dispose(e));
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) { if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
const evType = k === "checked" ? "change" : "input"; el.addEventListener(k === "checked" ? "change" : "input", (ev) => v(ev.target[k]));
el.addEventListener(evType, (ev) => v(ev.target[k]));
} }
} else { } else {
const val = validateAttr(k, v); let r = valAtt(k, v);
if (val != null) { if (r != null) {
if (k === "style" && typeof val === "string") if (k === "style" && typeof r == "string")
el.setAttribute("style", val); el.setAttribute("style", r);
else if (k in el && !isSVG) else if (k in el && !isS)
el[k] = val; el[k] = r;
else else
el.setAttribute(k, val === true ? "" : val); el.setAttribute(k, r === true ? "" : r);
} }
} }
} }
const append = (c) => { const app = (c) => {
if (isArr(c)) if (isArr(c))
return c.forEach(append); return c.forEach(app);
if (isFunc(c)) { if (isFunc(c)) {
const anchor = doc.createTextNode(""); let anc = txt(""), cur = [];
el.appendChild(anchor); el.appendChild(anc);
let currentNodes = []; let e = createEffect(() => {
const effect = createEffect(() => { let r = c(), nxt = (isArr(r) ? r : [r]).map(toNd), ref = anc;
const res = c(); cur.forEach((n) => {
const next = (isArr(res) ? res : [res]).map(ensureNode); n._rt ? n._del() : clnNd(n);
currentNodes.forEach((n) => {
if (n._isRuntime)
n.destroy();
else
cleanupNode(n);
if (n.parentNode) if (n.parentNode)
n.remove(); n.remove();
}); });
let ref = anchor; for (let i = nxt.length - 1;i >= 0; i--) {
for (let i = next.length - 1;i >= 0; i--) { let nd = nxt[i];
const node = next[i]; if (nd.parentNode !== ref.parentNode)
if (node.parentNode !== ref.parentNode) ref.parentNode?.insertBefore(nd, ref);
ref.parentNode?.insertBefore(node, ref); if (nd._m)
if (node._mounts) nd._m.forEach((f) => f());
node._mounts.forEach((fn) => fn()); ref = nd;
ref = node;
} }
currentNodes = next; cur = nxt;
}); });
effect(); e();
el._cleanups.add(() => dispose(effect)); el._c.add(() => dispose(e));
onUnmount(() => dispose(effect)); onUnmount(() => dispose(e));
} else { } else {
const node = ensureNode(c); let nd = toNd(c);
el.appendChild(node); el.appendChild(nd);
if (node._mounts) if (nd._m)
node._mounts.forEach((fn) => fn()); nd._m.forEach((f) => f());
} }
}; };
append(children); app(ch);
return el; return el;
}; };
var render = (renderFn) => { var render = (rFn) => {
const cleanups = new Set; let c = new Set, pO = aOwn, pE = aEff, cnt = doc.createElement("div");
const previousOwner = activeOwner; cnt.style.display = "contents";
const previousEffect = activeEffect; cnt.setAttribute("role", "presentation");
const container = doc.createElement("div"); aOwn = { _c: c };
container.style.display = "contents"; aEff = null;
container.setAttribute("role", "presentation"); const pRes = (r) => {
activeOwner = { _cleanups: cleanups }; if (!r)
activeEffect = null;
const processResult = (result) => {
if (!result)
return; return;
if (result._isRuntime) { if (r._rt) {
cleanups.add(result.destroy); c.add(r._del);
container.appendChild(result.container); cnt.appendChild(r._cnt);
} else if (isArr(result)) { } else if (isArr(r))
result.forEach(processResult); r.forEach(pRes);
} else { else
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result))); cnt.appendChild(r instanceof Node ? r : txt(r));
}
}; };
try { try {
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) })); pRes(rFn({ onCleanup: (f) => c.add(f) }));
} finally { } finally {
activeOwner = previousOwner; aOwn = pO;
activeEffect = previousEffect; aEff = pE;
}
return {
_isRuntime: true,
container,
destroy: () => {
cleanups.forEach((fn) => fn());
cleanupNode(container);
container.remove();
} }
return { _rt: 1, _cnt: cnt, _del: () => {
clr(c);
clnNd(cnt);
cnt.remove();
} };
}; };
}; var when = (c, Y, N = null) => {
var when = (cond, SIP, NOP = null) => { let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), v;
const anchor = doc.createTextNode(""); watch(() => !!val(c), (s) => {
const root = h("div", { style: "display:contents" }, [anchor]); if (v) {
let currentView = null; v._del();
watch(() => !!(isFunc(cond) ? cond() : cond), (show) => { v = null;
if (currentView) {
currentView.destroy();
currentView = null;
} }
const content = show ? SIP : NOP; let ct = s ? Y : N;
if (content) { if (ct) {
currentView = render(() => isFunc(content) ? content() : content); v = render(() => val(ct));
root.insertBefore(currentView.container, anchor); rt.insertBefore(v._cnt, anc);
} }
}); });
onUnmount(() => currentView?.destroy()); onUnmount(() => v?._del());
return root; return rt;
}; };
var each = (src, itemFn, keyField) => { var each = (s, fn, kF) => {
const anchor = doc.createTextNode(""); let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), cch = new Map;
const root = h("div", { style: "display:contents" }, [anchor]); watch(() => val(s) || [], (it) => {
let cache = new Map; let nCc = new Map, nOd = [];
watch(() => (isFunc(src) ? src() : src) || [], (items) => { for (let i = 0, l = (it || []).length;i < l; i++) {
const nextCache = new Map; let t = it[i], k = kF ? t?.[kF] ?? i : t?.id ?? i, v = cch.get(k);
const nextOrder = []; if (!v)
const newItems = items || []; v = render(() => fn(t, i));
for (let i = 0;i < newItems.length; i++) {
const item = newItems[i];
const key = keyField ? item?.[keyField] ?? i : item?.id ?? i;
let view = cache.get(key);
if (!view)
view = render(() => itemFn(item, i));
else else
cache.delete(key); cch.delete(k);
nextCache.set(key, view); nCc.set(k, v);
nextOrder.push(view); nOd.push(v);
} }
cache.forEach((view) => view.destroy()); cch.forEach((v) => v._del());
let lastRef = anchor; let ref = anc;
for (let i = nextOrder.length - 1;i >= 0; i--) { for (let i = nOd.length - 1;i >= 0; i--) {
const view = nextOrder[i]; let nd = nOd[i]._cnt;
const node = view.container; if (nd.nextSibling !== ref)
if (node.nextSibling !== lastRef) rt.insertBefore(nd, ref);
root.insertBefore(node, lastRef); ref = nd;
lastRef = node;
} }
cache = nextCache; cch = nCc;
}); });
return root; return rt;
}; };
var Fragment = (props) => props.children; var mount = (c, tgt) => {
var mount = (comp, target) => { let t = typeof tgt == "string" ? doc.querySelector(tgt) : tgt;
const t = typeof target === "string" ? doc.querySelector(target) : target;
if (!t) if (!t)
return; return;
if (MOUNTED_NODES.has(t)) if (MOUNTED.has(t))
MOUNTED_NODES.get(t).destroy(); MOUNTED.get(t)._del();
const inst = render(isFunc(comp) ? comp : () => comp); let i = render(isFunc(c) ? c : () => c);
t.replaceChildren(inst.container); t.replaceChildren(i._cnt);
MOUNTED_NODES.set(t, inst); MOUNTED.set(t, i);
return inst; return i;
}; };
if (typeof window !== "undefined") { if (typeof window < "u") {
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => { "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((t) => window[t] = (p, c) => h(t, p, c));
window[tag] = (props, children) => h(tag, props, children);
});
} }
export { export {
when, when,
watch, watch,
val,
render, render,
onUnmount, onUnmount,
mount, mount,

File diff suppressed because one or more lines are too long

596
dist/sigpro.js vendored
View File

@@ -1,443 +1,383 @@
(() => { (() => {
// src/sigpro.js // src/sigpro.js
var isFunc = (f) => typeof f === "function"; var isFunc = (f) => typeof f == "function";
var isObj = (o) => o && typeof o === "object"; var isObj = (o) => o && typeof o == "object";
var isArr = Array.isArray; var isArr = Array.isArray;
var doc = typeof document !== "undefined" ? document : null; var doc = typeof document < "u" ? document : null;
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n)); var txt = (s) => doc.createTextNode(s == null ? "" : String(s));
var activeEffect = null; var toNd = (n) => n?._rt ? n._cnt : n instanceof Node ? n : txt(n);
var activeOwner = null; var Fragment = (p) => p.children;
var isFlushing = false; var val = (v) => isFunc(v) ? v() : v;
var batchDepth = 0; var aEff = null;
var effectQueue = new Set; var aOwn = null;
var MOUNTED_NODES = new WeakMap; var isFlushing = 0;
var bDepth = 0;
var eQ = new Set;
var MOUNTED = new WeakMap;
var SVG_NS = "http://www.w3.org/2000/svg"; var SVG_NS = "http://www.w3.org/2000/svg";
var XLINK_NS = "http://www.w3.org/1999/xlink"; var XLINK = "http://www.w3.org/1999/xlink";
var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")); var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","));
var dispose = (eff) => { var DANG_ATTR = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]);
if (!eff || eff._disposed) var clr = (s) => {
if (s) {
s.forEach((f) => f());
s.clear();
}
};
var dispose = (e) => {
if (!e || e._x)
return; return;
eff._disposed = true; e._x = 1;
const stack = [eff]; let st = [e], c;
while (stack.length) { while (c = st.pop()) {
const e = stack.pop(); clr(c._c);
if (e._cleanups) { if (c._ch) {
e._cleanups.forEach((fn) => fn()); c._ch.forEach((x) => st.push(x));
e._cleanups.clear(); c._ch.clear();
} }
if (e._children) { if (c._d) {
e._children.forEach((child) => stack.push(child)); c._d.forEach((d) => d.delete(c));
e._children.clear(); c._d.clear();
}
if (e._deps) {
e._deps.forEach((depSet) => depSet.delete(e));
e._deps.clear();
} }
} }
}; };
var onUnmount = (fn) => { var onUnmount = (f) => aOwn && (aOwn._c ||= new Set).add(f);
if (activeOwner) var untrack = (f) => {
(activeOwner._cleanups ||= new Set).add(fn); let p = aEff;
}; aEff = null;
var untrack = (fn) => {
const p = activeEffect;
activeEffect = null;
try { try {
return fn(); return f();
} finally { } finally {
activeEffect = p; aEff = p;
} }
}; };
var createEffect = (fn, isComputed = false) => { var createEffect = (f, isC = 0) => {
const effect = () => { const e = () => {
if (effect._disposed) if (e._x)
return; return;
if (effect._deps) if (e._d)
effect._deps.forEach((s) => s.delete(effect)); e._d.forEach((s) => s.delete(e));
if (effect._cleanups) { clr(e._c);
effect._cleanups.forEach((c) => c()); let pE = aEff, pO = aOwn;
effect._cleanups.clear(); aEff = aOwn = e;
}
const prevEffect = activeEffect;
const prevOwner = activeOwner;
activeEffect = activeOwner = effect;
try { try {
return effect._result = fn(); return e._res = f();
} catch (e) { } catch (err) {
console.error("[SigPro]", e); console.error("[SigPro]", err);
} finally { } finally {
activeEffect = prevEffect; aEff = pE;
activeOwner = prevOwner; aOwn = pO;
} }
}; };
effect._deps = effect._cleanups = effect._children = null; e._d = e._c = e._ch = null;
effect._disposed = false; e._x = 0;
effect._isComputed = isComputed; e._iC = isC;
effect._depth = activeEffect ? activeEffect._depth + 1 : 0; e._dp = aEff ? aEff._dp + 1 : 0;
effect._mounts = []; e._m = [];
effect._parent = activeOwner; e._p = aOwn;
if (activeOwner) if (aOwn)
(activeOwner._children ||= new Set).add(effect); (aOwn._ch ||= new Set).add(e);
return effect; return e;
}; };
var flush = () => { var flush = () => {
if (isFlushing) if (isFlushing)
return; return;
isFlushing = true; isFlushing = 1;
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth); let q = [...eQ].sort((a, b) => a._dp - b._dp);
effectQueue.clear(); eQ.clear();
for (const e of sorted) for (let e of q)
if (!e._disposed) if (!e._x)
e(); e();
isFlushing = false; isFlushing = 0;
}; };
var batch = (fn) => { var batch = (f) => {
batchDepth++; bDepth++;
try { try {
return fn(); return f();
} finally { } finally {
batchDepth--; if (!--bDepth && eQ.size && !isFlushing)
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing)
flush(); flush();
} }
}; };
var trackUpdate = (subs, trigger = false) => { var trkUpd = (s, trg = 0) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trg && aEff && !aEff._x) {
subs.add(activeEffect); s.add(aEff);
(activeEffect._deps ||= new Set).add(subs); (aEff._d ||= new Set).add(s);
} else if (trigger && subs.size > 0) { } else if (trg && s.size) {
let hasQueue = false; let q = 0;
for (const e of subs) { for (let e of s) {
if (e === activeEffect || e._disposed) if (e === aEff || e._x)
continue; continue;
if (e._isComputed) { if (e._iC) {
e._dirty = true; e._dt = 1;
if (e._subs) if (e._sb)
trackUpdate(e._subs, true); trkUpd(e._sb, 1);
} else { } else {
effectQueue.add(e); eQ.add(e);
hasQueue = true; q = 1;
} }
} }
if (hasQueue && !isFlushing && batchDepth === 0) if (q && !isFlushing && !bDepth)
queueMicrotask(flush); queueMicrotask(flush);
} }
}; };
var $ = (val, key = null) => { var $ = (v, k = null) => {
const subs = new Set; let s = new Set;
if (isFunc(val)) { if (isFunc(v)) {
let cache; let c, cp = () => {
const computed = () => { if (cp._dt) {
if (computed._dirty) { let p = aEff;
const prev = activeEffect; aEff = cp;
activeEffect = computed;
try { try {
const next = val(); let n = v();
if (!Object.is(cache, next)) { if (!Object.is(c, n)) {
cache = next; c = n;
trackUpdate(subs, true); trkUpd(s, 1);
} }
} finally { } finally {
activeEffect = prev; aEff = p;
} }
computed._dirty = false; cp._dt = 0;
} }
trackUpdate(subs); trkUpd(s);
return cache; return c;
}; };
computed._isComputed = true; cp._iC = cp._dt = 1;
computed._subs = subs; cp._sb = s;
computed._dirty = true; cp._d = null;
computed._deps = null; cp._x = 0;
computed._disposed = false; return cp;
return computed;
} }
if (key) if (k)
try { try {
val = JSON.parse(localStorage.getItem(key)) ?? val; v = JSON.parse(localStorage.getItem(k)) ?? v;
} catch (e) {} } catch (e) {}
return (...args) => { return (...a) => {
if (args.length) { if (a.length) {
const next = isFunc(args[0]) ? args[0](val) : args[0]; let n = isFunc(a[0]) ? a[0](v) : a[0];
if (!Object.is(val, next)) { if (!Object.is(v, n)) {
val = next; v = n;
if (key) if (k)
localStorage.setItem(key, JSON.stringify(val)); localStorage.setItem(k, JSON.stringify(v));
trackUpdate(subs, true); trkUpd(s, 1);
} }
} }
trackUpdate(subs); trkUpd(s);
return val; return v;
}; };
}; };
var watch = (sources, cb) => { var watch = (src, cb) => {
if (cb === undefined) { let e = createEffect(cb ? () => {
const effect2 = createEffect(sources); let v = isArr(src) ? src.map((s) => s()) : src();
effect2(); untrack(() => cb(v));
return () => dispose(effect2); } : src);
} e();
const effect = createEffect(() => { return () => dispose(e);
const vals = isArr(sources) ? sources.map((s) => s()) : sources();
untrack(() => cb(vals));
});
effect();
return () => dispose(effect);
}; };
var cleanupNode = (node) => { var clnNd = (n) => {
if (!node) if (!n)
return; return;
if (node._cleanups) { clr(n._c);
node._cleanups.forEach((fn) => fn()); if (n._oE)
node._cleanups.clear(); dispose(n._oE);
} if (n.childNodes)
if (node._ownerEffect) n.childNodes.forEach(clnNd);
dispose(node._ownerEffect);
if (node.childNodes)
node.childNodes.forEach((n) => cleanupNode(n));
}; };
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; var valAtt = (k, v) => v == null || v === false ? null : (DANG_ATTR.has(k) || k.startsWith("on")) && /^\s*(javascript|data|vbscript):/i.test(String(v)) ? "#" : v;
var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); var h = (tag, prp = {}, ch = []) => {
var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on"); if (prp instanceof Node || isArr(prp) || !isObj(prp)) {
var validateAttr = (key, val) => { ch = prp;
if (val == null || val === false) prp = {};
return null;
if (isDangerousAttr(key)) {
const sVal = String(val);
if (DANGEROUS_PROTOCOL.test(sVal))
return "#";
}
return val;
};
var h = (tag, props = {}, children = []) => {
if (props instanceof Node || isArr(props) || !isObj(props)) {
children = props;
props = {};
} }
if (isFunc(tag)) { if (isFunc(tag)) {
const effect = createEffect(() => { let e = createEffect(() => e._res = tag(prp, { children: ch, emit: (ev, ...a) => prp[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...a) }));
const result2 = tag(props, { e();
children, if (e._res == null)
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
});
effect._result = result2;
return result2;
});
effect();
const result = effect._result;
if (result == null)
return null; return null;
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result)); let nd = e._res instanceof Node || isArr(e._res) && e._res.every((n) => n instanceof Node) ? e._res : txt(e._res);
const attach = (n) => { let att = (n) => {
if (isObj(n) && !n._isRuntime) { if (isObj(n) && !n._rt) {
n._mounts = effect._mounts || []; n._m = e._m || [];
n._cleanups = effect._cleanups || new Set; n._c = e._c || new Set;
n._ownerEffect = effect; n._oE = e;
} }
}; };
isArr(node) ? node.forEach(attach) : attach(node); isArr(nd) ? nd.forEach(att) : att(nd);
return node; return nd;
} }
const isSVG = SVG_TAGS.has(tag); let isS = SVG_TAGS.has(tag), el = isS ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag);
const el = isSVG ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag); el._c = new Set;
el._cleanups = new Set; for (let k in prp) {
for (const k of Object.keys(props)) { let v = prp[k];
let v = props[k];
if (k === "ref") { if (k === "ref") {
isFunc(v) ? v(el) : v.current = el; isFunc(v) ? v(el) : v.current = el;
continue; continue;
} }
if (isSVG && k.startsWith("xlink:")) { if (isS && k.startsWith("xlink:")) {
const cleanVal = validateAttr(k.slice(6), v); let cv = valAtt(k.slice(6), v);
cleanVal == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal); cv == null ? el.removeAttributeNS(XLINK, k.slice(6)) : el.setAttributeNS(XLINK, k.slice(6), cv);
continue; continue;
} }
if (k.startsWith("on")) { if (k.startsWith("on")) {
const ev = k.slice(2).toLowerCase(); let ev = k.slice(2).toLowerCase();
el.addEventListener(ev, v); el.addEventListener(ev, v);
const off = () => el.removeEventListener(ev, v); let off = () => el.removeEventListener(ev, v);
el._cleanups.add(off); el._c.add(off);
onUnmount(off); onUnmount(off);
} else if (isFunc(v)) { } else if (isFunc(v)) {
const effect = createEffect(() => { let e = createEffect(() => {
const val = validateAttr(k, v()); let r = valAtt(k, v());
if (k === "class") if (k === "class")
el.className = val || ""; el.className = r || "";
else if (val == null) else if (r == null)
el.removeAttribute(k); el.removeAttribute(k);
else if (k === "style" && typeof val === "string") else if (k === "style" && typeof r == "string")
el.setAttribute("style", val); el.setAttribute("style", r);
else if (k in el && !isSVG) else if (k in el && !isS)
el[k] = val; el[k] = r;
else else
el.setAttribute(k, val === true ? "" : val); el.setAttribute(k, r === true ? "" : r);
}); });
effect(); e();
el._cleanups.add(() => dispose(effect)); el._c.add(() => dispose(e));
onUnmount(() => dispose(effect)); onUnmount(() => dispose(e));
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) { if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
const evType = k === "checked" ? "change" : "input"; el.addEventListener(k === "checked" ? "change" : "input", (ev) => v(ev.target[k]));
el.addEventListener(evType, (ev) => v(ev.target[k]));
} }
} else { } else {
const val = validateAttr(k, v); let r = valAtt(k, v);
if (val != null) { if (r != null) {
if (k === "style" && typeof val === "string") if (k === "style" && typeof r == "string")
el.setAttribute("style", val); el.setAttribute("style", r);
else if (k in el && !isSVG) else if (k in el && !isS)
el[k] = val; el[k] = r;
else else
el.setAttribute(k, val === true ? "" : val); el.setAttribute(k, r === true ? "" : r);
} }
} }
} }
const append = (c) => { const app = (c) => {
if (isArr(c)) if (isArr(c))
return c.forEach(append); return c.forEach(app);
if (isFunc(c)) { if (isFunc(c)) {
const anchor = doc.createTextNode(""); let anc = txt(""), cur = [];
el.appendChild(anchor); el.appendChild(anc);
let currentNodes = []; let e = createEffect(() => {
const effect = createEffect(() => { let r = c(), nxt = (isArr(r) ? r : [r]).map(toNd), ref = anc;
const res = c(); cur.forEach((n) => {
const next = (isArr(res) ? res : [res]).map(ensureNode); n._rt ? n._del() : clnNd(n);
currentNodes.forEach((n) => {
if (n._isRuntime)
n.destroy();
else
cleanupNode(n);
if (n.parentNode) if (n.parentNode)
n.remove(); n.remove();
}); });
let ref = anchor; for (let i = nxt.length - 1;i >= 0; i--) {
for (let i = next.length - 1;i >= 0; i--) { let nd = nxt[i];
const node = next[i]; if (nd.parentNode !== ref.parentNode)
if (node.parentNode !== ref.parentNode) ref.parentNode?.insertBefore(nd, ref);
ref.parentNode?.insertBefore(node, ref); if (nd._m)
if (node._mounts) nd._m.forEach((f) => f());
node._mounts.forEach((fn) => fn()); ref = nd;
ref = node;
} }
currentNodes = next; cur = nxt;
}); });
effect(); e();
el._cleanups.add(() => dispose(effect)); el._c.add(() => dispose(e));
onUnmount(() => dispose(effect)); onUnmount(() => dispose(e));
} else { } else {
const node = ensureNode(c); let nd = toNd(c);
el.appendChild(node); el.appendChild(nd);
if (node._mounts) if (nd._m)
node._mounts.forEach((fn) => fn()); nd._m.forEach((f) => f());
} }
}; };
append(children); app(ch);
return el; return el;
}; };
var render = (renderFn) => { var render = (rFn) => {
const cleanups = new Set; let c = new Set, pO = aOwn, pE = aEff, cnt = doc.createElement("div");
const previousOwner = activeOwner; cnt.style.display = "contents";
const previousEffect = activeEffect; cnt.setAttribute("role", "presentation");
const container = doc.createElement("div"); aOwn = { _c: c };
container.style.display = "contents"; aEff = null;
container.setAttribute("role", "presentation"); const pRes = (r) => {
activeOwner = { _cleanups: cleanups }; if (!r)
activeEffect = null;
const processResult = (result) => {
if (!result)
return; return;
if (result._isRuntime) { if (r._rt) {
cleanups.add(result.destroy); c.add(r._del);
container.appendChild(result.container); cnt.appendChild(r._cnt);
} else if (isArr(result)) { } else if (isArr(r))
result.forEach(processResult); r.forEach(pRes);
} else { else
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result))); cnt.appendChild(r instanceof Node ? r : txt(r));
}
}; };
try { try {
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) })); pRes(rFn({ onCleanup: (f) => c.add(f) }));
} finally { } finally {
activeOwner = previousOwner; aOwn = pO;
activeEffect = previousEffect; aEff = pE;
}
return {
_isRuntime: true,
container,
destroy: () => {
cleanups.forEach((fn) => fn());
cleanupNode(container);
container.remove();
} }
return { _rt: 1, _cnt: cnt, _del: () => {
clr(c);
clnNd(cnt);
cnt.remove();
} };
}; };
}; var when = (c, Y, N = null) => {
var when = (cond, SIP, NOP = null) => { let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), v;
const anchor = doc.createTextNode(""); watch(() => !!val(c), (s) => {
const root = h("div", { style: "display:contents" }, [anchor]); if (v) {
let currentView = null; v._del();
watch(() => !!(isFunc(cond) ? cond() : cond), (show) => { v = null;
if (currentView) {
currentView.destroy();
currentView = null;
} }
const content = show ? SIP : NOP; let ct = s ? Y : N;
if (content) { if (ct) {
currentView = render(() => isFunc(content) ? content() : content); v = render(() => val(ct));
root.insertBefore(currentView.container, anchor); rt.insertBefore(v._cnt, anc);
} }
}); });
onUnmount(() => currentView?.destroy()); onUnmount(() => v?._del());
return root; return rt;
}; };
var each = (src, itemFn, keyField) => { var each = (s, fn, kF) => {
const anchor = doc.createTextNode(""); let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), cch = new Map;
const root = h("div", { style: "display:contents" }, [anchor]); watch(() => val(s) || [], (it) => {
let cache = new Map; let nCc = new Map, nOd = [];
watch(() => (isFunc(src) ? src() : src) || [], (items) => { for (let i = 0, l = (it || []).length;i < l; i++) {
const nextCache = new Map; let t = it[i], k = kF ? t?.[kF] ?? i : t?.id ?? i, v = cch.get(k);
const nextOrder = []; if (!v)
const newItems = items || []; v = render(() => fn(t, i));
for (let i = 0;i < newItems.length; i++) {
const item = newItems[i];
const key = keyField ? item?.[keyField] ?? i : item?.id ?? i;
let view = cache.get(key);
if (!view)
view = render(() => itemFn(item, i));
else else
cache.delete(key); cch.delete(k);
nextCache.set(key, view); nCc.set(k, v);
nextOrder.push(view); nOd.push(v);
} }
cache.forEach((view) => view.destroy()); cch.forEach((v) => v._del());
let lastRef = anchor; let ref = anc;
for (let i = nextOrder.length - 1;i >= 0; i--) { for (let i = nOd.length - 1;i >= 0; i--) {
const view = nextOrder[i]; let nd = nOd[i]._cnt;
const node = view.container; if (nd.nextSibling !== ref)
if (node.nextSibling !== lastRef) rt.insertBefore(nd, ref);
root.insertBefore(node, lastRef); ref = nd;
lastRef = node;
} }
cache = nextCache; cch = nCc;
}); });
return root; return rt;
}; };
var Fragment = (props) => props.children; var mount = (c, tgt) => {
var mount = (comp, target) => { let t = typeof tgt == "string" ? doc.querySelector(tgt) : tgt;
const t = typeof target === "string" ? doc.querySelector(target) : target;
if (!t) if (!t)
return; return;
if (MOUNTED_NODES.has(t)) if (MOUNTED.has(t))
MOUNTED_NODES.get(t).destroy(); MOUNTED.get(t)._del();
const inst = render(isFunc(comp) ? comp : () => comp); let i = render(isFunc(c) ? c : () => c);
t.replaceChildren(inst.container); t.replaceChildren(i._cnt);
MOUNTED_NODES.set(t, inst); MOUNTED.set(t, i);
return inst; return i;
}; };
if (typeof window !== "undefined") { if (typeof window < "u") {
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => { "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((t) => window[t] = (p, c) => h(t, p, c));
window[tag] = (props, children) => h(tag, props, children);
});
} }
// src/sigpro.plus.js // src/sigpro.utils.js
var router = (routes) => { var router = (routes) => {
const getHash = () => window.location.hash.slice(1) || "/"; const getHash = () => window.location.hash.slice(1) || "/";
const path = $(getHash()); const path = $(getHash());

2
dist/sigpro.min.js vendored

File diff suppressed because one or more lines are too long

447
dist/sigpro.plus.js vendored
View File

@@ -1,447 +0,0 @@
// src/sigpro.js
var isFunc = (f) => typeof f === "function";
var isObj = (o) => o && typeof o === "object";
var isArr = Array.isArray;
var doc = typeof document !== "undefined" ? document : null;
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n));
var activeEffect = null;
var activeOwner = null;
var isFlushing = false;
var batchDepth = 0;
var effectQueue = new Set;
var MOUNTED_NODES = new WeakMap;
var SVG_NS = "http://www.w3.org/2000/svg";
var XLINK_NS = "http://www.w3.org/1999/xlink";
var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","));
var dispose = (eff) => {
if (!eff || eff._disposed)
return;
eff._disposed = true;
const stack = [eff];
while (stack.length) {
const e = stack.pop();
if (e._cleanups) {
e._cleanups.forEach((fn) => fn());
e._cleanups.clear();
}
if (e._children) {
e._children.forEach((child) => stack.push(child));
e._children.clear();
}
if (e._deps) {
e._deps.forEach((depSet) => depSet.delete(e));
e._deps.clear();
}
}
};
var onUnmount = (fn) => {
if (activeOwner)
(activeOwner._cleanups ||= new Set).add(fn);
};
var untrack = (fn) => {
const p = activeEffect;
activeEffect = null;
try {
return fn();
} finally {
activeEffect = p;
}
};
var createEffect = (fn, isComputed = false) => {
const effect = () => {
if (effect._disposed)
return;
if (effect._deps)
effect._deps.forEach((s) => s.delete(effect));
if (effect._cleanups) {
effect._cleanups.forEach((c) => c());
effect._cleanups.clear();
}
const prevEffect = activeEffect;
const prevOwner = activeOwner;
activeEffect = activeOwner = effect;
try {
return effect._result = fn();
} catch (e) {
console.error("[SigPro]", e);
} finally {
activeEffect = prevEffect;
activeOwner = prevOwner;
}
};
effect._deps = effect._cleanups = effect._children = null;
effect._disposed = false;
effect._isComputed = isComputed;
effect._depth = activeEffect ? activeEffect._depth + 1 : 0;
effect._mounts = [];
effect._parent = activeOwner;
if (activeOwner)
(activeOwner._children ||= new Set).add(effect);
return effect;
};
var flush = () => {
if (isFlushing)
return;
isFlushing = true;
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth);
effectQueue.clear();
for (const e of sorted)
if (!e._disposed)
e();
isFlushing = false;
};
var trackUpdate = (subs, trigger = false) => {
if (!trigger && activeEffect && !activeEffect._disposed) {
subs.add(activeEffect);
(activeEffect._deps ||= new Set).add(subs);
} else if (trigger && subs.size > 0) {
let hasQueue = false;
for (const e of subs) {
if (e === activeEffect || e._disposed)
continue;
if (e._isComputed) {
e._dirty = true;
if (e._subs)
trackUpdate(e._subs, true);
} else {
effectQueue.add(e);
hasQueue = true;
}
}
if (hasQueue && !isFlushing && batchDepth === 0)
queueMicrotask(flush);
}
};
var $ = (val, key = null) => {
const subs = new Set;
if (isFunc(val)) {
let cache;
const computed = () => {
if (computed._dirty) {
const prev = activeEffect;
activeEffect = computed;
try {
const next = val();
if (!Object.is(cache, next)) {
cache = next;
trackUpdate(subs, true);
}
} finally {
activeEffect = prev;
}
computed._dirty = false;
}
trackUpdate(subs);
return cache;
};
computed._isComputed = true;
computed._subs = subs;
computed._dirty = true;
computed._deps = null;
computed._disposed = false;
return computed;
}
if (key)
try {
val = JSON.parse(localStorage.getItem(key)) ?? val;
} catch (e) {}
return (...args) => {
if (args.length) {
const next = isFunc(args[0]) ? args[0](val) : args[0];
if (!Object.is(val, next)) {
val = next;
if (key)
localStorage.setItem(key, JSON.stringify(val));
trackUpdate(subs, true);
}
}
trackUpdate(subs);
return val;
};
};
var watch = (sources, cb) => {
if (cb === undefined) {
const effect2 = createEffect(sources);
effect2();
return () => dispose(effect2);
}
const effect = createEffect(() => {
const vals = isArr(sources) ? sources.map((s) => s()) : sources();
untrack(() => cb(vals));
});
effect();
return () => dispose(effect);
};
var cleanupNode = (node) => {
if (!node)
return;
if (node._cleanups) {
node._cleanups.forEach((fn) => fn());
node._cleanups.clear();
}
if (node._ownerEffect)
dispose(node._ownerEffect);
if (node.childNodes)
node.childNodes.forEach((n) => cleanupNode(n));
};
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i;
var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]);
var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on");
var validateAttr = (key, val) => {
if (val == null || val === false)
return null;
if (isDangerousAttr(key)) {
const sVal = String(val);
if (DANGEROUS_PROTOCOL.test(sVal))
return "#";
}
return val;
};
var h = (tag, props = {}, children = []) => {
if (props instanceof Node || isArr(props) || !isObj(props)) {
children = props;
props = {};
}
if (isFunc(tag)) {
const effect = createEffect(() => {
const result2 = tag(props, {
children,
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
});
effect._result = result2;
return result2;
});
effect();
const result = effect._result;
if (result == null)
return null;
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result));
const attach = (n) => {
if (isObj(n) && !n._isRuntime) {
n._mounts = effect._mounts || [];
n._cleanups = effect._cleanups || new Set;
n._ownerEffect = effect;
}
};
isArr(node) ? node.forEach(attach) : attach(node);
return node;
}
const isSVG = SVG_TAGS.has(tag);
const el = isSVG ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag);
el._cleanups = new Set;
for (const k of Object.keys(props)) {
let v = props[k];
if (k === "ref") {
isFunc(v) ? v(el) : v.current = el;
continue;
}
if (isSVG && k.startsWith("xlink:")) {
const cleanVal = validateAttr(k.slice(6), v);
cleanVal == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal);
continue;
}
if (k.startsWith("on")) {
const ev = k.slice(2).toLowerCase();
el.addEventListener(ev, v);
const off = () => el.removeEventListener(ev, v);
el._cleanups.add(off);
onUnmount(off);
} else if (isFunc(v)) {
const effect = createEffect(() => {
const val = validateAttr(k, v());
if (k === "class")
el.className = val || "";
else if (val == null)
el.removeAttribute(k);
else if (k === "style" && typeof val === "string")
el.setAttribute("style", val);
else if (k in el && !isSVG)
el[k] = val;
else
el.setAttribute(k, val === true ? "" : val);
});
effect();
el._cleanups.add(() => dispose(effect));
onUnmount(() => dispose(effect));
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
const evType = k === "checked" ? "change" : "input";
el.addEventListener(evType, (ev) => v(ev.target[k]));
}
} else {
const val = validateAttr(k, v);
if (val != null) {
if (k === "style" && typeof val === "string")
el.setAttribute("style", val);
else if (k in el && !isSVG)
el[k] = val;
else
el.setAttribute(k, val === true ? "" : val);
}
}
}
const append = (c) => {
if (isArr(c))
return c.forEach(append);
if (isFunc(c)) {
const anchor = doc.createTextNode("");
el.appendChild(anchor);
let currentNodes = [];
const effect = createEffect(() => {
const res = c();
const next = (isArr(res) ? res : [res]).map(ensureNode);
currentNodes.forEach((n) => {
if (n._isRuntime)
n.destroy();
else
cleanupNode(n);
if (n.parentNode)
n.remove();
});
let ref = anchor;
for (let i = next.length - 1;i >= 0; i--) {
const node = next[i];
if (node.parentNode !== ref.parentNode)
ref.parentNode?.insertBefore(node, ref);
if (node._mounts)
node._mounts.forEach((fn) => fn());
ref = node;
}
currentNodes = next;
});
effect();
el._cleanups.add(() => dispose(effect));
onUnmount(() => dispose(effect));
} else {
const node = ensureNode(c);
el.appendChild(node);
if (node._mounts)
node._mounts.forEach((fn) => fn());
}
};
append(children);
return el;
};
var render = (renderFn) => {
const cleanups = new Set;
const previousOwner = activeOwner;
const previousEffect = activeEffect;
const container = doc.createElement("div");
container.style.display = "contents";
container.setAttribute("role", "presentation");
activeOwner = { _cleanups: cleanups };
activeEffect = null;
const processResult = (result) => {
if (!result)
return;
if (result._isRuntime) {
cleanups.add(result.destroy);
container.appendChild(result.container);
} else if (isArr(result)) {
result.forEach(processResult);
} else {
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result)));
}
};
try {
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) }));
} finally {
activeOwner = previousOwner;
activeEffect = previousEffect;
}
return {
_isRuntime: true,
container,
destroy: () => {
cleanups.forEach((fn) => fn());
cleanupNode(container);
container.remove();
}
};
};
if (typeof window !== "undefined") {
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => {
window[tag] = (props, children) => h(tag, props, children);
});
}
// src/sigpro.plus.js
var router = (routes) => {
const getHash = () => window.location.hash.slice(1) || "/";
const path = $(getHash());
const handler = () => path(getHash());
window.addEventListener("hashchange", handler);
const hook = h("div", { class: "router-hook" });
let currentView = null;
watch([path], () => {
const cur = path();
const route = routes.find((r) => {
const p1 = r.path.split("/").filter(Boolean);
const p2 = cur.split("/").filter(Boolean);
return p1.length === p2.length && p1.every((p, i) => p[0] === ":" || p === p2[i]);
}) || routes.find((r) => r.path === "*");
if (route) {
currentView?.destroy();
const params = {};
route.path.split("/").filter(Boolean).forEach((p, i) => {
if (p[0] === ":")
params[p.slice(1)] = cur.split("/").filter(Boolean)[i];
});
router.params(params);
currentView = render(() => isFunc(route.component) ? route.component(params) : route.component);
hook.replaceChildren(currentView.container);
}
});
hook.destroy = () => {
window.removeEventListener("hashchange", handler);
currentView?.destroy();
};
return hook;
};
router.params = $({});
router.to = (p) => window.location.hash = p.replace(/^#?\/?/, "#/");
router.back = () => window.history.back();
router.path = () => window.location.hash.replace(/^#/, "") || "/";
var db = async (url, data = {}, loading = null) => {
if (loading)
loading(true);
try {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
credentials: "include"
});
if (!res.ok) {
const errorText = await res.text();
throw new Error(`Error ${res.status}: ${errorText}`);
}
return await res.json();
} finally {
if (loading)
loading(false);
}
};
var currentLocale = $("en");
var translations = {};
var addLang = (obj) => {
for (const locale of Object.keys(obj)) {
if (!translations[locale])
translations[locale] = {};
Object.assign(translations[locale], obj[locale]);
}
};
var setLocale = (locale) => {
if (locale && translations[locale]) {
currentLocale(locale);
}
};
var t = (key) => {
return () => translations[currentLocale()]?.[key] ?? key;
};
export {
t,
setLocale,
router,
db,
addLang
};

396
dist/sigpro.utils.js vendored Normal file
View File

@@ -0,0 +1,396 @@
// src/sigpro.js
var isFunc = (f) => typeof f == "function";
var isObj = (o) => o && typeof o == "object";
var isArr = Array.isArray;
var doc = typeof document < "u" ? document : null;
var txt = (s) => doc.createTextNode(s == null ? "" : String(s));
var toNd = (n) => n?._rt ? n._cnt : n instanceof Node ? n : txt(n);
var aEff = null;
var aOwn = null;
var isFlushing = 0;
var bDepth = 0;
var eQ = new Set;
var MOUNTED = new WeakMap;
var SVG_NS = "http://www.w3.org/2000/svg";
var XLINK = "http://www.w3.org/1999/xlink";
var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","));
var DANG_ATTR = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]);
var clr = (s) => {
if (s) {
s.forEach((f) => f());
s.clear();
}
};
var dispose = (e) => {
if (!e || e._x)
return;
e._x = 1;
let st = [e], c;
while (c = st.pop()) {
clr(c._c);
if (c._ch) {
c._ch.forEach((x) => st.push(x));
c._ch.clear();
}
if (c._d) {
c._d.forEach((d) => d.delete(c));
c._d.clear();
}
}
};
var onUnmount = (f) => aOwn && (aOwn._c ||= new Set).add(f);
var untrack = (f) => {
let p = aEff;
aEff = null;
try {
return f();
} finally {
aEff = p;
}
};
var createEffect = (f, isC = 0) => {
const e = () => {
if (e._x)
return;
if (e._d)
e._d.forEach((s) => s.delete(e));
clr(e._c);
let pE = aEff, pO = aOwn;
aEff = aOwn = e;
try {
return e._res = f();
} catch (err) {
console.error("[SigPro]", err);
} finally {
aEff = pE;
aOwn = pO;
}
};
e._d = e._c = e._ch = null;
e._x = 0;
e._iC = isC;
e._dp = aEff ? aEff._dp + 1 : 0;
e._m = [];
e._p = aOwn;
if (aOwn)
(aOwn._ch ||= new Set).add(e);
return e;
};
var flush = () => {
if (isFlushing)
return;
isFlushing = 1;
let q = [...eQ].sort((a, b) => a._dp - b._dp);
eQ.clear();
for (let e of q)
if (!e._x)
e();
isFlushing = 0;
};
var trkUpd = (s, trg = 0) => {
if (!trg && aEff && !aEff._x) {
s.add(aEff);
(aEff._d ||= new Set).add(s);
} else if (trg && s.size) {
let q = 0;
for (let e of s) {
if (e === aEff || e._x)
continue;
if (e._iC) {
e._dt = 1;
if (e._sb)
trkUpd(e._sb, 1);
} else {
eQ.add(e);
q = 1;
}
}
if (q && !isFlushing && !bDepth)
queueMicrotask(flush);
}
};
var $ = (v, k = null) => {
let s = new Set;
if (isFunc(v)) {
let c, cp = () => {
if (cp._dt) {
let p = aEff;
aEff = cp;
try {
let n = v();
if (!Object.is(c, n)) {
c = n;
trkUpd(s, 1);
}
} finally {
aEff = p;
}
cp._dt = 0;
}
trkUpd(s);
return c;
};
cp._iC = cp._dt = 1;
cp._sb = s;
cp._d = null;
cp._x = 0;
return cp;
}
if (k)
try {
v = JSON.parse(localStorage.getItem(k)) ?? v;
} catch (e) {}
return (...a) => {
if (a.length) {
let n = isFunc(a[0]) ? a[0](v) : a[0];
if (!Object.is(v, n)) {
v = n;
if (k)
localStorage.setItem(k, JSON.stringify(v));
trkUpd(s, 1);
}
}
trkUpd(s);
return v;
};
};
var watch = (src, cb) => {
let e = createEffect(cb ? () => {
let v = isArr(src) ? src.map((s) => s()) : src();
untrack(() => cb(v));
} : src);
e();
return () => dispose(e);
};
var clnNd = (n) => {
if (!n)
return;
clr(n._c);
if (n._oE)
dispose(n._oE);
if (n.childNodes)
n.childNodes.forEach(clnNd);
};
var valAtt = (k, v) => v == null || v === false ? null : (DANG_ATTR.has(k) || k.startsWith("on")) && /^\s*(javascript|data|vbscript):/i.test(String(v)) ? "#" : v;
var h = (tag, prp = {}, ch = []) => {
if (prp instanceof Node || isArr(prp) || !isObj(prp)) {
ch = prp;
prp = {};
}
if (isFunc(tag)) {
let e = createEffect(() => e._res = tag(prp, { children: ch, emit: (ev, ...a) => prp[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...a) }));
e();
if (e._res == null)
return null;
let nd = e._res instanceof Node || isArr(e._res) && e._res.every((n) => n instanceof Node) ? e._res : txt(e._res);
let att = (n) => {
if (isObj(n) && !n._rt) {
n._m = e._m || [];
n._c = e._c || new Set;
n._oE = e;
}
};
isArr(nd) ? nd.forEach(att) : att(nd);
return nd;
}
let isS = SVG_TAGS.has(tag), el = isS ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag);
el._c = new Set;
for (let k in prp) {
let v = prp[k];
if (k === "ref") {
isFunc(v) ? v(el) : v.current = el;
continue;
}
if (isS && k.startsWith("xlink:")) {
let cv = valAtt(k.slice(6), v);
cv == null ? el.removeAttributeNS(XLINK, k.slice(6)) : el.setAttributeNS(XLINK, k.slice(6), cv);
continue;
}
if (k.startsWith("on")) {
let ev = k.slice(2).toLowerCase();
el.addEventListener(ev, v);
let off = () => el.removeEventListener(ev, v);
el._c.add(off);
onUnmount(off);
} else if (isFunc(v)) {
let e = createEffect(() => {
let r = valAtt(k, v());
if (k === "class")
el.className = r || "";
else if (r == null)
el.removeAttribute(k);
else if (k === "style" && typeof r == "string")
el.setAttribute("style", r);
else if (k in el && !isS)
el[k] = r;
else
el.setAttribute(k, r === true ? "" : r);
});
e();
el._c.add(() => dispose(e));
onUnmount(() => dispose(e));
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
el.addEventListener(k === "checked" ? "change" : "input", (ev) => v(ev.target[k]));
}
} else {
let r = valAtt(k, v);
if (r != null) {
if (k === "style" && typeof r == "string")
el.setAttribute("style", r);
else if (k in el && !isS)
el[k] = r;
else
el.setAttribute(k, r === true ? "" : r);
}
}
}
const app = (c) => {
if (isArr(c))
return c.forEach(app);
if (isFunc(c)) {
let anc = txt(""), cur = [];
el.appendChild(anc);
let e = createEffect(() => {
let r = c(), nxt = (isArr(r) ? r : [r]).map(toNd), ref = anc;
cur.forEach((n) => {
n._rt ? n._del() : clnNd(n);
if (n.parentNode)
n.remove();
});
for (let i = nxt.length - 1;i >= 0; i--) {
let nd = nxt[i];
if (nd.parentNode !== ref.parentNode)
ref.parentNode?.insertBefore(nd, ref);
if (nd._m)
nd._m.forEach((f) => f());
ref = nd;
}
cur = nxt;
});
e();
el._c.add(() => dispose(e));
onUnmount(() => dispose(e));
} else {
let nd = toNd(c);
el.appendChild(nd);
if (nd._m)
nd._m.forEach((f) => f());
}
};
app(ch);
return el;
};
var render = (rFn) => {
let c = new Set, pO = aOwn, pE = aEff, cnt = doc.createElement("div");
cnt.style.display = "contents";
cnt.setAttribute("role", "presentation");
aOwn = { _c: c };
aEff = null;
const pRes = (r) => {
if (!r)
return;
if (r._rt) {
c.add(r._del);
cnt.appendChild(r._cnt);
} else if (isArr(r))
r.forEach(pRes);
else
cnt.appendChild(r instanceof Node ? r : txt(r));
};
try {
pRes(rFn({ onCleanup: (f) => c.add(f) }));
} finally {
aOwn = pO;
aEff = pE;
}
return { _rt: 1, _cnt: cnt, _del: () => {
clr(c);
clnNd(cnt);
cnt.remove();
} };
};
if (typeof window < "u") {
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((t) => window[t] = (p, c) => h(t, p, c));
}
// src/sigpro.utils.js
var router = (routes) => {
const getHash = () => window.location.hash.slice(1) || "/";
const path = $(getHash());
const handler = () => path(getHash());
window.addEventListener("hashchange", handler);
const hook = h("div", { class: "router-hook" });
let currentView = null;
watch([path], () => {
const cur = path();
const route = routes.find((r) => {
const p1 = r.path.split("/").filter(Boolean);
const p2 = cur.split("/").filter(Boolean);
return p1.length === p2.length && p1.every((p, i) => p[0] === ":" || p === p2[i]);
}) || routes.find((r) => r.path === "*");
if (route) {
currentView?.destroy();
const params = {};
route.path.split("/").filter(Boolean).forEach((p, i) => {
if (p[0] === ":")
params[p.slice(1)] = cur.split("/").filter(Boolean)[i];
});
router.params(params);
currentView = render(() => isFunc(route.component) ? route.component(params) : route.component);
hook.replaceChildren(currentView.container);
}
});
hook.destroy = () => {
window.removeEventListener("hashchange", handler);
currentView?.destroy();
};
return hook;
};
router.params = $({});
router.to = (p) => window.location.hash = p.replace(/^#?\/?/, "#/");
router.back = () => window.history.back();
router.path = () => window.location.hash.replace(/^#/, "") || "/";
var db = async (url, data = {}, loading = null) => {
if (loading)
loading(true);
try {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
credentials: "include"
});
if (!res.ok) {
const errorText = await res.text();
throw new Error(`Error ${res.status}: ${errorText}`);
}
return await res.json();
} finally {
if (loading)
loading(false);
}
};
var currentLocale = $("en");
var translations = {};
var addLang = (obj) => {
for (const locale of Object.keys(obj)) {
if (!translations[locale])
translations[locale] = {};
Object.assign(translations[locale], obj[locale]);
}
};
var setLocale = (locale) => {
if (locale && translations[locale]) {
currentLocale(locale);
}
};
var t = (key) => {
return () => translations[currentLocale()]?.[key] ?? key;
};
export {
t,
setLocale,
router,
db,
addLang
};

View File

@@ -17,7 +17,7 @@ router(routes: Route[]): HTMLElement
**Returns:** A `div` element (with class `"router-hook"`) that acts as the router outlet. The router automatically destroys the previous view and mounts the matched component when the hash changes. **Returns:** A `div` element (with class `"router-hook"`) that acts as the router outlet. The router automatically destroys the previous view and mounts the matched component when the hash changes.
> **Availability:** `router` and its helper methods (`router.to`, `router.back`, `router.path`, `router.params`) are exported from the SigPro module. In **ESM** you must import them (`import { router } from 'sigpro/plus'`). In the **IIFE** classic script, they are automatically available on `window`. The examples below assume the functions are already in scope. > **Availability:** `router` and its helper methods (`router.to`, `router.back`, `router.path`, `router.params`) are exported from the SigPro module. In **ESM** you must import them (`import { router } from 'sigpro/utils'`). In the **IIFE** classic script, they are automatically available on `window`. The examples below assume the functions are already in scope.
--- ---
@@ -243,7 +243,7 @@ Thanks to **SigPro's synchronous initialization**, you no longer need to wrap yo
```javascript ```javascript
// src/main.js // src/main.js
import { mount } from 'sigpro'; import { mount } from 'sigpro';
import { router } from 'sigpro/plus'; import { router } from 'sigpro/utils';
import { routes } from 'virtual:sigpro-routes'; import { routes } from 'virtual:sigpro-routes';
// The Core already has Router ready // The Core already has Router ready

View File

@@ -1,443 +1,383 @@
(() => { (() => {
// src/sigpro.js // src/sigpro.js
var isFunc = (f) => typeof f === "function"; var isFunc = (f) => typeof f == "function";
var isObj = (o) => o && typeof o === "object"; var isObj = (o) => o && typeof o == "object";
var isArr = Array.isArray; var isArr = Array.isArray;
var doc = typeof document !== "undefined" ? document : null; var doc = typeof document < "u" ? document : null;
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n)); var txt = (s) => doc.createTextNode(s == null ? "" : String(s));
var activeEffect = null; var toNd = (n) => n?._rt ? n._cnt : n instanceof Node ? n : txt(n);
var activeOwner = null; var Fragment = (p) => p.children;
var isFlushing = false; var val = (v) => isFunc(v) ? v() : v;
var batchDepth = 0; var aEff = null;
var effectQueue = new Set; var aOwn = null;
var MOUNTED_NODES = new WeakMap; var isFlushing = 0;
var bDepth = 0;
var eQ = new Set;
var MOUNTED = new WeakMap;
var SVG_NS = "http://www.w3.org/2000/svg"; var SVG_NS = "http://www.w3.org/2000/svg";
var XLINK_NS = "http://www.w3.org/1999/xlink"; var XLINK = "http://www.w3.org/1999/xlink";
var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")); var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","));
var dispose = (eff) => { var DANG_ATTR = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]);
if (!eff || eff._disposed) var clr = (s) => {
if (s) {
s.forEach((f) => f());
s.clear();
}
};
var dispose = (e) => {
if (!e || e._x)
return; return;
eff._disposed = true; e._x = 1;
const stack = [eff]; let st = [e], c;
while (stack.length) { while (c = st.pop()) {
const e = stack.pop(); clr(c._c);
if (e._cleanups) { if (c._ch) {
e._cleanups.forEach((fn) => fn()); c._ch.forEach((x) => st.push(x));
e._cleanups.clear(); c._ch.clear();
} }
if (e._children) { if (c._d) {
e._children.forEach((child) => stack.push(child)); c._d.forEach((d) => d.delete(c));
e._children.clear(); c._d.clear();
}
if (e._deps) {
e._deps.forEach((depSet) => depSet.delete(e));
e._deps.clear();
} }
} }
}; };
var onUnmount = (fn) => { var onUnmount = (f) => aOwn && (aOwn._c ||= new Set).add(f);
if (activeOwner) var untrack = (f) => {
(activeOwner._cleanups ||= new Set).add(fn); let p = aEff;
}; aEff = null;
var untrack = (fn) => {
const p = activeEffect;
activeEffect = null;
try { try {
return fn(); return f();
} finally { } finally {
activeEffect = p; aEff = p;
} }
}; };
var createEffect = (fn, isComputed = false) => { var createEffect = (f, isC = 0) => {
const effect = () => { const e = () => {
if (effect._disposed) if (e._x)
return; return;
if (effect._deps) if (e._d)
effect._deps.forEach((s) => s.delete(effect)); e._d.forEach((s) => s.delete(e));
if (effect._cleanups) { clr(e._c);
effect._cleanups.forEach((c) => c()); let pE = aEff, pO = aOwn;
effect._cleanups.clear(); aEff = aOwn = e;
}
const prevEffect = activeEffect;
const prevOwner = activeOwner;
activeEffect = activeOwner = effect;
try { try {
return effect._result = fn(); return e._res = f();
} catch (e) { } catch (err) {
console.error("[SigPro]", e); console.error("[SigPro]", err);
} finally { } finally {
activeEffect = prevEffect; aEff = pE;
activeOwner = prevOwner; aOwn = pO;
} }
}; };
effect._deps = effect._cleanups = effect._children = null; e._d = e._c = e._ch = null;
effect._disposed = false; e._x = 0;
effect._isComputed = isComputed; e._iC = isC;
effect._depth = activeEffect ? activeEffect._depth + 1 : 0; e._dp = aEff ? aEff._dp + 1 : 0;
effect._mounts = []; e._m = [];
effect._parent = activeOwner; e._p = aOwn;
if (activeOwner) if (aOwn)
(activeOwner._children ||= new Set).add(effect); (aOwn._ch ||= new Set).add(e);
return effect; return e;
}; };
var flush = () => { var flush = () => {
if (isFlushing) if (isFlushing)
return; return;
isFlushing = true; isFlushing = 1;
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth); let q = [...eQ].sort((a, b) => a._dp - b._dp);
effectQueue.clear(); eQ.clear();
for (const e of sorted) for (let e of q)
if (!e._disposed) if (!e._x)
e(); e();
isFlushing = false; isFlushing = 0;
}; };
var batch = (fn) => { var batch = (f) => {
batchDepth++; bDepth++;
try { try {
return fn(); return f();
} finally { } finally {
batchDepth--; if (!--bDepth && eQ.size && !isFlushing)
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing)
flush(); flush();
} }
}; };
var trackUpdate = (subs, trigger = false) => { var trkUpd = (s, trg = 0) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trg && aEff && !aEff._x) {
subs.add(activeEffect); s.add(aEff);
(activeEffect._deps ||= new Set).add(subs); (aEff._d ||= new Set).add(s);
} else if (trigger && subs.size > 0) { } else if (trg && s.size) {
let hasQueue = false; let q = 0;
for (const e of subs) { for (let e of s) {
if (e === activeEffect || e._disposed) if (e === aEff || e._x)
continue; continue;
if (e._isComputed) { if (e._iC) {
e._dirty = true; e._dt = 1;
if (e._subs) if (e._sb)
trackUpdate(e._subs, true); trkUpd(e._sb, 1);
} else { } else {
effectQueue.add(e); eQ.add(e);
hasQueue = true; q = 1;
} }
} }
if (hasQueue && !isFlushing && batchDepth === 0) if (q && !isFlushing && !bDepth)
queueMicrotask(flush); queueMicrotask(flush);
} }
}; };
var $ = (val, key = null) => { var $ = (v, k = null) => {
const subs = new Set; let s = new Set;
if (isFunc(val)) { if (isFunc(v)) {
let cache; let c, cp = () => {
const computed = () => { if (cp._dt) {
if (computed._dirty) { let p = aEff;
const prev = activeEffect; aEff = cp;
activeEffect = computed;
try { try {
const next = val(); let n = v();
if (!Object.is(cache, next)) { if (!Object.is(c, n)) {
cache = next; c = n;
trackUpdate(subs, true); trkUpd(s, 1);
} }
} finally { } finally {
activeEffect = prev; aEff = p;
} }
computed._dirty = false; cp._dt = 0;
} }
trackUpdate(subs); trkUpd(s);
return cache; return c;
}; };
computed._isComputed = true; cp._iC = cp._dt = 1;
computed._subs = subs; cp._sb = s;
computed._dirty = true; cp._d = null;
computed._deps = null; cp._x = 0;
computed._disposed = false; return cp;
return computed;
} }
if (key) if (k)
try { try {
val = JSON.parse(localStorage.getItem(key)) ?? val; v = JSON.parse(localStorage.getItem(k)) ?? v;
} catch (e) {} } catch (e) {}
return (...args) => { return (...a) => {
if (args.length) { if (a.length) {
const next = isFunc(args[0]) ? args[0](val) : args[0]; let n = isFunc(a[0]) ? a[0](v) : a[0];
if (!Object.is(val, next)) { if (!Object.is(v, n)) {
val = next; v = n;
if (key) if (k)
localStorage.setItem(key, JSON.stringify(val)); localStorage.setItem(k, JSON.stringify(v));
trackUpdate(subs, true); trkUpd(s, 1);
} }
} }
trackUpdate(subs); trkUpd(s);
return val; return v;
}; };
}; };
var watch = (sources, cb) => { var watch = (src, cb) => {
if (cb === undefined) { let e = createEffect(cb ? () => {
const effect2 = createEffect(sources); let v = isArr(src) ? src.map((s) => s()) : src();
effect2(); untrack(() => cb(v));
return () => dispose(effect2); } : src);
} e();
const effect = createEffect(() => { return () => dispose(e);
const vals = isArr(sources) ? sources.map((s) => s()) : sources();
untrack(() => cb(vals));
});
effect();
return () => dispose(effect);
}; };
var cleanupNode = (node) => { var clnNd = (n) => {
if (!node) if (!n)
return; return;
if (node._cleanups) { clr(n._c);
node._cleanups.forEach((fn) => fn()); if (n._oE)
node._cleanups.clear(); dispose(n._oE);
} if (n.childNodes)
if (node._ownerEffect) n.childNodes.forEach(clnNd);
dispose(node._ownerEffect);
if (node.childNodes)
node.childNodes.forEach((n) => cleanupNode(n));
}; };
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; var valAtt = (k, v) => v == null || v === false ? null : (DANG_ATTR.has(k) || k.startsWith("on")) && /^\s*(javascript|data|vbscript):/i.test(String(v)) ? "#" : v;
var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); var h = (tag, prp = {}, ch = []) => {
var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on"); if (prp instanceof Node || isArr(prp) || !isObj(prp)) {
var validateAttr = (key, val) => { ch = prp;
if (val == null || val === false) prp = {};
return null;
if (isDangerousAttr(key)) {
const sVal = String(val);
if (DANGEROUS_PROTOCOL.test(sVal))
return "#";
}
return val;
};
var h = (tag, props = {}, children = []) => {
if (props instanceof Node || isArr(props) || !isObj(props)) {
children = props;
props = {};
} }
if (isFunc(tag)) { if (isFunc(tag)) {
const effect = createEffect(() => { let e = createEffect(() => e._res = tag(prp, { children: ch, emit: (ev, ...a) => prp[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...a) }));
const result2 = tag(props, { e();
children, if (e._res == null)
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
});
effect._result = result2;
return result2;
});
effect();
const result = effect._result;
if (result == null)
return null; return null;
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result)); let nd = e._res instanceof Node || isArr(e._res) && e._res.every((n) => n instanceof Node) ? e._res : txt(e._res);
const attach = (n) => { let att = (n) => {
if (isObj(n) && !n._isRuntime) { if (isObj(n) && !n._rt) {
n._mounts = effect._mounts || []; n._m = e._m || [];
n._cleanups = effect._cleanups || new Set; n._c = e._c || new Set;
n._ownerEffect = effect; n._oE = e;
} }
}; };
isArr(node) ? node.forEach(attach) : attach(node); isArr(nd) ? nd.forEach(att) : att(nd);
return node; return nd;
} }
const isSVG = SVG_TAGS.has(tag); let isS = SVG_TAGS.has(tag), el = isS ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag);
const el = isSVG ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag); el._c = new Set;
el._cleanups = new Set; for (let k in prp) {
for (const k of Object.keys(props)) { let v = prp[k];
let v = props[k];
if (k === "ref") { if (k === "ref") {
isFunc(v) ? v(el) : v.current = el; isFunc(v) ? v(el) : v.current = el;
continue; continue;
} }
if (isSVG && k.startsWith("xlink:")) { if (isS && k.startsWith("xlink:")) {
const cleanVal = validateAttr(k.slice(6), v); let cv = valAtt(k.slice(6), v);
cleanVal == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal); cv == null ? el.removeAttributeNS(XLINK, k.slice(6)) : el.setAttributeNS(XLINK, k.slice(6), cv);
continue; continue;
} }
if (k.startsWith("on")) { if (k.startsWith("on")) {
const ev = k.slice(2).toLowerCase(); let ev = k.slice(2).toLowerCase();
el.addEventListener(ev, v); el.addEventListener(ev, v);
const off = () => el.removeEventListener(ev, v); let off = () => el.removeEventListener(ev, v);
el._cleanups.add(off); el._c.add(off);
onUnmount(off); onUnmount(off);
} else if (isFunc(v)) { } else if (isFunc(v)) {
const effect = createEffect(() => { let e = createEffect(() => {
const val = validateAttr(k, v()); let r = valAtt(k, v());
if (k === "class") if (k === "class")
el.className = val || ""; el.className = r || "";
else if (val == null) else if (r == null)
el.removeAttribute(k); el.removeAttribute(k);
else if (k === "style" && typeof val === "string") else if (k === "style" && typeof r == "string")
el.setAttribute("style", val); el.setAttribute("style", r);
else if (k in el && !isSVG) else if (k in el && !isS)
el[k] = val; el[k] = r;
else else
el.setAttribute(k, val === true ? "" : val); el.setAttribute(k, r === true ? "" : r);
}); });
effect(); e();
el._cleanups.add(() => dispose(effect)); el._c.add(() => dispose(e));
onUnmount(() => dispose(effect)); onUnmount(() => dispose(e));
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) { if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
const evType = k === "checked" ? "change" : "input"; el.addEventListener(k === "checked" ? "change" : "input", (ev) => v(ev.target[k]));
el.addEventListener(evType, (ev) => v(ev.target[k]));
} }
} else { } else {
const val = validateAttr(k, v); let r = valAtt(k, v);
if (val != null) { if (r != null) {
if (k === "style" && typeof val === "string") if (k === "style" && typeof r == "string")
el.setAttribute("style", val); el.setAttribute("style", r);
else if (k in el && !isSVG) else if (k in el && !isS)
el[k] = val; el[k] = r;
else else
el.setAttribute(k, val === true ? "" : val); el.setAttribute(k, r === true ? "" : r);
} }
} }
} }
const append = (c) => { const app = (c) => {
if (isArr(c)) if (isArr(c))
return c.forEach(append); return c.forEach(app);
if (isFunc(c)) { if (isFunc(c)) {
const anchor = doc.createTextNode(""); let anc = txt(""), cur = [];
el.appendChild(anchor); el.appendChild(anc);
let currentNodes = []; let e = createEffect(() => {
const effect = createEffect(() => { let r = c(), nxt = (isArr(r) ? r : [r]).map(toNd), ref = anc;
const res = c(); cur.forEach((n) => {
const next = (isArr(res) ? res : [res]).map(ensureNode); n._rt ? n._del() : clnNd(n);
currentNodes.forEach((n) => {
if (n._isRuntime)
n.destroy();
else
cleanupNode(n);
if (n.parentNode) if (n.parentNode)
n.remove(); n.remove();
}); });
let ref = anchor; for (let i = nxt.length - 1;i >= 0; i--) {
for (let i = next.length - 1;i >= 0; i--) { let nd = nxt[i];
const node = next[i]; if (nd.parentNode !== ref.parentNode)
if (node.parentNode !== ref.parentNode) ref.parentNode?.insertBefore(nd, ref);
ref.parentNode?.insertBefore(node, ref); if (nd._m)
if (node._mounts) nd._m.forEach((f) => f());
node._mounts.forEach((fn) => fn()); ref = nd;
ref = node;
} }
currentNodes = next; cur = nxt;
}); });
effect(); e();
el._cleanups.add(() => dispose(effect)); el._c.add(() => dispose(e));
onUnmount(() => dispose(effect)); onUnmount(() => dispose(e));
} else { } else {
const node = ensureNode(c); let nd = toNd(c);
el.appendChild(node); el.appendChild(nd);
if (node._mounts) if (nd._m)
node._mounts.forEach((fn) => fn()); nd._m.forEach((f) => f());
} }
}; };
append(children); app(ch);
return el; return el;
}; };
var render = (renderFn) => { var render = (rFn) => {
const cleanups = new Set; let c = new Set, pO = aOwn, pE = aEff, cnt = doc.createElement("div");
const previousOwner = activeOwner; cnt.style.display = "contents";
const previousEffect = activeEffect; cnt.setAttribute("role", "presentation");
const container = doc.createElement("div"); aOwn = { _c: c };
container.style.display = "contents"; aEff = null;
container.setAttribute("role", "presentation"); const pRes = (r) => {
activeOwner = { _cleanups: cleanups }; if (!r)
activeEffect = null;
const processResult = (result) => {
if (!result)
return; return;
if (result._isRuntime) { if (r._rt) {
cleanups.add(result.destroy); c.add(r._del);
container.appendChild(result.container); cnt.appendChild(r._cnt);
} else if (isArr(result)) { } else if (isArr(r))
result.forEach(processResult); r.forEach(pRes);
} else { else
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result))); cnt.appendChild(r instanceof Node ? r : txt(r));
}
}; };
try { try {
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) })); pRes(rFn({ onCleanup: (f) => c.add(f) }));
} finally { } finally {
activeOwner = previousOwner; aOwn = pO;
activeEffect = previousEffect; aEff = pE;
}
return {
_isRuntime: true,
container,
destroy: () => {
cleanups.forEach((fn) => fn());
cleanupNode(container);
container.remove();
} }
return { _rt: 1, _cnt: cnt, _del: () => {
clr(c);
clnNd(cnt);
cnt.remove();
} };
}; };
}; var when = (c, Y, N = null) => {
var when = (cond, SIP, NOP = null) => { let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), v;
const anchor = doc.createTextNode(""); watch(() => !!val(c), (s) => {
const root = h("div", { style: "display:contents" }, [anchor]); if (v) {
let currentView = null; v._del();
watch(() => !!(isFunc(cond) ? cond() : cond), (show) => { v = null;
if (currentView) {
currentView.destroy();
currentView = null;
} }
const content = show ? SIP : NOP; let ct = s ? Y : N;
if (content) { if (ct) {
currentView = render(() => isFunc(content) ? content() : content); v = render(() => val(ct));
root.insertBefore(currentView.container, anchor); rt.insertBefore(v._cnt, anc);
} }
}); });
onUnmount(() => currentView?.destroy()); onUnmount(() => v?._del());
return root; return rt;
}; };
var each = (src, itemFn, keyField) => { var each = (s, fn, kF) => {
const anchor = doc.createTextNode(""); let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), cch = new Map;
const root = h("div", { style: "display:contents" }, [anchor]); watch(() => val(s) || [], (it) => {
let cache = new Map; let nCc = new Map, nOd = [];
watch(() => (isFunc(src) ? src() : src) || [], (items) => { for (let i = 0, l = (it || []).length;i < l; i++) {
const nextCache = new Map; let t = it[i], k = kF ? t?.[kF] ?? i : t?.id ?? i, v = cch.get(k);
const nextOrder = []; if (!v)
const newItems = items || []; v = render(() => fn(t, i));
for (let i = 0;i < newItems.length; i++) {
const item = newItems[i];
const key = keyField ? item?.[keyField] ?? i : item?.id ?? i;
let view = cache.get(key);
if (!view)
view = render(() => itemFn(item, i));
else else
cache.delete(key); cch.delete(k);
nextCache.set(key, view); nCc.set(k, v);
nextOrder.push(view); nOd.push(v);
} }
cache.forEach((view) => view.destroy()); cch.forEach((v) => v._del());
let lastRef = anchor; let ref = anc;
for (let i = nextOrder.length - 1;i >= 0; i--) { for (let i = nOd.length - 1;i >= 0; i--) {
const view = nextOrder[i]; let nd = nOd[i]._cnt;
const node = view.container; if (nd.nextSibling !== ref)
if (node.nextSibling !== lastRef) rt.insertBefore(nd, ref);
root.insertBefore(node, lastRef); ref = nd;
lastRef = node;
} }
cache = nextCache; cch = nCc;
}); });
return root; return rt;
}; };
var Fragment = (props) => props.children; var mount = (c, tgt) => {
var mount = (comp, target) => { let t = typeof tgt == "string" ? doc.querySelector(tgt) : tgt;
const t = typeof target === "string" ? doc.querySelector(target) : target;
if (!t) if (!t)
return; return;
if (MOUNTED_NODES.has(t)) if (MOUNTED.has(t))
MOUNTED_NODES.get(t).destroy(); MOUNTED.get(t)._del();
const inst = render(isFunc(comp) ? comp : () => comp); let i = render(isFunc(c) ? c : () => c);
t.replaceChildren(inst.container); t.replaceChildren(i._cnt);
MOUNTED_NODES.set(t, inst); MOUNTED.set(t, i);
return inst; return i;
}; };
if (typeof window !== "undefined") { if (typeof window < "u") {
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => { "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((t) => window[t] = (p, c) => h(t, p, c));
window[tag] = (props, children) => h(tag, props, children);
});
} }
// src/sigpro.plus.js // src/sigpro.utils.js
var router = (routes) => { var router = (routes) => {
const getHash = () => window.location.hash.slice(1) || "/"; const getHash = () => window.location.hash.slice(1) || "/";
const path = $(getHash()); const path = $(getHash());

View File

@@ -19,8 +19,8 @@
"script": "./dist/sigpro.min.js", "script": "./dist/sigpro.min.js",
"types": "./sigpro.d.ts" "types": "./sigpro.d.ts"
}, },
"./plus": { "./utils": {
"import": "./dist/sigpro.plus.js" "import": "./dist/sigpro.utils.js"
}, },
"./vite": { "./vite": {
"import": "./dist/sigpro.vite.js" "import": "./dist/sigpro.vite.js"
@@ -49,10 +49,10 @@
"build:iife:min": "bun build ./src/build_umd.js --bundle --outfile=./dist/sigpro.min.js --format=iife --global-name=sp --minify", "build:iife:min": "bun build ./src/build_umd.js --bundle --outfile=./dist/sigpro.min.js --format=iife --global-name=sp --minify",
"build:esm": "bun build ./src/sigpro.js --bundle --outfile=./dist/sigpro.esm.js --format=esm", "build:esm": "bun build ./src/sigpro.js --bundle --outfile=./dist/sigpro.esm.js --format=esm",
"build:esm:min": "bun build ./src/sigpro.js --bundle --outfile=./dist/sigpro.esm.min.js --format=esm --minify", "build:esm:min": "bun build ./src/sigpro.js --bundle --outfile=./dist/sigpro.esm.min.js --format=esm --minify",
"build:plus": "bun build ./src/sigpro.plus.js --bundle --outfile=./dist/sigpro.plus.js --format=esm", "build:utils": "bun build ./src/sigpro.utils.js --bundle --outfile=./dist/sigpro.utils.js --format=esm",
"build:vite": "bun build ./src/sigpro.vite.js --bundle --outfile=./dist/sigpro.vite.js --format=esm --external:fs --external:path", "build:vite": "bun build ./src/sigpro.vite.js --bundle --outfile=./dist/sigpro.vite.js --format=esm --external:fs --external:path",
"build:copy": "cp ./dist/sigpro.js ./docs/sigpro.js", "build:copy": "cp ./dist/sigpro.js ./docs/sigpro.js",
"build": "bun run build:iife && bun run build:iife:min && bun run build:esm && bun run build:esm:min && bun run build:plus && bun run build:vite && bun run build:copy", "build": "bun run build:iife && bun run build:iife:min && bun run build:esm && bun run build:esm:min && bun run build:utils && bun run build:vite && bun run build:copy",
"docs": "bun x serve docs" "docs": "bun x serve docs"
}, },
"keywords": [ "keywords": [

View File

@@ -1,5 +1,5 @@
import { $, watch, batch, h, Fragment, mount, when, each, isArr, isFunc, isObj } from "./sigpro.js" import { $, watch, batch, h, Fragment, mount, when, each, isArr, isFunc, isObj } from "./sigpro.js"
import { router, addLang, t } from "./sigpro.plus.js" import { router, addLang, t } from "./sigpro.utils.js"
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
Object.assign(window, { $, watch, h, Fragment, when, each, router, addLang, t, mount, batch, isArr, isFunc, isObj }) Object.assign(window, { $, watch, h, Fragment, when, each, router, addLang, t, mount, batch, isArr, isFunc, isObj })

View File

@@ -1,433 +1,250 @@
const isFunc = f => typeof f === "function" const isFunc = f => typeof f == "function";
const isObj = o => o && typeof o === "object" const isObj = o => o && typeof o == "object";
const isArr = Array.isArray const isArr = Array.isArray;
const doc = typeof document !== "undefined" ? document : null const doc = typeof document < "u" ? document : null;
const ensureNode = n => n?._isRuntime ? n.container : (n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n))) const txt = s => doc.createTextNode(s == null ? "" : String(s));
const toNd = n => n?._rt ? n._cnt : (n instanceof Node ? n : txt(n));
const Fragment = p => p.children;
const val = v => isFunc(v) ? v() : v;
let activeEffect = null let aEff = null, aOwn = null, isFlushing = 0, bDepth = 0;
let activeOwner = null const eQ = new Set(), MOUNTED = new WeakMap();
let isFlushing = false
let batchDepth = 0
const effectQueue = new Set()
const MOUNTED_NODES = new WeakMap()
const SVG_NS = "http://www.w3.org/2000/svg" const SVG_NS = "http://www.w3.org/2000/svg", XLINK = "http://www.w3.org/1999/xlink";
const XLINK_NS = "http://www.w3.org/1999/xlink" const SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","));
const SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")) const DANG_ATTR = new Set(["src","href","formaction","action","background","code","archive"]);
const dispose = eff => { const clr = s => { if(s){ s.forEach(f => f()); s.clear(); } };
if (!eff || eff._disposed) return const dispose = e => {
eff._disposed = true if (!e || e._x) return;
const stack = [eff] e._x = 1;
while (stack.length) { let st = [e], c;
const e = stack.pop() while ((c = st.pop())) {
if (e._cleanups) { clr(c._c);
e._cleanups.forEach(fn => fn()) if (c._ch) { c._ch.forEach(x => st.push(x)); c._ch.clear(); }
e._cleanups.clear() if (c._d) { c._d.forEach(d => d.delete(c)); c._d.clear(); }
} }
if (e._children) {
e._children.forEach(child => stack.push(child))
e._children.clear()
}
if (e._deps) {
e._deps.forEach(depSet => depSet.delete(e))
e._deps.clear()
}
}
}
const onUnmount = fn => {
if (activeOwner) (activeOwner._cleanups ||= new Set()).add(fn)
}
const untrack = fn => {
const p = activeEffect
activeEffect = null
try { return fn() } finally { activeEffect = p }
}
const createEffect = (fn, isComputed = false) => {
const effect = () => {
if (effect._disposed) return
if (effect._deps) effect._deps.forEach(s => s.delete(effect))
if (effect._cleanups) {
effect._cleanups.forEach(c => c())
effect._cleanups.clear()
}
const prevEffect = activeEffect
const prevOwner = activeOwner
activeEffect = activeOwner = effect
try {
return effect._result = fn()
} catch (e) {
console.error("[SigPro]", e)
} finally {
activeEffect = prevEffect
activeOwner = prevOwner
}
}
effect._deps = effect._cleanups = effect._children = null
effect._disposed = false
effect._isComputed = isComputed
effect._depth = activeEffect ? activeEffect._depth + 1 : 0
effect._mounts = []
effect._parent = activeOwner
if (activeOwner) (activeOwner._children ||= new Set()).add(effect)
return effect
}
const flush = () => {
if (isFlushing) return
isFlushing = true
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth)
effectQueue.clear()
for (const e of sorted) if (!e._disposed) e()
isFlushing = false
}
const batch = fn => {
batchDepth++
try {
return fn()
} finally {
batchDepth--
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) flush()
}
}
const trackUpdate = (subs, trigger = false) => {
if (!trigger && activeEffect && !activeEffect._disposed) {
subs.add(activeEffect);
(activeEffect._deps ||= new Set()).add(subs)
} else if (trigger && subs.size > 0) {
let hasQueue = false
for (const e of subs) {
if (e === activeEffect || e._disposed) continue
if (e._isComputed) {
e._dirty = true
if (e._subs) trackUpdate(e._subs, true)
} else {
effectQueue.add(e)
hasQueue = true
}
}
if (hasQueue && !isFlushing && batchDepth === 0) queueMicrotask(flush)
}
}
const $ = (val, key = null) => {
const subs = new Set()
if (isFunc(val)) {
let cache
const computed = () => {
if (computed._dirty) {
const prev = activeEffect
activeEffect = computed
try {
const next = val()
if (!Object.is(cache, next)) {
cache = next
trackUpdate(subs, true)
}
} finally {
activeEffect = prev
}
computed._dirty = false
}
trackUpdate(subs)
return cache
}
computed._isComputed = true
computed._subs = subs
computed._dirty = true
computed._deps = null
computed._disposed = false
return computed
}
if (key) try { val = JSON.parse(localStorage.getItem(key)) ?? val } catch (e) { }
return (...args) => {
if (args.length) {
const next = isFunc(args[0]) ? args[0](val) : args[0]
if (!Object.is(val, next)) {
val = next
if (key) localStorage.setItem(key, JSON.stringify(val))
trackUpdate(subs, true)
}
}
trackUpdate(subs)
return val
}
}
const watch = (sources, cb) => {
if (cb === undefined) {
const effect = createEffect(sources)
effect()
return () => dispose(effect)
}
const effect = createEffect(() => {
const vals = isArr(sources) ? sources.map(s => s()) : sources()
untrack(() => cb(vals))
})
effect()
return () => dispose(effect)
}
const cleanupNode = (node) => {
if (!node) return;
if (node._cleanups) {
node._cleanups.forEach(fn => fn());
node._cleanups.clear();
}
if (node._ownerEffect) dispose(node._ownerEffect);
if (node.childNodes) node.childNodes.forEach(n => cleanupNode(n));
}; };
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; const onUnmount = f => aOwn && (aOwn._c ||= new Set()).add(f);
var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); const untrack = f => { let p = aEff; aEff = null; try { return f() } finally { aEff = p } };
var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on");
const validateAttr = (key, val) => { const createEffect = (f, isC = 0) => {
if (val == null || val === false) return null const e = () => {
if (isDangerousAttr(key)) { if (e._x) return;
const sVal = String(val) if (e._d) e._d.forEach(s => s.delete(e));
if (DANGEROUS_PROTOCOL.test(sVal)) return '#' clr(e._c);
} let pE = aEff, pO = aOwn;
return val aEff = aOwn = e;
} try { return e._res = f(); }
catch (err) { console.error("[SigPro]", err); }
finally { aEff = pE; aOwn = pO; }
};
e._d = e._c = e._ch = null;
e._x = 0; e._iC = isC;
e._dp = aEff ? aEff._dp + 1 : 0;
e._m = []; e._p = aOwn;
if (aOwn) (aOwn._ch ||= new Set()).add(e);
return e;
};
const h = (tag, props = {}, children = []) => { const flush = () => {
if (props instanceof Node || isArr(props) || !isObj(props)) { if (isFlushing) return;
children = props isFlushing = 1;
props = {} let q = [...eQ].sort((a, b) => a._dp - b._dp);
eQ.clear();
for (let e of q) if (!e._x) e();
isFlushing = 0;
};
const batch = f => {
bDepth++;
try { return f() } finally { if (!--bDepth && eQ.size && !isFlushing) flush() }
};
const trkUpd = (s, trg = 0) => {
if (!trg && aEff && !aEff._x) {
s.add(aEff);
(aEff._d ||= new Set()).add(s);
} else if (trg && s.size) {
let q = 0;
for (let e of s) {
if (e === aEff || e._x) continue;
if (e._iC) { e._dt = 1; if (e._sb) trkUpd(e._sb, 1); }
else { eQ.add(e); q = 1; }
} }
if (q && !isFlushing && !bDepth) queueMicrotask(flush);
}
};
const $ = (v, k = null) => {
let s = new Set();
if (isFunc(v)) {
let c, cp = () => {
if (cp._dt) {
let p = aEff; aEff = cp;
try { let n = v(); if (!Object.is(c, n)) { c = n; trkUpd(s, 1); } }
finally { aEff = p; }
cp._dt = 0;
}
trkUpd(s); return c;
};
cp._iC = cp._dt = 1; cp._sb = s; cp._d = null; cp._x = 0;
return cp;
}
if (k) try { v = JSON.parse(localStorage.getItem(k)) ?? v } catch(e){}
return (...a) => {
if (a.length) {
let n = isFunc(a[0]) ? a[0](v) : a[0];
if (!Object.is(v, n)) { v = n; if (k) localStorage.setItem(k, JSON.stringify(v)); trkUpd(s, 1); }
}
trkUpd(s); return v;
};
};
const watch = (src, cb) => {
let e = createEffect(cb ? () => { let v = isArr(src) ? src.map(s=>s()) : src(); untrack(() => cb(v)) } : src);
e(); return () => dispose(e);
};
const clnNd = n => {
if (!n) return;
clr(n._c);
if (n._oE) dispose(n._oE);
if (n.childNodes) n.childNodes.forEach(clnNd);
};
const valAtt = (k, v) => (v == null || v === false) ? null :
(DANG_ATTR.has(k) || k.startsWith("on")) && /^\s*(javascript|data|vbscript):/i.test(String(v)) ? '#' : v;
const h = (tag, prp = {}, ch = []) => {
if (prp instanceof Node || isArr(prp) || !isObj(prp)) { ch = prp; prp = {}; }
if (isFunc(tag)) { if (isFunc(tag)) {
const effect = createEffect(() => { let e = createEffect(() => e._res = tag(prp, { children: ch, emit: (ev, ...a) => prp[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...a) }));
const result = tag(props, { e();
children, if (e._res == null) return null;
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args) let nd = e._res instanceof Node || (isArr(e._res) && e._res.every(n => n instanceof Node)) ? e._res : txt(e._res);
}) let att = n => { if (isObj(n) && !n._rt) { n._m = e._m || []; n._c = e._c || new Set(); n._oE = e; } };
effect._result = result isArr(nd) ? nd.forEach(att) : att(nd);
return result return nd;
})
effect()
const result = effect._result
if (result == null) return null
const node = (result instanceof Node || (isArr(result) && result.every(n => n instanceof Node)))
? result
: doc.createTextNode(String(result))
const attach = n => {
if (isObj(n) && !n._isRuntime) {
n._mounts = effect._mounts || []
n._cleanups = effect._cleanups || new Set()
n._ownerEffect = effect
}
} }
isArr(node) ? node.forEach(attach) : attach(node) let isS = SVG_TAGS.has(tag), el = isS ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag);
return node el._c = new Set();
}
const isSVG = SVG_TAGS.has(tag) for (let k in prp) {
const el = isSVG ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag) let v = prp[k];
el._cleanups = new Set() if (k === "ref") { isFunc(v) ? v(el) : (v.current = el); continue; }
if (isS && k.startsWith("xlink:")) {
for (const k of Object.keys(props)) { let cv = valAtt(k.slice(6), v);
let v = props[k] cv == null ? el.removeAttributeNS(XLINK, k.slice(6)) : el.setAttributeNS(XLINK, k.slice(6), cv);
if (k === "ref") { continue;
isFunc(v) ? v(el) : (v.current = el)
continue
}
if (isSVG && k.startsWith("xlink:")) {
const cleanVal = validateAttr(k.slice(6), v)
cleanVal == null
? el.removeAttributeNS(XLINK_NS, k.slice(6))
: el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal)
continue
} }
if (k.startsWith("on")) { if (k.startsWith("on")) {
const ev = k.slice(2).toLowerCase() let ev = k.slice(2).toLowerCase(); el.addEventListener(ev, v);
el.addEventListener(ev, v) let off = () => el.removeEventListener(ev, v); el._c.add(off); onUnmount(off);
const off = () => el.removeEventListener(ev, v)
el._cleanups.add(off)
onUnmount(off)
} else if (isFunc(v)) { } else if (isFunc(v)) {
const effect = createEffect(() => { let e = createEffect(() => {
const val = validateAttr(k, v()) let r = valAtt(k, v());
if (k === "class") el.className = val || "" if (k === "class") el.className = r || "";
else if (val == null) el.removeAttribute(k) else if (r == null) el.removeAttribute(k);
else if (k === "style" && typeof val === "string") el.setAttribute("style", val) else if (k === "style" && typeof r == "string") el.setAttribute("style", r);
else if (k in el && !isSVG) el[k] = val else if (k in el && !isS) el[k] = r;
else el.setAttribute(k, val === true ? "" : val) else el.setAttribute(k, r === true ? "" : r);
}) });
effect() e(); el._c.add(() => dispose(e)); onUnmount(() => dispose(e));
el._cleanups.add(() => dispose(effect))
onUnmount(() => dispose(effect))
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) { if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
const evType = k === "checked" ? "change" : "input" el.addEventListener(k === "checked" ? "change" : "input", ev => v(ev.target[k]));
el.addEventListener(evType, ev => v(ev.target[k]))
} }
} else { } else {
const val = validateAttr(k, v) let r = valAtt(k, v);
if (val != null) { if (r != null) {
if (k === "style" && typeof val === "string") el.setAttribute("style", val) if (k === "style" && typeof r == "string") el.setAttribute("style", r);
else if (k in el && !isSVG) el[k] = val else if (k in el && !isS) el[k] = r;
else el.setAttribute(k, val === true ? "" : val) else el.setAttribute(k, r === true ? "" : r);
} }
} }
} }
const append = c => { const app = c => {
if (isArr(c)) return c.forEach(append) if (isArr(c)) return c.forEach(app);
if (isFunc(c)) { if (isFunc(c)) {
const anchor = doc.createTextNode("") let anc = txt(""), cur = []; el.appendChild(anc);
el.appendChild(anchor) let e = createEffect(() => {
let currentNodes = [] let r = c(), nxt = (isArr(r) ? r : [r]).map(toNd), ref = anc;
const effect = createEffect(() => { cur.forEach(n => { n._rt ? n._del() : clnNd(n); if (n.parentNode) n.remove(); });
const res = c() for (let i = nxt.length - 1; i >= 0; i--) {
const next = (isArr(res) ? res : [res]).map(ensureNode) let nd = nxt[i];
currentNodes.forEach(n => { if (nd.parentNode !== ref.parentNode) ref.parentNode?.insertBefore(nd, ref);
if (n._isRuntime) n.destroy() if (nd._m) nd._m.forEach(f => f()); ref = nd;
else cleanupNode(n)
if (n.parentNode) n.remove()
})
let ref = anchor
for (let i = next.length - 1; i >= 0; i--) {
const node = next[i]
if (node.parentNode !== ref.parentNode) ref.parentNode?.insertBefore(node, ref)
if (node._mounts) node._mounts.forEach(fn => fn())
ref = node
} }
currentNodes = next cur = nxt;
}) });
effect() e(); el._c.add(() => dispose(e)); onUnmount(() => dispose(e));
el._cleanups.add(() => dispose(effect))
onUnmount(() => dispose(effect))
} else { } else {
const node = ensureNode(c) let nd = toNd(c); el.appendChild(nd);
el.appendChild(node) if (nd._m) nd._m.forEach(f => f());
if (node._mounts) node._mounts.forEach(fn => fn())
}
}
append(children)
return el
} }
};
app(ch); return el;
};
const render = renderFn => { const render = rFn => {
const cleanups = new Set() let c = new Set(), pO = aOwn, pE = aEff, cnt = doc.createElement("div");
const previousOwner = activeOwner cnt.style.display = "contents"; cnt.setAttribute("role", "presentation");
const previousEffect = activeEffect aOwn = { _c: c }; aEff = null;
const container = doc.createElement("div") const pRes = r => {
container.style.display = "contents" if (!r) return;
container.setAttribute("role", "presentation") if (r._rt) { c.add(r._del); cnt.appendChild(r._cnt); }
activeOwner = { _cleanups: cleanups } else if (isArr(r)) r.forEach(pRes);
activeEffect = null else cnt.appendChild(r instanceof Node ? r : txt(r));
};
try { pRes(rFn({ onCleanup: f => c.add(f) })); } finally { aOwn = pO; aEff = pE; }
return { _rt: 1, _cnt: cnt, _del: () => { clr(c); clnNd(cnt); cnt.remove(); } };
};
const processResult = result => { const when = (c, Y, N = null) => {
if (!result) return let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), v;
if (result._isRuntime) { watch(() => !!val(c), s => {
cleanups.add(result.destroy) if (v) { v._del(); v = null; }
container.appendChild(result.container) let ct = s ? Y : N;
} else if (isArr(result)) { if (ct) { v = render(() => val(ct)); rt.insertBefore(v._cnt, anc); }
result.forEach(processResult) });
} else { onUnmount(() => v?._del()); return rt;
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result))) };
}
}
try { const each = (s, fn, kF) => {
processResult(renderFn({ onCleanup: fn => cleanups.add(fn) })) let anc = txt(""), rt = h("div", { style: "display:contents" }, [anc]), cch = new Map();
} finally { watch(() => val(s) || [], it => {
activeOwner = previousOwner let nCc = new Map(), nOd = [];
activeEffect = previousEffect for (let i = 0, l = (it||[]).length; i < l; i++) {
let t = it[i], k = kF ? (t?.[kF] ?? i) : (t?.id ?? i), v = cch.get(k);
if (!v) v = render(() => fn(t, i)); else cch.delete(k);
nCc.set(k, v); nOd.push(v);
} }
cch.forEach(v => v._del());
let ref = anc;
for (let i = nOd.length - 1; i >= 0; i--) {
let nd = nOd[i]._cnt;
if (nd.nextSibling !== ref) rt.insertBefore(nd, ref); ref = nd;
}
cch = nCc;
});
return rt;
};
return { const mount = (c, tgt) => {
_isRuntime: true, let t = typeof tgt == "string" ? doc.querySelector(tgt) : tgt;
container, if (!t) return;
destroy: () => { if (MOUNTED.has(t)) MOUNTED.get(t)._del();
cleanups.forEach(fn => fn()) let i = render(isFunc(c) ? c : () => c);
cleanupNode(container) t.replaceChildren(i._cnt); MOUNTED.set(t, i); return i;
container.remove() };
}
}
}
const when = (cond, SIP, NOP = null) => { if (typeof window < "u") {
const anchor = doc.createTextNode("")
const root = h("div", { style: "display:contents" }, [anchor])
let currentView = null
watch(
() => !!(isFunc(cond) ? cond() : cond),
show => {
if (currentView) {
currentView.destroy()
currentView = null
}
const content = show ? SIP : NOP
if (content) {
currentView = render(() => isFunc(content) ? content() : content)
root.insertBefore(currentView.container, anchor)
}
}
)
onUnmount(() => currentView?.destroy())
return root
}
const each = (src, itemFn, keyField) => {
const anchor = doc.createTextNode("")
const root = h("div", { style: "display:contents" }, [anchor])
let cache = new Map()
watch(() => (isFunc(src) ? src() : src) || [], items => {
const nextCache = new Map()
const nextOrder = []
const newItems = items || []
for (let i = 0; i < newItems.length; i++) {
const item = newItems[i]
const key = keyField ? (item?.[keyField] ?? i) : (item?.id ?? i)
let view = cache.get(key)
if (!view) view = render(() => itemFn(item, i))
else cache.delete(key)
nextCache.set(key, view)
nextOrder.push(view)
}
cache.forEach(view => view.destroy())
let lastRef = anchor
for (let i = nextOrder.length - 1; i >= 0; i--) {
const view = nextOrder[i]
const node = view.container
if (node.nextSibling !== lastRef) root.insertBefore(node, lastRef)
lastRef = node
}
cache = nextCache
})
return root
}
const Fragment = (props) => props.children;
const mount = (comp, target) => {
const t = typeof target === "string" ? doc.querySelector(target) : target
if (!t) return
if (MOUNTED_NODES.has(t)) MOUNTED_NODES.get(t).destroy()
const inst = render(isFunc(comp) ? comp : () => comp)
t.replaceChildren(inst.container)
MOUNTED_NODES.set(t, inst)
return inst
}
if (typeof window !== "undefined") {
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video" "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video"
.split(" ") .split(" ").forEach(t => window[t] = (p, c) => h(t, p, c));
.forEach(tag => { window[tag] = (props, children) => h(tag, props, children) })
} }
export { $, watch, batch, h, Fragment, render, mount, when, each, onUnmount, isArr, isFunc, isObj } export { $, watch, batch, h, Fragment, render, mount, when, each, onUnmount, val, isArr, isFunc, isObj };