sibujs 4.4.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/browser.cjs +339 -130
- package/dist/browser.d.cts +61 -16
- package/dist/browser.d.ts +61 -16
- package/dist/browser.js +8 -6
- package/dist/build.cjs +273 -82
- package/dist/build.js +15 -16
- package/dist/cdn.dev.global.js +12 -12
- package/dist/cdn.full.dev.global.js +11 -11
- package/dist/cdn.full.global.js +10 -10
- package/dist/cdn.global.js +12 -12
- package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
- package/dist/chunk-3ISI6ACU.js +44 -0
- package/dist/{chunk-VCTAEPSB.js → chunk-47M47FOM.js} +11 -3
- package/dist/chunk-5HZXGZ6T.js +24 -0
- package/dist/{chunk-KKLW7YWL.js → chunk-5MT6SJ3P.js} +275 -144
- package/dist/{chunk-3BTTCZ5J.js → chunk-5Q4R7HCL.js} +42 -4
- package/dist/{chunk-ADM46X22.js → chunk-7GQCWFOE.js} +157 -61
- package/dist/{chunk-4Z3SPQ67.js → chunk-7NCARGJW.js} +16 -8
- package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
- package/dist/{chunk-LQFGQNMV.js → chunk-AIF3Z2T7.js} +302 -39
- package/dist/{chunk-UCALUKB5.js → chunk-BAAG6ZTI.js} +98 -29
- package/dist/{chunk-NVNJH22U.js → chunk-D33YTSX5.js} +2 -2
- package/dist/{chunk-M2F7TZHH.js → chunk-DKGBBKOF.js} +136 -80
- package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
- package/dist/{chunk-HFCOH2GN.js → chunk-HYXDKS4N.js} +153 -110
- package/dist/chunk-J6FW5TV6.js +233 -0
- package/dist/{chunk-36S2YPP4.js → chunk-JSXPZCET.js} +1 -1
- package/dist/chunk-NYNYSPK7.js +318 -0
- package/dist/{chunk-HQSEH5F6.js → chunk-ORMZXBKQ.js} +108 -45
- package/dist/{chunk-LYVUX7NT.js → chunk-OXUY2A6L.js} +287 -130
- package/dist/{chunk-6GSIXTWX.js → chunk-PK6FK2G2.js} +187 -66
- package/dist/{chunk-W2EQ7X2L.js → chunk-QE4TTDU3.js} +47 -9
- package/dist/{chunk-XLO7SLIX.js → chunk-SXXVZMKZ.js} +262 -70
- package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
- package/dist/{chunk-RR7M3FHM.js → chunk-UZQ6ALFS.js} +3 -3
- package/dist/{chunk-PNIRUQ4C.js → chunk-VVWPJ543.js} +6 -8
- package/dist/{chunk-7GIHSAWB.js → chunk-XC4MEKGA.js} +3 -3
- package/dist/{chunk-SKPTERHP.js → chunk-XRRZKZYX.js} +55 -31
- package/dist/{contracts-DBdg9J_a.d.cts → contracts-DRIuclVT.d.cts} +10 -2
- package/dist/{contracts-DBdg9J_a.d.ts → contracts-DRIuclVT.d.ts} +10 -2
- package/dist/{customElement-CNZxEB9G.d.ts → customElement-MmInOW1U.d.cts} +59 -10
- package/dist/{customElement-CNZxEB9G.d.cts → customElement-MmInOW1U.d.ts} +59 -10
- package/dist/data.cjs +293 -125
- package/dist/data.d.cts +47 -9
- package/dist/data.d.ts +47 -9
- package/dist/data.js +12 -9
- package/dist/devtools.cjs +121 -58
- package/dist/devtools.js +7 -8
- package/dist/dispose-GEIG2KOF.js +28 -0
- package/dist/ecosystem.cjs +391 -112
- package/dist/ecosystem.d.cts +31 -7
- package/dist/ecosystem.d.ts +31 -7
- package/dist/ecosystem.js +12 -12
- package/dist/extras.cjs +2250 -879
- package/dist/extras.d.cts +10 -9
- package/dist/extras.d.ts +10 -9
- package/dist/extras.js +39 -28
- package/dist/index.cjs +273 -82
- package/dist/index.d.cts +44 -154
- package/dist/index.d.ts +44 -154
- package/dist/index.js +24 -27
- package/dist/motion.cjs +137 -42
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +397 -48
- package/dist/patterns.d.cts +32 -9
- package/dist/patterns.d.ts +32 -9
- package/dist/patterns.js +8 -8
- package/dist/performance.cjs +338 -217
- package/dist/performance.d.cts +2 -2
- package/dist/performance.d.ts +2 -2
- package/dist/performance.js +8 -9
- package/dist/plugin-DVgSnTfK.d.cts +112 -0
- package/dist/plugin-DVgSnTfK.d.ts +112 -0
- package/dist/plugins.cjs +587 -203
- package/dist/plugins.d.cts +3 -3
- package/dist/plugins.d.ts +3 -3
- package/dist/plugins.js +35 -23
- package/dist/signal-EotCj4hS.d.cts +110 -0
- package/dist/signal-EotCj4hS.d.ts +110 -0
- package/dist/{ssr-BiPRdZ6n.d.cts → ssr-Bli9XRW5.d.cts} +5 -0
- package/dist/{ssr-BiPRdZ6n.d.ts → ssr-Bli9XRW5.d.ts} +5 -0
- package/dist/{ssr-Y7XOEPEN.js → ssr-XOTUASDO.js} +4 -5
- package/dist/ssr.cjs +214 -73
- package/dist/ssr.d.cts +9 -3
- package/dist/ssr.d.ts +9 -3
- package/dist/ssr.js +11 -12
- package/dist/{startup-BMpaiMhP.d.ts → startup-BLfSeL15.d.cts} +73 -22
- package/dist/{startup-BMpaiMhP.d.cts → startup-BLfSeL15.d.ts} +73 -22
- package/dist/tagFactory-DFstCLQV.d.cts +117 -0
- package/dist/tagFactory-DkaNVUNV.d.ts +117 -0
- package/dist/testing.cjs +2481 -2153
- package/dist/testing.d.cts +56 -5
- package/dist/testing.d.ts +56 -5
- package/dist/testing.js +580 -307
- package/dist/ui.cjs +798 -328
- package/dist/ui.d.cts +40 -7
- package/dist/ui.d.ts +40 -7
- package/dist/ui.js +151 -56
- package/dist/widgets.cjs +319 -285
- package/dist/widgets.js +9 -10
- package/package.json +2 -2
- package/dist/chunk-2WLZ6757.js +0 -149
- package/dist/chunk-7NBDXVHS.js +0 -60
- package/dist/chunk-CCSJMTRN.js +0 -15
- package/dist/chunk-QKRPLZ2V.js +0 -108
- package/dist/chunk-WWV3SJ3L.js +0 -131
- package/dist/dispose-46BOMMQJ.js +0 -19
- package/dist/plugin-D30wlGW5.d.cts +0 -71
- package/dist/plugin-D30wlGW5.d.ts +0 -71
- package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
- package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
package/dist/ecosystem.cjs
CHANGED
|
@@ -141,6 +141,90 @@ function reportError(error, context) {
|
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
// src/core/rendering/dispose.ts
|
|
145
|
+
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
146
|
+
var MAX_DRAIN_TEARDOWNS = 1e4;
|
|
147
|
+
function reportDrainRunaway(label, executed, remaining) {
|
|
148
|
+
if (typeof console === "undefined") return;
|
|
149
|
+
console.error(
|
|
150
|
+
`[SibuJS ${label}] runaway cleanup: stopped after running ${executed} teardowns with ${remaining} still queued. Cleanup production did not stabilize before the teardown safety ceiling was reached \u2014 the remaining work was NOT run.`,
|
|
151
|
+
{ executed, remaining }
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
var activeBindingCount = 0;
|
|
155
|
+
function resolveCapture(capture) {
|
|
156
|
+
let frame = capture;
|
|
157
|
+
while (frame?.closed) frame = frame.forwardTo;
|
|
158
|
+
return frame ?? null;
|
|
159
|
+
}
|
|
160
|
+
var registrationCaptures = [];
|
|
161
|
+
function currentDisposerCapture() {
|
|
162
|
+
return resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
|
|
163
|
+
}
|
|
164
|
+
function beginDisposerCapture(capture) {
|
|
165
|
+
if (capture === null && registrationCaptures.length === 0) return false;
|
|
166
|
+
registrationCaptures.push(resolveCapture(capture));
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
function endDisposerCapture() {
|
|
170
|
+
registrationCaptures.pop();
|
|
171
|
+
}
|
|
172
|
+
function registerDisposer(node, teardown) {
|
|
173
|
+
let disposers = elementDisposers.get(node);
|
|
174
|
+
if (!disposers) {
|
|
175
|
+
disposers = [];
|
|
176
|
+
elementDisposers.set(node, disposers);
|
|
177
|
+
}
|
|
178
|
+
disposers.push(teardown);
|
|
179
|
+
if (DEV) activeBindingCount++;
|
|
180
|
+
const capture = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
|
|
181
|
+
if (capture) capture.entries.push([node, teardown]);
|
|
182
|
+
}
|
|
183
|
+
function dispose(node) {
|
|
184
|
+
const stack = [node];
|
|
185
|
+
const order = [];
|
|
186
|
+
while (stack.length > 0) {
|
|
187
|
+
const current = stack.pop();
|
|
188
|
+
order.push(current);
|
|
189
|
+
const children = Array.from(current.childNodes);
|
|
190
|
+
for (let i = 0; i < children.length; i++) {
|
|
191
|
+
stack.push(children[i]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
for (let i = order.length - 1; i >= 0; i--) {
|
|
195
|
+
disposeNodeOwn(order[i]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function disposeNodeOwn(node) {
|
|
199
|
+
if (!elementDisposers.has(node)) return;
|
|
200
|
+
let executed = 0;
|
|
201
|
+
let runaway = false;
|
|
202
|
+
while (!runaway) {
|
|
203
|
+
const pending = elementDisposers.get(node);
|
|
204
|
+
if (!pending || pending.length === 0) break;
|
|
205
|
+
const snapshot = pending.slice();
|
|
206
|
+
elementDisposers.delete(node);
|
|
207
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
208
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
209
|
+
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
210
|
+
const rest = snapshot.slice(i);
|
|
211
|
+
const added = elementDisposers.get(node);
|
|
212
|
+
elementDisposers.set(node, added ? rest.concat(added) : rest);
|
|
213
|
+
if (DEV) activeBindingCount += rest.length;
|
|
214
|
+
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
215
|
+
runaway = true;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
executed++;
|
|
219
|
+
try {
|
|
220
|
+
snapshot[i]();
|
|
221
|
+
} catch (err) {
|
|
222
|
+
reportError(err, { phase: "cleanup", name: "disposer" });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
144
228
|
// src/reactivity/track-core.ts
|
|
145
229
|
var POOL_MAX = 4096;
|
|
146
230
|
var nodePool = [];
|
|
@@ -288,8 +372,18 @@ function untracked(fn) {
|
|
|
288
372
|
var subscriberEpochCounter = 0;
|
|
289
373
|
function retrack(effectFn, subscriber) {
|
|
290
374
|
const prev = currentSubscriber;
|
|
375
|
+
let savedDepth = 0;
|
|
376
|
+
let savedSuspendSub = null;
|
|
377
|
+
if (trackingSuspended) {
|
|
378
|
+
savedDepth = suspendDepth;
|
|
379
|
+
savedSuspendSub = suspendSavedSub;
|
|
380
|
+
suspendDepth = 0;
|
|
381
|
+
suspendSavedSub = null;
|
|
382
|
+
trackingSuspended = false;
|
|
383
|
+
}
|
|
291
384
|
currentSubscriber = subscriber;
|
|
292
385
|
const sub = subscriber;
|
|
386
|
+
if (sub._cap === void 0) sub._cap = currentDisposerCapture();
|
|
293
387
|
const epoch = ++subscriberEpochCounter;
|
|
294
388
|
sub._epoch = epoch;
|
|
295
389
|
sub._structDirty = false;
|
|
@@ -302,6 +396,11 @@ function retrack(effectFn, subscriber) {
|
|
|
302
396
|
effectFn();
|
|
303
397
|
} finally {
|
|
304
398
|
currentSubscriber = prev;
|
|
399
|
+
if (savedDepth !== 0) {
|
|
400
|
+
suspendDepth = savedDepth;
|
|
401
|
+
suspendSavedSub = savedSuspendSub;
|
|
402
|
+
trackingSuspended = true;
|
|
403
|
+
}
|
|
305
404
|
let node = sub.depsHead ?? null;
|
|
306
405
|
while (node !== null) {
|
|
307
406
|
const next = node.subNext;
|
|
@@ -321,11 +420,25 @@ function track(effectFn, subscriber) {
|
|
|
321
420
|
if (!subscriber) return reactiveBinding(effectFn);
|
|
322
421
|
cleanup(subscriber);
|
|
323
422
|
const prev = currentSubscriber;
|
|
423
|
+
let savedDepth = 0;
|
|
424
|
+
let savedSuspendSub = null;
|
|
425
|
+
if (trackingSuspended) {
|
|
426
|
+
savedDepth = suspendDepth;
|
|
427
|
+
savedSuspendSub = suspendSavedSub;
|
|
428
|
+
suspendDepth = 0;
|
|
429
|
+
suspendSavedSub = null;
|
|
430
|
+
trackingSuspended = false;
|
|
431
|
+
}
|
|
324
432
|
currentSubscriber = subscriber;
|
|
325
433
|
try {
|
|
326
434
|
effectFn();
|
|
327
435
|
} finally {
|
|
328
436
|
currentSubscriber = prev;
|
|
437
|
+
if (savedDepth !== 0) {
|
|
438
|
+
suspendDepth = savedDepth;
|
|
439
|
+
suspendSavedSub = savedSuspendSub;
|
|
440
|
+
trackingSuspended = true;
|
|
441
|
+
}
|
|
329
442
|
const sub2 = subscriber;
|
|
330
443
|
for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
|
|
331
444
|
const sig = n.sig;
|
|
@@ -462,7 +575,12 @@ function drainQueue() {
|
|
|
462
575
|
quarantined.add(sub);
|
|
463
576
|
continue;
|
|
464
577
|
}
|
|
465
|
-
|
|
578
|
+
const pushed = beginDisposerCapture(sub._cap ?? null);
|
|
579
|
+
try {
|
|
580
|
+
safeInvoke(sub);
|
|
581
|
+
} finally {
|
|
582
|
+
if (pushed) endDisposerCapture();
|
|
583
|
+
}
|
|
466
584
|
}
|
|
467
585
|
}
|
|
468
586
|
function drainNotificationQueue() {
|
|
@@ -496,8 +614,9 @@ function propagateDirty(sub) {
|
|
|
496
614
|
if (s._c) {
|
|
497
615
|
const nSig = s._sig;
|
|
498
616
|
if (nSig) {
|
|
499
|
-
if (!nSig._d) {
|
|
617
|
+
if (!nSig._d || nSig._f === true) {
|
|
500
618
|
nSig._d = true;
|
|
619
|
+
nSig._f = false;
|
|
501
620
|
stack.push(nSig);
|
|
502
621
|
}
|
|
503
622
|
} else {
|
|
@@ -597,7 +716,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
597
716
|
}
|
|
598
717
|
|
|
599
718
|
// src/reactivity/track.ts
|
|
600
|
-
var _runtimeVersion = true ? "4.
|
|
719
|
+
var _runtimeVersion = true ? "4.6.0" : "dev";
|
|
601
720
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
602
721
|
function resolveReactiveApi() {
|
|
603
722
|
const g = globalThis;
|
|
@@ -937,6 +1056,27 @@ function signal(initial, options) {
|
|
|
937
1056
|
return [get, set];
|
|
938
1057
|
}
|
|
939
1058
|
|
|
1059
|
+
// src/utils/adoptThenable.ts
|
|
1060
|
+
function adoptThenable(value) {
|
|
1061
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return null;
|
|
1062
|
+
let then;
|
|
1063
|
+
try {
|
|
1064
|
+
then = value.then;
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
return Promise.reject(error);
|
|
1067
|
+
}
|
|
1068
|
+
if (typeof then !== "function") return null;
|
|
1069
|
+
return new Promise((resolve, reject) => {
|
|
1070
|
+
queueMicrotask(() => {
|
|
1071
|
+
try {
|
|
1072
|
+
Reflect.apply(then, value, [resolve, reject]);
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
reject(error);
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
|
|
940
1080
|
// src/utils/globalSingleton.ts
|
|
941
1081
|
function globalSingleton(key, create) {
|
|
942
1082
|
const g = globalThis;
|
|
@@ -944,37 +1084,127 @@ function globalSingleton(key, create) {
|
|
|
944
1084
|
}
|
|
945
1085
|
|
|
946
1086
|
// src/plugins/plugin.ts
|
|
1087
|
+
var CANCELLED_BRAND = /* @__PURE__ */ Symbol.for("sibujs.plugins.installCancelled.v1");
|
|
1088
|
+
var _a;
|
|
1089
|
+
var PluginInstallCancelledError = class extends Error {
|
|
1090
|
+
constructor(pluginName) {
|
|
1091
|
+
super(`[Plugin] Installation of "${pluginName}" was cancelled before it was committed (registry reset).`);
|
|
1092
|
+
/**
|
|
1093
|
+
* Brand, not identity: the default registry is shared across duplicate copies
|
|
1094
|
+
* of this module, so the error a caller receives may come from another copy's
|
|
1095
|
+
* constructor. `instanceof` is taught to recognise the brand instead.
|
|
1096
|
+
*/
|
|
1097
|
+
this[_a] = true;
|
|
1098
|
+
this.name = "PluginInstallCancelledError";
|
|
1099
|
+
this.pluginName = pluginName;
|
|
1100
|
+
}
|
|
1101
|
+
static [(_a = CANCELLED_BRAND, Symbol.hasInstance)](value) {
|
|
1102
|
+
return isPluginInstallCancelledError(value);
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
function isPluginInstallCancelledError(value) {
|
|
1106
|
+
return typeof value === "object" && value !== null && value[CANCELLED_BRAND] === true;
|
|
1107
|
+
}
|
|
947
1108
|
function createPluginRegistry() {
|
|
948
1109
|
const installedPlugins = /* @__PURE__ */ new Set();
|
|
949
1110
|
const hooks = { init: [], mount: [], unmount: [], error: [] };
|
|
950
1111
|
const provided = /* @__PURE__ */ new Map();
|
|
1112
|
+
const installStack = /* @__PURE__ */ new Set();
|
|
1113
|
+
const pendingInstalls = /* @__PURE__ */ new Map();
|
|
1114
|
+
let generation = 0;
|
|
951
1115
|
const registry = {
|
|
952
1116
|
installedPlugins,
|
|
953
1117
|
hooks,
|
|
954
1118
|
provided,
|
|
1119
|
+
/**
|
|
1120
|
+
* Install a plugin as a transaction.
|
|
1121
|
+
*
|
|
1122
|
+
* Hooks and providers registered through `ctx` are staged and committed
|
|
1123
|
+
* only if `install()` returns; a throwing install leaves the registry
|
|
1124
|
+
* exactly as it found it (and can simply be retried). The plugin is marked
|
|
1125
|
+
* installed at commit, before its init hooks run.
|
|
1126
|
+
*
|
|
1127
|
+
* Each `plugin()` call is its own transaction: a dependency installed by a
|
|
1128
|
+
* nested `plugin()` call commits on its own and stays installed even if the
|
|
1129
|
+
* outer installation later fails.
|
|
1130
|
+
*/
|
|
955
1131
|
plugin(p, options) {
|
|
956
1132
|
if (installedPlugins.has(p.name)) {
|
|
957
1133
|
console.warn(`[Plugin] "${p.name}" is already installed.`);
|
|
958
1134
|
return;
|
|
959
1135
|
}
|
|
1136
|
+
if (installStack.has(p.name)) {
|
|
1137
|
+
throw new Error(`[Plugin] "${p.name}" is already being installed (recursive installation).`);
|
|
1138
|
+
}
|
|
1139
|
+
if (pendingInstalls.has(p.name)) {
|
|
1140
|
+
throw new Error(`[Plugin] "${p.name}" is already being installed (asynchronous installation in flight).`);
|
|
1141
|
+
}
|
|
1142
|
+
const staged = { init: [], mount: [], unmount: [], error: [] };
|
|
1143
|
+
const stagedProvided = /* @__PURE__ */ new Map();
|
|
1144
|
+
let committed = false;
|
|
1145
|
+
const myGeneration = generation;
|
|
1146
|
+
const stale = () => {
|
|
1147
|
+
if (myGeneration === generation) return false;
|
|
1148
|
+
if (DEV) devWarn(`plugin: "${p.name}" registered after the registry was reset; the registration was ignored.`);
|
|
1149
|
+
return true;
|
|
1150
|
+
};
|
|
1151
|
+
const target = () => stale() ? null : committed ? hooks : staged;
|
|
960
1152
|
const ctx = {
|
|
961
|
-
onInit: (cb) =>
|
|
962
|
-
onMount: (cb) =>
|
|
963
|
-
onUnmount: (cb) =>
|
|
964
|
-
onError: (cb) =>
|
|
965
|
-
provide: (key, value) =>
|
|
1153
|
+
onInit: (cb) => void target()?.init.push(cb),
|
|
1154
|
+
onMount: (cb) => void target()?.mount.push(cb),
|
|
1155
|
+
onUnmount: (cb) => void target()?.unmount.push(cb),
|
|
1156
|
+
onError: (cb) => void target()?.error.push(cb),
|
|
1157
|
+
provide: (key, value) => {
|
|
1158
|
+
if (stale()) return;
|
|
1159
|
+
(committed ? provided : stagedProvided).set(key, value);
|
|
1160
|
+
}
|
|
966
1161
|
};
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1162
|
+
const commit = () => {
|
|
1163
|
+
if (myGeneration !== generation) return false;
|
|
1164
|
+
hooks.init.push(...staged.init);
|
|
1165
|
+
hooks.mount.push(...staged.mount);
|
|
1166
|
+
hooks.unmount.push(...staged.unmount);
|
|
1167
|
+
hooks.error.push(...staged.error);
|
|
1168
|
+
for (const [key, value] of stagedProvided) provided.set(key, value);
|
|
1169
|
+
installedPlugins.add(p.name);
|
|
1170
|
+
committed = true;
|
|
1171
|
+
if (pendingInstalls.get(p.name) === myGeneration) pendingInstalls.delete(p.name);
|
|
1172
|
+
for (const cb of staged.init.slice()) {
|
|
1173
|
+
try {
|
|
1174
|
+
cb();
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
console.error(`[Plugin] "${p.name}" init error:`, e);
|
|
1177
|
+
}
|
|
976
1178
|
}
|
|
1179
|
+
return true;
|
|
1180
|
+
};
|
|
1181
|
+
installStack.add(p.name);
|
|
1182
|
+
let pending;
|
|
1183
|
+
try {
|
|
1184
|
+
pending = adoptThenable(p.install(ctx, options));
|
|
1185
|
+
} finally {
|
|
1186
|
+
installStack.delete(p.name);
|
|
977
1187
|
}
|
|
1188
|
+
if (!pending) {
|
|
1189
|
+
if (!commit()) throw new PluginInstallCancelledError(p.name);
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
if (myGeneration === generation) pendingInstalls.set(p.name, myGeneration);
|
|
1193
|
+
const settled = pending.then(
|
|
1194
|
+
() => {
|
|
1195
|
+
if (commit()) return;
|
|
1196
|
+
if (pendingInstalls.get(p.name) === myGeneration) pendingInstalls.delete(p.name);
|
|
1197
|
+
throw new PluginInstallCancelledError(p.name);
|
|
1198
|
+
},
|
|
1199
|
+
(err) => {
|
|
1200
|
+
if (pendingInstalls.get(p.name) === myGeneration) pendingInstalls.delete(p.name);
|
|
1201
|
+
reportError(err, { phase: "async", name: `plugin(${p.name})` });
|
|
1202
|
+
throw err;
|
|
1203
|
+
}
|
|
1204
|
+
);
|
|
1205
|
+
settled.catch(() => {
|
|
1206
|
+
});
|
|
1207
|
+
return settled;
|
|
978
1208
|
},
|
|
979
1209
|
inject(key, defaultValue) {
|
|
980
1210
|
if (provided.has(key)) return provided.get(key);
|
|
@@ -1012,6 +1242,8 @@ function createPluginRegistry() {
|
|
|
1012
1242
|
}
|
|
1013
1243
|
},
|
|
1014
1244
|
reset() {
|
|
1245
|
+
generation++;
|
|
1246
|
+
pendingInstalls.clear();
|
|
1015
1247
|
installedPlugins.clear();
|
|
1016
1248
|
hooks.init.length = 0;
|
|
1017
1249
|
hooks.mount.length = 0;
|
|
@@ -1084,10 +1316,14 @@ function derived(getter, options) {
|
|
|
1084
1316
|
const cs = {};
|
|
1085
1317
|
cs._d = false;
|
|
1086
1318
|
cs._init = false;
|
|
1319
|
+
cs._f = false;
|
|
1087
1320
|
cs._g = getter;
|
|
1088
1321
|
cs.__v = 0;
|
|
1322
|
+
let evaluating = false;
|
|
1323
|
+
let disposed = false;
|
|
1324
|
+
let pendingError;
|
|
1089
1325
|
const markDirty = () => {
|
|
1090
|
-
if (cs._d) return;
|
|
1326
|
+
if (cs._d || disposed) return;
|
|
1091
1327
|
cs._d = true;
|
|
1092
1328
|
};
|
|
1093
1329
|
markDirty._c = 1;
|
|
@@ -1110,33 +1346,53 @@ function derived(getter, options) {
|
|
|
1110
1346
|
}
|
|
1111
1347
|
}, markDirty);
|
|
1112
1348
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1113
|
-
let evaluating = false;
|
|
1114
1349
|
const validate = () => {
|
|
1115
|
-
if (!cs._d) return;
|
|
1350
|
+
if (!cs._d || disposed || pendingError !== void 0) return;
|
|
1116
1351
|
const oldValue = cs._v;
|
|
1117
1352
|
evaluating = true;
|
|
1118
1353
|
try {
|
|
1119
1354
|
retrack2(recompute, markDirty);
|
|
1120
1355
|
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
1356
|
+
} catch (err) {
|
|
1357
|
+
pendingError = { error: err };
|
|
1358
|
+
cs.__v++;
|
|
1359
|
+
if (disposed) cs._d = true;
|
|
1360
|
+
else cs._f = true;
|
|
1121
1361
|
} finally {
|
|
1122
1362
|
evaluating = false;
|
|
1363
|
+
if (disposed) cleanup2(markDirty);
|
|
1123
1364
|
}
|
|
1124
|
-
if (hook && !Object.is(oldValue, cs._v)) {
|
|
1365
|
+
if (hook && !disposed && !Object.is(oldValue, cs._v)) {
|
|
1125
1366
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
1126
1367
|
}
|
|
1127
1368
|
};
|
|
1128
1369
|
cs._validate = validate;
|
|
1370
|
+
const throwPending = () => {
|
|
1371
|
+
const { error } = pendingError;
|
|
1372
|
+
pendingError = void 0;
|
|
1373
|
+
if (disposed) cs._d = false;
|
|
1374
|
+
throw error;
|
|
1375
|
+
};
|
|
1129
1376
|
function computedGetter() {
|
|
1130
1377
|
if (evaluating) {
|
|
1131
1378
|
throw new Error(
|
|
1132
1379
|
`[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
|
|
1133
1380
|
);
|
|
1134
1381
|
}
|
|
1135
|
-
if (isTrackingSuspended2()) {
|
|
1136
|
-
if (cs._d)
|
|
1382
|
+
if (isTrackingSuspended2() || disposed) {
|
|
1383
|
+
if (cs._d) {
|
|
1384
|
+
validate();
|
|
1385
|
+
if (pendingError !== void 0) throwPending();
|
|
1386
|
+
}
|
|
1137
1387
|
return cs._v;
|
|
1138
1388
|
}
|
|
1139
|
-
if (cs._d)
|
|
1389
|
+
if (cs._d) {
|
|
1390
|
+
validate();
|
|
1391
|
+
if (pendingError !== void 0) {
|
|
1392
|
+
recordDependency2(cs);
|
|
1393
|
+
throwPending();
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1140
1396
|
recordDependency2(cs);
|
|
1141
1397
|
return cs._v;
|
|
1142
1398
|
}
|
|
@@ -1145,6 +1401,19 @@ function derived(getter, options) {
|
|
|
1145
1401
|
cs.__name = debugName;
|
|
1146
1402
|
}
|
|
1147
1403
|
computedGetter.__signal = cs;
|
|
1404
|
+
computedGetter.dispose = () => {
|
|
1405
|
+
if (disposed) return;
|
|
1406
|
+
disposed = true;
|
|
1407
|
+
cs._d = pendingError !== void 0;
|
|
1408
|
+
cleanup2(markDirty);
|
|
1409
|
+
const h = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1410
|
+
if (h) {
|
|
1411
|
+
try {
|
|
1412
|
+
h.emit("computed:destroy", { signal: cs, getter: computedGetter });
|
|
1413
|
+
} catch {
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1148
1417
|
if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
|
|
1149
1418
|
return computedGetter;
|
|
1150
1419
|
}
|
|
@@ -1462,6 +1731,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1462
1731
|
const html = isHtmlElement(el);
|
|
1463
1732
|
const idlName = html ? name.toLowerCase() : name;
|
|
1464
1733
|
if (typeof value === "boolean") {
|
|
1734
|
+
if (name.length > 5 && name.slice(0, 5).toLowerCase() === "aria-") {
|
|
1735
|
+
const token = value ? "true" : "false";
|
|
1736
|
+
if ((ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name)) !== token) {
|
|
1737
|
+
if (ns) el.setAttributeNS(ns, name, token);
|
|
1738
|
+
else el.setAttribute(name, token);
|
|
1739
|
+
}
|
|
1740
|
+
return true;
|
|
1741
|
+
}
|
|
1465
1742
|
if (html && BOOLEAN_IDL_ATTRS.has(idlName) && idlName in el) {
|
|
1466
1743
|
setProp(el, idlName, value);
|
|
1467
1744
|
} else if (value) {
|
|
@@ -1507,70 +1784,6 @@ function bindAttribute(el, attr, getter) {
|
|
|
1507
1784
|
return reactiveBinding2(commit, el);
|
|
1508
1785
|
}
|
|
1509
1786
|
|
|
1510
|
-
// src/core/rendering/dispose.ts
|
|
1511
|
-
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
1512
|
-
var MAX_DRAIN_TEARDOWNS = 1e4;
|
|
1513
|
-
function reportDrainRunaway(label, executed, remaining) {
|
|
1514
|
-
if (typeof console === "undefined") return;
|
|
1515
|
-
console.error(
|
|
1516
|
-
`[SibuJS ${label}] runaway cleanup: stopped after running ${executed} teardowns with ${remaining} still queued. Cleanup production did not stabilize before the teardown safety ceiling was reached \u2014 the remaining work was NOT run.`,
|
|
1517
|
-
{ executed, remaining }
|
|
1518
|
-
);
|
|
1519
|
-
}
|
|
1520
|
-
var activeBindingCount = 0;
|
|
1521
|
-
function registerDisposer(node, teardown) {
|
|
1522
|
-
let disposers = elementDisposers.get(node);
|
|
1523
|
-
if (!disposers) {
|
|
1524
|
-
disposers = [];
|
|
1525
|
-
elementDisposers.set(node, disposers);
|
|
1526
|
-
}
|
|
1527
|
-
disposers.push(teardown);
|
|
1528
|
-
if (DEV) activeBindingCount++;
|
|
1529
|
-
}
|
|
1530
|
-
function dispose(node) {
|
|
1531
|
-
const stack = [node];
|
|
1532
|
-
const order = [];
|
|
1533
|
-
while (stack.length > 0) {
|
|
1534
|
-
const current = stack.pop();
|
|
1535
|
-
order.push(current);
|
|
1536
|
-
const children = Array.from(current.childNodes);
|
|
1537
|
-
for (let i = 0; i < children.length; i++) {
|
|
1538
|
-
stack.push(children[i]);
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
for (let i = order.length - 1; i >= 0; i--) {
|
|
1542
|
-
const current = order[i];
|
|
1543
|
-
if (elementDisposers.has(current)) {
|
|
1544
|
-
let executed = 0;
|
|
1545
|
-
let runaway = false;
|
|
1546
|
-
while (!runaway) {
|
|
1547
|
-
const pending = elementDisposers.get(current);
|
|
1548
|
-
if (!pending || pending.length === 0) break;
|
|
1549
|
-
const snapshot = pending.slice();
|
|
1550
|
-
elementDisposers.delete(current);
|
|
1551
|
-
if (DEV) activeBindingCount -= snapshot.length;
|
|
1552
|
-
for (let i2 = 0; i2 < snapshot.length; i2++) {
|
|
1553
|
-
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
1554
|
-
const rest = snapshot.slice(i2);
|
|
1555
|
-
const added = elementDisposers.get(current);
|
|
1556
|
-
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
1557
|
-
if (DEV) activeBindingCount += rest.length;
|
|
1558
|
-
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
1559
|
-
runaway = true;
|
|
1560
|
-
break;
|
|
1561
|
-
}
|
|
1562
|
-
executed++;
|
|
1563
|
-
try {
|
|
1564
|
-
snapshot[i2]();
|
|
1565
|
-
} catch (err) {
|
|
1566
|
-
reportError(err, { phase: "cleanup", name: "disposer" });
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
1787
|
// src/core/rendering/focusPreservation.ts
|
|
1575
1788
|
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
1576
1789
|
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
@@ -1991,53 +2204,119 @@ var tagFactory = (tag, ns) => {
|
|
|
1991
2204
|
};
|
|
1992
2205
|
|
|
1993
2206
|
// src/ecosystem/ui/componentAdapter.ts
|
|
2207
|
+
var _themeLayers = globalSingleton(
|
|
2208
|
+
/* @__PURE__ */ Symbol.for("sibujs.themeLayers.v1"),
|
|
2209
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
2210
|
+
);
|
|
2211
|
+
function commitThemeProperty(root, name, record) {
|
|
2212
|
+
const top = record.layers[record.layers.length - 1];
|
|
2213
|
+
if (top) {
|
|
2214
|
+
root.style.setProperty(name, top.value);
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
_themeLayers.get(root)?.delete(name);
|
|
2218
|
+
if (record.original.value === "") root.style.removeProperty(name);
|
|
2219
|
+
else root.style.setProperty(name, record.original.value, record.original.priority);
|
|
2220
|
+
}
|
|
2221
|
+
function setThemeLayer(root, name, handle, value) {
|
|
2222
|
+
let properties = _themeLayers.get(root);
|
|
2223
|
+
if (!properties) _themeLayers.set(root, properties = /* @__PURE__ */ new Map());
|
|
2224
|
+
let record = properties.get(name);
|
|
2225
|
+
if (!record) {
|
|
2226
|
+
record = {
|
|
2227
|
+
original: { value: root.style.getPropertyValue(name), priority: root.style.getPropertyPriority(name) },
|
|
2228
|
+
layers: []
|
|
2229
|
+
};
|
|
2230
|
+
properties.set(name, record);
|
|
2231
|
+
}
|
|
2232
|
+
const layer = record.layers.find((l) => l.handle === handle);
|
|
2233
|
+
if (layer) layer.value = value;
|
|
2234
|
+
else record.layers.push({ handle, value });
|
|
2235
|
+
commitThemeProperty(root, name, record);
|
|
2236
|
+
}
|
|
2237
|
+
function removeThemeLayer(root, name, handle) {
|
|
2238
|
+
const record = _themeLayers.get(root)?.get(name);
|
|
2239
|
+
if (!record) return;
|
|
2240
|
+
const index = record.layers.findIndex((l) => l.handle === handle);
|
|
2241
|
+
if (index === -1) return;
|
|
2242
|
+
record.layers.splice(index, 1);
|
|
2243
|
+
commitThemeProperty(root, name, record);
|
|
2244
|
+
}
|
|
2245
|
+
function ownString(map, key) {
|
|
2246
|
+
if (!map || key === void 0 || !Object.hasOwn(map, key)) return void 0;
|
|
2247
|
+
const value = map[key];
|
|
2248
|
+
return typeof value === "string" ? value : void 0;
|
|
2249
|
+
}
|
|
1994
2250
|
function createTheme(initial) {
|
|
1995
2251
|
const [getConfig, setConfig] = signal(initial);
|
|
1996
2252
|
function resolveClass(component, variant) {
|
|
1997
2253
|
const config = getConfig();
|
|
1998
2254
|
const overrideKey = variant ? `${component}-${variant}` : component;
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
}
|
|
2255
|
+
const override = ownString(config.classOverrides, overrideKey);
|
|
2256
|
+
if (override) return override;
|
|
2002
2257
|
const base = `${config.prefix}-${component}`;
|
|
2003
2258
|
return variant ? `${base} ${config.prefix}-${component}--${variant}` : base;
|
|
2004
2259
|
}
|
|
2005
2260
|
function setTheme(partial) {
|
|
2006
2261
|
setConfig((prev) => ({ ...prev, ...partial }));
|
|
2007
2262
|
}
|
|
2008
|
-
|
|
2263
|
+
function applyTo(root) {
|
|
2264
|
+
const handle = {};
|
|
2265
|
+
let applied = /* @__PURE__ */ new Set();
|
|
2266
|
+
const stop = effect(() => {
|
|
2267
|
+
const variables = getConfig().variables ?? {};
|
|
2268
|
+
const next = new Set(Object.keys(variables));
|
|
2269
|
+
for (const name of applied) {
|
|
2270
|
+
if (!next.has(name)) removeThemeLayer(root, name, handle);
|
|
2271
|
+
}
|
|
2272
|
+
for (const [name, value] of Object.entries(variables)) setThemeLayer(root, name, handle, value);
|
|
2273
|
+
applied = next;
|
|
2274
|
+
});
|
|
2275
|
+
let released = false;
|
|
2276
|
+
return () => {
|
|
2277
|
+
if (released) return;
|
|
2278
|
+
released = true;
|
|
2279
|
+
stop();
|
|
2280
|
+
for (const name of applied) removeThemeLayer(root, name, handle);
|
|
2281
|
+
applied.clear();
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
return { config: getConfig, setTheme, resolveClass, applyTo };
|
|
2009
2285
|
}
|
|
2010
2286
|
function componentAdapter(config) {
|
|
2011
2287
|
const theme = createTheme({ prefix: config.prefix });
|
|
2288
|
+
const reprefix = (cls, prefix) => prefix !== config.prefix && cls.startsWith(`${config.prefix}-`) ? `${prefix}-${cls.slice(config.prefix.length + 1)}` : cls;
|
|
2012
2289
|
const components = {};
|
|
2013
2290
|
for (const [name, mapping] of Object.entries(config.components)) {
|
|
2014
2291
|
const factory = tagFactory(mapping.tag || "div");
|
|
2015
|
-
components[name] = (props = {}) => {
|
|
2292
|
+
components[name] = (props = {}, children) => {
|
|
2016
2293
|
const { variant, size, class: userClass, ...rest } = props;
|
|
2017
|
-
const
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2294
|
+
const themeClasses = () => {
|
|
2295
|
+
const current = theme.config();
|
|
2296
|
+
const overrides = current.classOverrides ?? {};
|
|
2297
|
+
const pick = (key, fallback) => Object.hasOwn(overrides, key) ? overrides[key] : reprefix(fallback, current.prefix);
|
|
2298
|
+
const classes = [pick(name, mapping.baseClass)];
|
|
2299
|
+
const variantClass = ownString(mapping.variants, variant);
|
|
2300
|
+
if (variant && variantClass) {
|
|
2301
|
+
classes.push(pick(`${name}-${variant}`, variantClass));
|
|
2302
|
+
}
|
|
2303
|
+
const sizeClass = ownString(mapping.sizes, size);
|
|
2304
|
+
if (size && sizeClass) {
|
|
2305
|
+
classes.push(pick(`${name}-${size}`, sizeClass));
|
|
2306
|
+
}
|
|
2307
|
+
return classes.filter(Boolean).join(" ");
|
|
2308
|
+
};
|
|
2309
|
+
const finalClass = () => {
|
|
2310
|
+
const base = themeClasses();
|
|
2311
|
+
const extra = typeof userClass === "function" ? userClass() : userClass;
|
|
2312
|
+
return typeof extra === "string" && extra ? `${base} ${extra}` : base;
|
|
2313
|
+
};
|
|
2035
2314
|
const mergedProps = {
|
|
2036
2315
|
...mapping.defaultProps,
|
|
2037
2316
|
...rest,
|
|
2038
2317
|
class: finalClass
|
|
2039
2318
|
};
|
|
2040
|
-
return factory(mergedProps);
|
|
2319
|
+
return children === void 0 ? factory(mergedProps) : factory(mergedProps, children);
|
|
2041
2320
|
};
|
|
2042
2321
|
}
|
|
2043
2322
|
return { name: config.name, components, theme };
|