Ok
This commit is contained in:
101
dist/sigpro-ui.esm.js
vendored
101
dist/sigpro-ui.esm.js
vendored
@@ -18,7 +18,10 @@ var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : do
|
||||
var activeEffect = null;
|
||||
var activeOwner = null;
|
||||
var isFlushing = false;
|
||||
var batchDepth = 0;
|
||||
var effectQueue = new Set;
|
||||
var proxyCache = new WeakMap;
|
||||
var ITER = Symbol("iter");
|
||||
var MOUNTED_NODES = new WeakMap;
|
||||
var dispose = (eff) => {
|
||||
if (!eff || eff._disposed)
|
||||
@@ -49,16 +52,6 @@ var onUnmount = (fn) => {
|
||||
if (activeOwner)
|
||||
(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) => {
|
||||
const p = activeEffect;
|
||||
activeEffect = null;
|
||||
@@ -111,6 +104,17 @@ var flush = () => {
|
||||
e();
|
||||
isFlushing = false;
|
||||
};
|
||||
var Batch = (fn) => {
|
||||
batchDepth++;
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
batchDepth--;
|
||||
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
var trackUpdate = (subs, trigger = false) => {
|
||||
if (!trigger && activeEffect && !activeEffect._disposed) {
|
||||
subs.add(activeEffect);
|
||||
@@ -129,7 +133,7 @@ var trackUpdate = (subs, trigger = false) => {
|
||||
hasQueue = true;
|
||||
}
|
||||
});
|
||||
if (hasQueue && !isFlushing)
|
||||
if (hasQueue && !isFlushing && batchDepth === 0)
|
||||
queueMicrotask(flush);
|
||||
}
|
||||
};
|
||||
@@ -193,6 +197,49 @@ var $2 = (val, key = null) => {
|
||||
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) => {
|
||||
if (cb === undefined) {
|
||||
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 root = Tag2("div", { style: "display:contents" }, [anchor]);
|
||||
let currentView = null;
|
||||
let last = null;
|
||||
let exitPromise = null;
|
||||
Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => {
|
||||
if (show === last)
|
||||
return;
|
||||
last = show;
|
||||
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();
|
||||
if (currentView) {
|
||||
currentView.destroy();
|
||||
currentView = null;
|
||||
}
|
||||
const content = show ? ifYes : ifNot;
|
||||
if (content) {
|
||||
currentView = Render(() => isFunc(content) ? content() : content);
|
||||
root.insertBefore(currentView.container, anchor);
|
||||
if (trans?.in)
|
||||
trans.in(currentView.container);
|
||||
}
|
||||
});
|
||||
onUnmount(() => currentView?.destroy());
|
||||
return root;
|
||||
};
|
||||
var For2 = (src, itemFn, keyFn) => {
|
||||
@@ -501,7 +528,7 @@ var Mount2 = (comp, target) => {
|
||||
MOUNTED_NODES.set(t, 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") {
|
||||
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));
|
||||
|
||||
8
dist/sigpro-ui.esm.min.js
vendored
8
dist/sigpro-ui.esm.min.js
vendored
File diff suppressed because one or more lines are too long
101
dist/sigpro-ui.js
vendored
101
dist/sigpro-ui.js
vendored
@@ -84,7 +84,10 @@
|
||||
var activeEffect = null;
|
||||
var activeOwner = null;
|
||||
var isFlushing = false;
|
||||
var batchDepth = 0;
|
||||
var effectQueue = new Set;
|
||||
var proxyCache = new WeakMap;
|
||||
var ITER = Symbol("iter");
|
||||
var MOUNTED_NODES = new WeakMap;
|
||||
var dispose = (eff) => {
|
||||
if (!eff || eff._disposed)
|
||||
@@ -115,16 +118,6 @@
|
||||
if (activeOwner)
|
||||
(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) => {
|
||||
const p = activeEffect;
|
||||
activeEffect = null;
|
||||
@@ -177,6 +170,17 @@
|
||||
e();
|
||||
isFlushing = false;
|
||||
};
|
||||
var Batch = (fn) => {
|
||||
batchDepth++;
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
batchDepth--;
|
||||
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
var trackUpdate = (subs, trigger = false) => {
|
||||
if (!trigger && activeEffect && !activeEffect._disposed) {
|
||||
subs.add(activeEffect);
|
||||
@@ -195,7 +199,7 @@
|
||||
hasQueue = true;
|
||||
}
|
||||
});
|
||||
if (hasQueue && !isFlushing)
|
||||
if (hasQueue && !isFlushing && batchDepth === 0)
|
||||
queueMicrotask(flush);
|
||||
}
|
||||
};
|
||||
@@ -259,6 +263,49 @@
|
||||
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) => {
|
||||
if (cb === undefined) {
|
||||
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 root = Tag2("div", { style: "display:contents" }, [anchor]);
|
||||
let currentView = null;
|
||||
let last = null;
|
||||
let exitPromise = null;
|
||||
Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => {
|
||||
if (show === last)
|
||||
return;
|
||||
last = show;
|
||||
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();
|
||||
if (currentView) {
|
||||
currentView.destroy();
|
||||
currentView = null;
|
||||
}
|
||||
const content = show ? ifYes : ifNot;
|
||||
if (content) {
|
||||
currentView = Render(() => isFunc(content) ? content() : content);
|
||||
root.insertBefore(currentView.container, anchor);
|
||||
if (trans?.in)
|
||||
trans.in(currentView.container);
|
||||
}
|
||||
});
|
||||
onUnmount(() => currentView?.destroy());
|
||||
return root;
|
||||
};
|
||||
var For2 = (src, itemFn, keyFn) => {
|
||||
@@ -567,7 +594,7 @@
|
||||
MOUNTED_NODES.set(t, 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") {
|
||||
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));
|
||||
|
||||
8
dist/sigpro-ui.min.js
vendored
8
dist/sigpro-ui.min.js
vendored
File diff suppressed because one or more lines are too long
101
docs/sigpro-ui.min.js
vendored
101
docs/sigpro-ui.min.js
vendored
@@ -84,7 +84,10 @@
|
||||
var activeEffect = null;
|
||||
var activeOwner = null;
|
||||
var isFlushing = false;
|
||||
var batchDepth = 0;
|
||||
var effectQueue = new Set;
|
||||
var proxyCache = new WeakMap;
|
||||
var ITER = Symbol("iter");
|
||||
var MOUNTED_NODES = new WeakMap;
|
||||
var dispose = (eff) => {
|
||||
if (!eff || eff._disposed)
|
||||
@@ -115,16 +118,6 @@
|
||||
if (activeOwner)
|
||||
(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) => {
|
||||
const p = activeEffect;
|
||||
activeEffect = null;
|
||||
@@ -177,6 +170,17 @@
|
||||
e();
|
||||
isFlushing = false;
|
||||
};
|
||||
var Batch = (fn) => {
|
||||
batchDepth++;
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
batchDepth--;
|
||||
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
var trackUpdate = (subs, trigger = false) => {
|
||||
if (!trigger && activeEffect && !activeEffect._disposed) {
|
||||
subs.add(activeEffect);
|
||||
@@ -195,7 +199,7 @@
|
||||
hasQueue = true;
|
||||
}
|
||||
});
|
||||
if (hasQueue && !isFlushing)
|
||||
if (hasQueue && !isFlushing && batchDepth === 0)
|
||||
queueMicrotask(flush);
|
||||
}
|
||||
};
|
||||
@@ -259,6 +263,49 @@
|
||||
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) => {
|
||||
if (cb === undefined) {
|
||||
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 root = Tag2("div", { style: "display:contents" }, [anchor]);
|
||||
let currentView = null;
|
||||
let last = null;
|
||||
let exitPromise = null;
|
||||
Watch2(() => !!(isFunc(cond) ? cond() : cond), (show) => {
|
||||
if (show === last)
|
||||
return;
|
||||
last = show;
|
||||
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();
|
||||
if (currentView) {
|
||||
currentView.destroy();
|
||||
currentView = null;
|
||||
}
|
||||
const content = show ? ifYes : ifNot;
|
||||
if (content) {
|
||||
currentView = Render(() => isFunc(content) ? content() : content);
|
||||
root.insertBefore(currentView.container, anchor);
|
||||
if (trans?.in)
|
||||
trans.in(currentView.container);
|
||||
}
|
||||
});
|
||||
onUnmount(() => currentView?.destroy());
|
||||
return root;
|
||||
};
|
||||
var For2 = (src, itemFn, keyFn) => {
|
||||
@@ -567,7 +594,7 @@
|
||||
MOUNTED_NODES.set(t, 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") {
|
||||
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));
|
||||
|
||||
198
src/sigpro.js
198
src/sigpro.js
@@ -8,10 +8,12 @@ const ensureNode = n => n?._isRuntime ? n.container : (n instanceof Node ? n : d
|
||||
let activeEffect = null
|
||||
let activeOwner = null
|
||||
let isFlushing = false
|
||||
let batchDepth = 0
|
||||
const effectQueue = new Set()
|
||||
const proxyCache = new WeakMap()
|
||||
const ITER = Symbol('iter')
|
||||
const MOUNTED_NODES = new WeakMap()
|
||||
|
||||
// effect cleanup
|
||||
const dispose = eff => {
|
||||
if (!eff || eff._disposed) return
|
||||
eff._disposed = true
|
||||
@@ -33,7 +35,6 @@ const dispose = eff => {
|
||||
}
|
||||
}
|
||||
|
||||
// helpers
|
||||
const onMount = fn => {
|
||||
if (activeOwner) (activeOwner._mounts ||= []).push(fn)
|
||||
}
|
||||
@@ -42,42 +43,32 @@ const onUnmount = 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 p = activeEffect
|
||||
activeEffect = null
|
||||
try { return fn() } finally { activeEffect = p }
|
||||
}
|
||||
|
||||
// effect creation
|
||||
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()
|
||||
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
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -97,6 +88,18 @@ const flush = () => {
|
||||
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)
|
||||
@@ -113,11 +116,10 @@ const trackUpdate = (subs, trigger = false) => {
|
||||
hasQueue = true
|
||||
}
|
||||
})
|
||||
if (hasQueue && !isFlushing) queueMicrotask(flush)
|
||||
if (hasQueue && !isFlushing && batchDepth === 0) queueMicrotask(flush)
|
||||
}
|
||||
}
|
||||
|
||||
// signal creation
|
||||
const $ = (val, key = null) => {
|
||||
const subs = new Set()
|
||||
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) => {
|
||||
if (cb === undefined) {
|
||||
const effect = createEffect(sources)
|
||||
@@ -209,42 +254,41 @@ const validateAttr = (key, val) => {
|
||||
return val
|
||||
}
|
||||
|
||||
// create Tag
|
||||
const Tag = (tag, props = {}, children = []) => {
|
||||
if (props instanceof Node || isArr(props) || !isObj(props)) {
|
||||
children = props
|
||||
props = {}
|
||||
}
|
||||
if (isFunc(tag)) {
|
||||
const ctx = { _mounts: [], _cleanups: new Set() }
|
||||
const effect = createEffect(() => {
|
||||
const result = tag(props, {
|
||||
children,
|
||||
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
|
||||
const ctx = { _mounts: [], _cleanups: new Set() }
|
||||
const effect = createEffect(() => {
|
||||
const result = tag(props, {
|
||||
children,
|
||||
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
|
||||
})
|
||||
effect._result = result
|
||||
return result
|
||||
})
|
||||
effect._result = result
|
||||
return result
|
||||
})
|
||||
effect()
|
||||
|
||||
const result = effect._result
|
||||
if (result == null) return null
|
||||
effect()
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
isArr(node) ? node.forEach(attach) : attach(node)
|
||||
return node
|
||||
}
|
||||
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)
|
||||
el._cleanups = new Set()
|
||||
@@ -322,7 +366,6 @@ const Tag = (tag, props = {}, children = []) => {
|
||||
return el
|
||||
}
|
||||
|
||||
// create Render
|
||||
const Render = renderFn => {
|
||||
const cleanups = new Set()
|
||||
const mounts = []
|
||||
@@ -330,7 +373,7 @@ const Render = renderFn => {
|
||||
const previousEffect = activeEffect
|
||||
const container = doc.createElement("div")
|
||||
container.style.display = "contents"
|
||||
container.setAttribute("role", "presentation") // ← único cambio real
|
||||
container.setAttribute("role", "presentation")
|
||||
activeOwner = { _cleanups: cleanups, _mounts: mounts }
|
||||
activeEffect = null
|
||||
|
||||
@@ -365,49 +408,31 @@ const Render = renderFn => {
|
||||
}
|
||||
}
|
||||
|
||||
// create If
|
||||
const If = (cond, ifYes, ifNot = null, trans = null) => {
|
||||
const If = (cond, ifYes, ifNot = null) => {
|
||||
const anchor = doc.createTextNode("")
|
||||
const root = Tag("div", { style: "display:contents" }, [anchor])
|
||||
let currentView = null
|
||||
let last = null
|
||||
let exitPromise = null
|
||||
|
||||
Watch(
|
||||
() => !!(isFunc(cond) ? cond() : cond),
|
||||
show => {
|
||||
if (show === last) return
|
||||
last = show
|
||||
|
||||
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()
|
||||
if (currentView) {
|
||||
currentView.destroy()
|
||||
currentView = null
|
||||
}
|
||||
|
||||
const content = show ? ifYes : ifNot
|
||||
if (content) {
|
||||
currentView = Render(() => isFunc(content) ? content() : content)
|
||||
root.insertBefore(currentView.container, anchor)
|
||||
if (trans?.in) trans.in(currentView.container)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onUnmount(() => currentView?.destroy())
|
||||
return root
|
||||
}
|
||||
|
||||
// create For
|
||||
const For = (src, itemFn, keyFn) => {
|
||||
const anchor = doc.createTextNode("")
|
||||
const root = Tag("div", { style: "display:contents" }, [anchor])
|
||||
@@ -438,7 +463,6 @@ const For = (src, itemFn, keyFn) => {
|
||||
return root
|
||||
}
|
||||
|
||||
// create Router
|
||||
const Router = routes => {
|
||||
const getHash = () => window.location.hash.slice(1) || "/"
|
||||
const path = $(getHash())
|
||||
@@ -482,7 +506,7 @@ const Mount = (comp, target) => {
|
||||
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") {
|
||||
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))
|
||||
}
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user