This commit is contained in:
2026-04-14 00:05:16 +02:00
parent a29963563e
commit f6677ad6b3
6 changed files with 311 additions and 206 deletions

101
dist/sigpro-ui.esm.js vendored
View File

@@ -18,7 +18,10 @@ var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : do
var activeEffect = null; var activeEffect = null;
var activeOwner = null; var activeOwner = null;
var isFlushing = false; var isFlushing = false;
var batchDepth = 0;
var effectQueue = new Set; var effectQueue = new Set;
var proxyCache = new WeakMap;
var ITER = Symbol("iter");
var MOUNTED_NODES = new WeakMap; var MOUNTED_NODES = new WeakMap;
var dispose = (eff) => { var dispose = (eff) => {
if (!eff || eff._disposed) if (!eff || eff._disposed)
@@ -49,16 +52,6 @@ var onUnmount = (fn) => {
if (activeOwner) if (activeOwner)
(activeOwner._cleanups ||= new Set).add(fn); (activeOwner._cleanups ||= new Set).add(fn);
}; };
var set = (signal, path, value) => {
if (value === undefined)
return signal(isFunc(path) ? path(signal()) : path);
const keys = path.split("."), root = { ...signal() };
let acc = root, k;
for (k of keys.slice(0, -1))
acc = acc[k] = { ...acc[k] || {} };
acc[keys.at(-1)] = value;
signal(root);
};
var untrack = (fn) => { var untrack = (fn) => {
const p = activeEffect; const p = activeEffect;
activeEffect = null; activeEffect = null;
@@ -111,6 +104,17 @@ var flush = () => {
e(); e();
isFlushing = false; isFlushing = false;
}; };
var Batch = (fn) => {
batchDepth++;
try {
return fn();
} finally {
batchDepth--;
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
flush();
}
}
};
var trackUpdate = (subs, trigger = false) => { var trackUpdate = (subs, trigger = false) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trigger && activeEffect && !activeEffect._disposed) {
subs.add(activeEffect); subs.add(activeEffect);
@@ -129,7 +133,7 @@ var trackUpdate = (subs, trigger = false) => {
hasQueue = true; hasQueue = true;
} }
}); });
if (hasQueue && !isFlushing) if (hasQueue && !isFlushing && batchDepth === 0)
queueMicrotask(flush); queueMicrotask(flush);
} }
}; };
@@ -193,6 +197,49 @@ var $2 = (val, key = null) => {
return val; return val;
}; };
}; };
var $$ = (target) => {
if (!isObj(target))
return target;
if (proxyCache.has(target))
return proxyCache.get(target);
const subsMap = new Map;
const getSubs = (k) => {
let s = subsMap.get(k);
if (!s)
subsMap.set(k, s = new Set);
return s;
};
const proxy = new Proxy(target, {
get(t, k) {
trackUpdate(getSubs(k));
return $$(t[k]);
},
set(t, k, v) {
const isNew = !(k in t);
if (!Object.is(t[k], v)) {
t[k] = v;
trackUpdate(getSubs(k), true);
if (isNew)
trackUpdate(getSubs(ITER), true);
}
return true;
},
deleteProperty(t, k) {
const res = Reflect.deleteProperty(t, k);
if (res) {
trackUpdate(getSubs(k), true);
trackUpdate(getSubs(ITER), true);
}
return res;
},
ownKeys(t) {
trackUpdate(getSubs(ITER));
return Reflect.ownKeys(t);
}
});
proxyCache.set(target, proxy);
return proxy;
};
var Watch2 = (sources, cb) => { var Watch2 = (sources, cb) => {
if (cb === undefined) { if (cb === undefined) {
const effect2 = createEffect(sources); const effect2 = createEffect(sources);
@@ -387,42 +434,22 @@ var Render = (renderFn) => {
} }
}; };
}; };
var If2 = (cond, ifYes, ifNot = null, trans = null) => { var If2 = (cond, ifYes, ifNot = null) => {
const anchor = doc.createTextNode(""); const anchor = doc.createTextNode("");
const root = Tag2("div", { style: "display:contents" }, [anchor]); const root = Tag2("div", { style: "display:contents" }, [anchor]);
let currentView = null; let currentView = null;
let last = null;
let exitPromise = null;
Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => { Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => {
if (show === last) if (currentView) {
return; currentView.destroy();
last = show; currentView = null;
const disposeView = () => {
if (currentView) {
currentView.destroy();
currentView = null;
}
};
if (currentView && !show && trans?.out) {
if (exitPromise && exitPromise.cancel)
exitPromise.cancel();
const anim = trans.out(currentView.container, disposeView);
exitPromise = anim;
if (anim && anim.finished)
anim.finished.then(disposeView);
else
disposeView();
} else {
disposeView();
} }
const content = show ? ifYes : ifNot; const content = show ? ifYes : ifNot;
if (content) { if (content) {
currentView = Render(() => isFunc(content) ? content() : content); currentView = Render(() => isFunc(content) ? content() : content);
root.insertBefore(currentView.container, anchor); root.insertBefore(currentView.container, anchor);
if (trans?.in)
trans.in(currentView.container);
} }
}); });
onUnmount(() => currentView?.destroy());
return root; return root;
}; };
var For2 = (src, itemFn, keyFn) => { var For2 = (src, itemFn, keyFn) => {
@@ -501,7 +528,7 @@ var Mount2 = (comp, target) => {
MOUNTED_NODES.set(t, inst); MOUNTED_NODES.set(t, inst);
return inst; return inst;
}; };
var SigPro = Object.freeze({ $: $2, Watch: Watch2, Tag: Tag2, Render, If: If2, For: For2, Router, Mount: Mount2, onMount, onUnmount, set }); var SigPro = Object.freeze({ $: $2, $$, Watch: Watch2, Tag: Tag2, Render, If: If2, For: For2, Router, Mount: Mount2, onMount, onUnmount, Batch });
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
Object.assign(window, SigPro); Object.assign(window, SigPro);
"div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer ul ol li a em strong pre code form label input textarea select button img svg".split(" ").forEach((t) => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c)); "div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer ul ol li a em strong pre code form label input textarea select button img svg".split(" ").forEach((t) => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c));

File diff suppressed because one or more lines are too long

101
dist/sigpro-ui.js vendored
View File

@@ -84,7 +84,10 @@
var activeEffect = null; var activeEffect = null;
var activeOwner = null; var activeOwner = null;
var isFlushing = false; var isFlushing = false;
var batchDepth = 0;
var effectQueue = new Set; var effectQueue = new Set;
var proxyCache = new WeakMap;
var ITER = Symbol("iter");
var MOUNTED_NODES = new WeakMap; var MOUNTED_NODES = new WeakMap;
var dispose = (eff) => { var dispose = (eff) => {
if (!eff || eff._disposed) if (!eff || eff._disposed)
@@ -115,16 +118,6 @@
if (activeOwner) if (activeOwner)
(activeOwner._cleanups ||= new Set).add(fn); (activeOwner._cleanups ||= new Set).add(fn);
}; };
var set = (signal, path, value) => {
if (value === undefined)
return signal(isFunc(path) ? path(signal()) : path);
const keys = path.split("."), root = { ...signal() };
let acc = root, k;
for (k of keys.slice(0, -1))
acc = acc[k] = { ...acc[k] || {} };
acc[keys.at(-1)] = value;
signal(root);
};
var untrack = (fn) => { var untrack = (fn) => {
const p = activeEffect; const p = activeEffect;
activeEffect = null; activeEffect = null;
@@ -177,6 +170,17 @@
e(); e();
isFlushing = false; isFlushing = false;
}; };
var Batch = (fn) => {
batchDepth++;
try {
return fn();
} finally {
batchDepth--;
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
flush();
}
}
};
var trackUpdate = (subs, trigger = false) => { var trackUpdate = (subs, trigger = false) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trigger && activeEffect && !activeEffect._disposed) {
subs.add(activeEffect); subs.add(activeEffect);
@@ -195,7 +199,7 @@
hasQueue = true; hasQueue = true;
} }
}); });
if (hasQueue && !isFlushing) if (hasQueue && !isFlushing && batchDepth === 0)
queueMicrotask(flush); queueMicrotask(flush);
} }
}; };
@@ -259,6 +263,49 @@
return val; return val;
}; };
}; };
var $$ = (target) => {
if (!isObj(target))
return target;
if (proxyCache.has(target))
return proxyCache.get(target);
const subsMap = new Map;
const getSubs = (k) => {
let s = subsMap.get(k);
if (!s)
subsMap.set(k, s = new Set);
return s;
};
const proxy = new Proxy(target, {
get(t, k) {
trackUpdate(getSubs(k));
return $$(t[k]);
},
set(t, k, v) {
const isNew = !(k in t);
if (!Object.is(t[k], v)) {
t[k] = v;
trackUpdate(getSubs(k), true);
if (isNew)
trackUpdate(getSubs(ITER), true);
}
return true;
},
deleteProperty(t, k) {
const res = Reflect.deleteProperty(t, k);
if (res) {
trackUpdate(getSubs(k), true);
trackUpdate(getSubs(ITER), true);
}
return res;
},
ownKeys(t) {
trackUpdate(getSubs(ITER));
return Reflect.ownKeys(t);
}
});
proxyCache.set(target, proxy);
return proxy;
};
var Watch2 = (sources, cb) => { var Watch2 = (sources, cb) => {
if (cb === undefined) { if (cb === undefined) {
const effect2 = createEffect(sources); const effect2 = createEffect(sources);
@@ -453,42 +500,22 @@
} }
}; };
}; };
var If2 = (cond, ifYes, ifNot = null, trans = null) => { var If2 = (cond, ifYes, ifNot = null) => {
const anchor = doc.createTextNode(""); const anchor = doc.createTextNode("");
const root = Tag2("div", { style: "display:contents" }, [anchor]); const root = Tag2("div", { style: "display:contents" }, [anchor]);
let currentView = null; let currentView = null;
let last = null;
let exitPromise = null;
Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => { Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => {
if (show === last) if (currentView) {
return; currentView.destroy();
last = show; currentView = null;
const disposeView = () => {
if (currentView) {
currentView.destroy();
currentView = null;
}
};
if (currentView && !show && trans?.out) {
if (exitPromise && exitPromise.cancel)
exitPromise.cancel();
const anim = trans.out(currentView.container, disposeView);
exitPromise = anim;
if (anim && anim.finished)
anim.finished.then(disposeView);
else
disposeView();
} else {
disposeView();
} }
const content = show ? ifYes : ifNot; const content = show ? ifYes : ifNot;
if (content) { if (content) {
currentView = Render(() => isFunc(content) ? content() : content); currentView = Render(() => isFunc(content) ? content() : content);
root.insertBefore(currentView.container, anchor); root.insertBefore(currentView.container, anchor);
if (trans?.in)
trans.in(currentView.container);
} }
}); });
onUnmount(() => currentView?.destroy());
return root; return root;
}; };
var For2 = (src, itemFn, keyFn) => { var For2 = (src, itemFn, keyFn) => {
@@ -567,7 +594,7 @@
MOUNTED_NODES.set(t, inst); MOUNTED_NODES.set(t, inst);
return inst; return inst;
}; };
var SigPro = Object.freeze({ $: $2, Watch: Watch2, Tag: Tag2, Render, If: If2, For: For2, Router, Mount: Mount2, onMount, onUnmount, set }); var SigPro = Object.freeze({ $: $2, $$, Watch: Watch2, Tag: Tag2, Render, If: If2, For: For2, Router, Mount: Mount2, onMount, onUnmount, Batch });
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
Object.assign(window, SigPro); Object.assign(window, SigPro);
"div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer ul ol li a em strong pre code form label input textarea select button img svg".split(" ").forEach((t) => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c)); "div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer ul ol li a em strong pre code form label input textarea select button img svg".split(" ").forEach((t) => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c));

File diff suppressed because one or more lines are too long

101
docs/sigpro-ui.min.js vendored
View File

@@ -84,7 +84,10 @@
var activeEffect = null; var activeEffect = null;
var activeOwner = null; var activeOwner = null;
var isFlushing = false; var isFlushing = false;
var batchDepth = 0;
var effectQueue = new Set; var effectQueue = new Set;
var proxyCache = new WeakMap;
var ITER = Symbol("iter");
var MOUNTED_NODES = new WeakMap; var MOUNTED_NODES = new WeakMap;
var dispose = (eff) => { var dispose = (eff) => {
if (!eff || eff._disposed) if (!eff || eff._disposed)
@@ -115,16 +118,6 @@
if (activeOwner) if (activeOwner)
(activeOwner._cleanups ||= new Set).add(fn); (activeOwner._cleanups ||= new Set).add(fn);
}; };
var set = (signal, path, value) => {
if (value === undefined)
return signal(isFunc(path) ? path(signal()) : path);
const keys = path.split("."), root = { ...signal() };
let acc = root, k;
for (k of keys.slice(0, -1))
acc = acc[k] = { ...acc[k] || {} };
acc[keys.at(-1)] = value;
signal(root);
};
var untrack = (fn) => { var untrack = (fn) => {
const p = activeEffect; const p = activeEffect;
activeEffect = null; activeEffect = null;
@@ -177,6 +170,17 @@
e(); e();
isFlushing = false; isFlushing = false;
}; };
var Batch = (fn) => {
batchDepth++;
try {
return fn();
} finally {
batchDepth--;
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
flush();
}
}
};
var trackUpdate = (subs, trigger = false) => { var trackUpdate = (subs, trigger = false) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trigger && activeEffect && !activeEffect._disposed) {
subs.add(activeEffect); subs.add(activeEffect);
@@ -195,7 +199,7 @@
hasQueue = true; hasQueue = true;
} }
}); });
if (hasQueue && !isFlushing) if (hasQueue && !isFlushing && batchDepth === 0)
queueMicrotask(flush); queueMicrotask(flush);
} }
}; };
@@ -259,6 +263,49 @@
return val; return val;
}; };
}; };
var $$ = (target) => {
if (!isObj(target))
return target;
if (proxyCache.has(target))
return proxyCache.get(target);
const subsMap = new Map;
const getSubs = (k) => {
let s = subsMap.get(k);
if (!s)
subsMap.set(k, s = new Set);
return s;
};
const proxy = new Proxy(target, {
get(t, k) {
trackUpdate(getSubs(k));
return $$(t[k]);
},
set(t, k, v) {
const isNew = !(k in t);
if (!Object.is(t[k], v)) {
t[k] = v;
trackUpdate(getSubs(k), true);
if (isNew)
trackUpdate(getSubs(ITER), true);
}
return true;
},
deleteProperty(t, k) {
const res = Reflect.deleteProperty(t, k);
if (res) {
trackUpdate(getSubs(k), true);
trackUpdate(getSubs(ITER), true);
}
return res;
},
ownKeys(t) {
trackUpdate(getSubs(ITER));
return Reflect.ownKeys(t);
}
});
proxyCache.set(target, proxy);
return proxy;
};
var Watch2 = (sources, cb) => { var Watch2 = (sources, cb) => {
if (cb === undefined) { if (cb === undefined) {
const effect2 = createEffect(sources); const effect2 = createEffect(sources);
@@ -453,42 +500,22 @@
} }
}; };
}; };
var If2 = (cond, ifYes, ifNot = null, trans = null) => { var If2 = (cond, ifYes, ifNot = null) => {
const anchor = doc.createTextNode(""); const anchor = doc.createTextNode("");
const root = Tag2("div", { style: "display:contents" }, [anchor]); const root = Tag2("div", { style: "display:contents" }, [anchor]);
let currentView = null; let currentView = null;
let last = null;
let exitPromise = null;
Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => { Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => {
if (show === last) if (currentView) {
return; currentView.destroy();
last = show; currentView = null;
const disposeView = () => {
if (currentView) {
currentView.destroy();
currentView = null;
}
};
if (currentView && !show && trans?.out) {
if (exitPromise && exitPromise.cancel)
exitPromise.cancel();
const anim = trans.out(currentView.container, disposeView);
exitPromise = anim;
if (anim && anim.finished)
anim.finished.then(disposeView);
else
disposeView();
} else {
disposeView();
} }
const content = show ? ifYes : ifNot; const content = show ? ifYes : ifNot;
if (content) { if (content) {
currentView = Render(() => isFunc(content) ? content() : content); currentView = Render(() => isFunc(content) ? content() : content);
root.insertBefore(currentView.container, anchor); root.insertBefore(currentView.container, anchor);
if (trans?.in)
trans.in(currentView.container);
} }
}); });
onUnmount(() => currentView?.destroy());
return root; return root;
}; };
var For2 = (src, itemFn, keyFn) => { var For2 = (src, itemFn, keyFn) => {
@@ -567,7 +594,7 @@
MOUNTED_NODES.set(t, inst); MOUNTED_NODES.set(t, inst);
return inst; return inst;
}; };
var SigPro = Object.freeze({ $: $2, Watch: Watch2, Tag: Tag2, Render, If: If2, For: For2, Router, Mount: Mount2, onMount, onUnmount, set }); var SigPro = Object.freeze({ $: $2, $$, Watch: Watch2, Tag: Tag2, Render, If: If2, For: For2, Router, Mount: Mount2, onMount, onUnmount, Batch });
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
Object.assign(window, SigPro); Object.assign(window, SigPro);
"div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer ul ol li a em strong pre code form label input textarea select button img svg".split(" ").forEach((t) => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c)); "div span p h1 h2 h3 h4 h5 h6 br hr section article aside nav main header footer ul ol li a em strong pre code form label input textarea select button img svg".split(" ").forEach((t) => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c));

View File

@@ -8,10 +8,12 @@ const ensureNode = n => n?._isRuntime ? n.container : (n instanceof Node ? n : d
let activeEffect = null let activeEffect = null
let activeOwner = null let activeOwner = null
let isFlushing = false let isFlushing = false
let batchDepth = 0
const effectQueue = new Set() const effectQueue = new Set()
const proxyCache = new WeakMap()
const ITER = Symbol('iter')
const MOUNTED_NODES = new WeakMap() const MOUNTED_NODES = new WeakMap()
// effect cleanup
const dispose = eff => { const dispose = eff => {
if (!eff || eff._disposed) return if (!eff || eff._disposed) return
eff._disposed = true eff._disposed = true
@@ -33,7 +35,6 @@ const dispose = eff => {
} }
} }
// helpers
const onMount = fn => { const onMount = fn => {
if (activeOwner) (activeOwner._mounts ||= []).push(fn) if (activeOwner) (activeOwner._mounts ||= []).push(fn)
} }
@@ -42,42 +43,32 @@ const onUnmount = fn => {
if (activeOwner) (activeOwner._cleanups ||= new Set()).add(fn) if (activeOwner) (activeOwner._cleanups ||= new Set()).add(fn)
} }
const set = (signal, path, value) => {
if (value === undefined) return signal(isFunc(path) ? path(signal()) : path)
const keys = path.split('.'), root = { ...signal() }
let acc = root, k
for (k of keys.slice(0, -1)) acc = acc[k] = { ...(acc[k] || {}) }
acc[keys.at(-1)] = value
signal(root)
}
const untrack = fn => { const untrack = fn => {
const p = activeEffect const p = activeEffect
activeEffect = null activeEffect = null
try { return fn() } finally { activeEffect = p } try { return fn() } finally { activeEffect = p }
} }
// effect creation
const createEffect = (fn, isComputed = false) => { const createEffect = (fn, isComputed = false) => {
const effect = () => { const effect = () => {
if (effect._disposed) return if (effect._disposed) return
if (effect._deps) effect._deps.forEach(s => s.delete(effect)) if (effect._deps) effect._deps.forEach(s => s.delete(effect))
if (effect._cleanups) { if (effect._cleanups) {
effect._cleanups.forEach(c => c()) effect._cleanups.forEach(c => c())
effect._cleanups.clear() 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
}
} }
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._deps = effect._cleanups = effect._children = null
effect._disposed = false effect._disposed = false
effect._isComputed = isComputed effect._isComputed = isComputed
@@ -97,6 +88,18 @@ const flush = () => {
isFlushing = false isFlushing = false
} }
const Batch = fn => {
batchDepth++
try {
return fn()
} finally {
batchDepth--
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
flush()
}
}
}
const trackUpdate = (subs, trigger = false) => { const trackUpdate = (subs, trigger = false) => {
if (!trigger && activeEffect && !activeEffect._disposed) { if (!trigger && activeEffect && !activeEffect._disposed) {
subs.add(activeEffect) subs.add(activeEffect)
@@ -113,11 +116,10 @@ const trackUpdate = (subs, trigger = false) => {
hasQueue = true hasQueue = true
} }
}) })
if (hasQueue && !isFlushing) queueMicrotask(flush) if (hasQueue && !isFlushing && batchDepth === 0) queueMicrotask(flush)
} }
} }
// signal creation
const $ = (val, key = null) => { const $ = (val, key = null) => {
const subs = new Set() const subs = new Set()
if (isFunc(val)) { if (isFunc(val)) {
@@ -170,7 +172,50 @@ const $ = (val, key = null) => {
} }
} }
// create Watch const $$ = (target) => {
if (!isObj(target)) return target
if (proxyCache.has(target)) return proxyCache.get(target)
const subsMap = new Map()
const getSubs = (k) => {
let s = subsMap.get(k)
if (!s) subsMap.set(k, s = new Set())
return s
}
const proxy = new Proxy(target, {
get(t, k) {
trackUpdate(getSubs(k))
return $$(t[k])
},
set(t, k, v) {
const isNew = !(k in t)
if (!Object.is(t[k], v)) {
t[k] = v
trackUpdate(getSubs(k), true)
if (isNew) trackUpdate(getSubs(ITER), true)
}
return true
},
deleteProperty(t, k) {
const res = Reflect.deleteProperty(t, k)
if (res) {
trackUpdate(getSubs(k), true)
trackUpdate(getSubs(ITER), true)
}
return res
},
ownKeys(t) {
trackUpdate(getSubs(ITER))
return Reflect.ownKeys(t)
}
})
proxyCache.set(target, proxy)
return proxy
}
const Watch = (sources, cb) => { const Watch = (sources, cb) => {
if (cb === undefined) { if (cb === undefined) {
const effect = createEffect(sources) const effect = createEffect(sources)
@@ -209,42 +254,41 @@ const validateAttr = (key, val) => {
return val return val
} }
// create Tag
const Tag = (tag, props = {}, children = []) => { const Tag = (tag, props = {}, children = []) => {
if (props instanceof Node || isArr(props) || !isObj(props)) { if (props instanceof Node || isArr(props) || !isObj(props)) {
children = props children = props
props = {} props = {}
} }
if (isFunc(tag)) { if (isFunc(tag)) {
const ctx = { _mounts: [], _cleanups: new Set() } const ctx = { _mounts: [], _cleanups: new Set() }
const effect = createEffect(() => { const effect = createEffect(() => {
const result = tag(props, { const result = tag(props, {
children, children,
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args) emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
})
effect._result = result
return result
}) })
effect._result = result effect()
return result
})
effect()
const result = effect._result const result = effect._result
if (result == null) return null if (result == null) return null
const node = (result instanceof Node || (isArr(result) && result.every(n => n instanceof Node))) const node = (result instanceof Node || (isArr(result) && result.every(n => n instanceof Node)))
? result ? result
: doc.createTextNode(String(result)) : doc.createTextNode(String(result))
const attach = n => { const attach = n => {
if (isObj(n) && !n._isRuntime) { if (isObj(n) && !n._isRuntime) {
n._mounts = effect._mounts || [] n._mounts = effect._mounts || []
n._cleanups = effect._cleanups || new Set() n._cleanups = effect._cleanups || new Set()
n._ownerEffect = effect n._ownerEffect = effect
}
} }
}
isArr(node) ? node.forEach(attach) : attach(node) isArr(node) ? node.forEach(attach) : attach(node)
return node return node
} }
const isSVG = /^(svg|path|circle|rect|line|polyline|polygon|g|defs|text|tspan|use)$/.test(tag) const isSVG = /^(svg|path|circle|rect|line|polyline|polygon|g|defs|text|tspan|use)$/.test(tag)
const el = isSVG ? doc.createElementNS("http://www.w3.org/2000/svg", tag) : doc.createElement(tag) const el = isSVG ? doc.createElementNS("http://www.w3.org/2000/svg", tag) : doc.createElement(tag)
el._cleanups = new Set() el._cleanups = new Set()
@@ -322,7 +366,6 @@ const Tag = (tag, props = {}, children = []) => {
return el return el
} }
// create Render
const Render = renderFn => { const Render = renderFn => {
const cleanups = new Set() const cleanups = new Set()
const mounts = [] const mounts = []
@@ -330,7 +373,7 @@ const Render = renderFn => {
const previousEffect = activeEffect const previousEffect = activeEffect
const container = doc.createElement("div") const container = doc.createElement("div")
container.style.display = "contents" container.style.display = "contents"
container.setAttribute("role", "presentation") // ← único cambio real container.setAttribute("role", "presentation")
activeOwner = { _cleanups: cleanups, _mounts: mounts } activeOwner = { _cleanups: cleanups, _mounts: mounts }
activeEffect = null activeEffect = null
@@ -365,49 +408,31 @@ const Render = renderFn => {
} }
} }
// create If const If = (cond, ifYes, ifNot = null) => {
const If = (cond, ifYes, ifNot = null, trans = null) => {
const anchor = doc.createTextNode("") const anchor = doc.createTextNode("")
const root = Tag("div", { style: "display:contents" }, [anchor]) const root = Tag("div", { style: "display:contents" }, [anchor])
let currentView = null let currentView = null
let last = null
let exitPromise = null
Watch( Watch(
() => !!(isFunc(cond) ? cond() : cond), () => !!(isFunc(cond) ? cond() : cond),
show => { show => {
if (show === last) return if (currentView) {
last = show currentView.destroy()
currentView = null
const disposeView = () => {
if (currentView) {
currentView.destroy()
currentView = null
}
}
if (currentView && !show && trans?.out) {
if (exitPromise && exitPromise.cancel) exitPromise.cancel()
const anim = trans.out(currentView.container, disposeView)
exitPromise = anim
if (anim && anim.finished) anim.finished.then(disposeView)
else disposeView()
} else {
disposeView()
} }
const content = show ? ifYes : ifNot const content = show ? ifYes : ifNot
if (content) { if (content) {
currentView = Render(() => isFunc(content) ? content() : content) currentView = Render(() => isFunc(content) ? content() : content)
root.insertBefore(currentView.container, anchor) root.insertBefore(currentView.container, anchor)
if (trans?.in) trans.in(currentView.container)
} }
} }
) )
onUnmount(() => currentView?.destroy())
return root return root
} }
// create For
const For = (src, itemFn, keyFn) => { const For = (src, itemFn, keyFn) => {
const anchor = doc.createTextNode("") const anchor = doc.createTextNode("")
const root = Tag("div", { style: "display:contents" }, [anchor]) const root = Tag("div", { style: "display:contents" }, [anchor])
@@ -438,7 +463,6 @@ const For = (src, itemFn, keyFn) => {
return root return root
} }
// create Router
const Router = routes => { const Router = routes => {
const getHash = () => window.location.hash.slice(1) || "/" const getHash = () => window.location.hash.slice(1) || "/"
const path = $(getHash()) const path = $(getHash())
@@ -482,7 +506,7 @@ const Mount = (comp, target) => {
return inst return inst
} }
const SigPro = Object.freeze({ $, Watch, Tag, Render, If, For, Router, Mount, onMount, onUnmount, set }) const SigPro = Object.freeze({ $, $$, Watch, Tag, Render, If, For, Router, Mount, onMount, onUnmount, Batch })
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
Object.assign(window, SigPro) Object.assign(window, SigPro)
@@ -490,5 +514,5 @@ if (typeof window !== "undefined") {
.split(" ").forEach(t => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c)) .split(" ").forEach(t => window[t[0].toUpperCase() + t.slice(1)] = (p, c) => SigPro.Tag(t, p, c))
} }
export { $, Watch, Tag, Render, If, For, Router, Mount, onMount, onUnmount, set } export { $, $$, Watch, Tag, Render, If, For, Router, Mount, onMount, onUnmount, Batch }
export default SigPro export default SigPro