sibujs 1.4.0 → 2.0.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 +105 -119
- package/dist/browser.cjs +288 -80
- package/dist/browser.d.cts +19 -9
- package/dist/browser.d.ts +19 -9
- package/dist/browser.js +6 -6
- package/dist/build.cjs +1019 -313
- package/dist/build.d.cts +1 -1
- package/dist/build.d.ts +1 -1
- package/dist/build.js +15 -13
- package/dist/cdn.global.js +17 -16
- package/dist/chunk-2RA7SHDA.js +65 -0
- package/dist/chunk-2UPRY23K.js +80 -0
- package/dist/chunk-3JHCYHWN.js +125 -0
- package/dist/{chunk-ZWKZCBO6.js → chunk-3LR7GLWQ.js} +154 -33
- package/dist/{chunk-3AIRKM3B.js → chunk-3NSGB5JN.js} +115 -34
- package/dist/{chunk-3ARAQO7B.js → chunk-52YJLLRO.js} +29 -6
- package/dist/chunk-54EDRCEF.js +93 -0
- package/dist/chunk-7JDB7I65.js +1327 -0
- package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
- package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
- package/dist/{chunk-WR5D4EGH.js → chunk-GTBNNBJ6.js} +14 -2
- package/dist/chunk-HB24TBAF.js +121 -0
- package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
- package/dist/{chunk-JAKHTMQU.js → chunk-JA6667UN.js} +206 -46
- package/dist/{chunk-77L6NL3X.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-F3FA4F32.js → chunk-KLRMB5ZS.js} +135 -79
- package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
- package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
- package/dist/{chunk-TSOKIX5Z.js → chunk-MIUAXB7K.js} +126 -74
- package/dist/{chunk-QWZG56ET.js → chunk-ND2664SF.js} +558 -190
- package/dist/{chunk-JCI5M6U6.js → chunk-O2MNQFLP.js} +261 -79
- package/dist/{chunk-EWFVA3TJ.js → chunk-R73P76YZ.js} +1 -1
- package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
- package/dist/chunk-UCS6AMJ7.js +79 -0
- package/dist/{chunk-ZD6OAMTH.js → chunk-VLPPXTYG.js} +90 -35
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- package/dist/{contracts-xo5ckdRP.d.cts → contracts-ey_Qh8ef.d.cts} +7 -8
- package/dist/{contracts-xo5ckdRP.d.ts → contracts-ey_Qh8ef.d.ts} +7 -8
- package/dist/{customElement-D2DJp_xn.d.cts → customElement-CPfIrbvg.d.cts} +18 -9
- package/dist/{customElement-D2DJp_xn.d.ts → customElement-CPfIrbvg.d.ts} +18 -9
- package/dist/data.cjs +452 -100
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +535 -247
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +34 -30
- package/dist/ecosystem.cjs +499 -143
- package/dist/ecosystem.d.cts +13 -11
- package/dist/ecosystem.d.ts +13 -11
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3639 -1629
- package/dist/extras.d.cts +11 -11
- package/dist/extras.d.ts +11 -11
- package/dist/extras.js +58 -45
- package/dist/index.cjs +1023 -313
- package/dist/index.d.cts +128 -55
- package/dist/index.d.ts +128 -55
- package/dist/index.js +28 -16
- package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
- package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
- package/dist/motion.cjs +90 -36
- package/dist/motion.d.cts +1 -1
- package/dist/motion.d.ts +1 -1
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +414 -81
- package/dist/patterns.d.cts +53 -20
- package/dist/patterns.d.ts +53 -20
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +364 -108
- package/dist/performance.d.cts +29 -17
- package/dist/performance.d.ts +29 -17
- package/dist/performance.js +13 -6
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +652 -271
- package/dist/plugins.d.cts +13 -6
- package/dist/plugins.d.ts +13 -6
- package/dist/plugins.js +116 -50
- package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
- package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
- package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
- package/dist/ssr.cjs +648 -219
- package/dist/ssr.d.cts +27 -7
- package/dist/ssr.d.ts +27 -7
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.ts} +9 -1
- package/dist/testing.cjs +252 -63
- package/dist/testing.d.cts +17 -4
- package/dist/testing.d.ts +17 -4
- package/dist/testing.js +100 -44
- package/dist/ui.cjs +576 -168
- package/dist/ui.d.cts +13 -16
- package/dist/ui.d.ts +13 -16
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +1001 -93
- package/dist/widgets.d.cts +104 -2
- package/dist/widgets.d.ts +104 -2
- package/dist/widgets.js +9 -7
- package/package.json +8 -2
- package/dist/chunk-32DY64NT.js +0 -282
- package/dist/chunk-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- package/dist/chunk-7BF6TK55.js +0 -1097
- package/dist/chunk-7TQKR4PP.js +0 -294
- package/dist/chunk-7V26P53V.js +0 -712
- package/dist/chunk-AZ3ISID5.js +0 -298
- package/dist/chunk-B7SWRFUT.js +0 -332
- package/dist/chunk-BGN5ZMP4.js +0 -26
- package/dist/chunk-BTU3TJDS.js +0 -365
- package/dist/chunk-BW3WT46K.js +0 -937
- package/dist/chunk-C6KFWOFV.js +0 -616
- package/dist/chunk-CHF5OHIA.js +0 -61
- package/dist/chunk-CHJ27IGK.js +0 -26
- package/dist/chunk-CMBFNA7L.js +0 -27
- package/dist/chunk-DAHRH4ON.js +0 -331
- package/dist/chunk-DKOHBI74.js +0 -924
- package/dist/chunk-DTCOOBMX.js +0 -725
- package/dist/chunk-EBGIRKQY.js +0 -616
- package/dist/chunk-EUZND3CB.js +0 -27
- package/dist/chunk-EVCZO745.js +0 -365
- package/dist/chunk-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-HGMJFBC7.js +0 -654
- package/dist/chunk-K5ZUMYVS.js +0 -89
- package/dist/chunk-KQPDEVVS.js +0 -398
- package/dist/chunk-L6JRBDNS.js +0 -60
- package/dist/chunk-LA6KQEDU.js +0 -712
- package/dist/chunk-MDVXJWFN.js +0 -304
- package/dist/chunk-MEZVEBPN.js +0 -2008
- package/dist/chunk-MK4ERFYL.js +0 -2249
- package/dist/chunk-MLKGABMK.js +0 -9
- package/dist/chunk-MQ5GOYPH.js +0 -2249
- package/dist/chunk-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NHUC2QWH.js +0 -282
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.js +0 -616
- package/dist/chunk-PTQJDMRT.js +0 -146
- package/dist/chunk-PZEGYCF5.js +0 -61
- package/dist/chunk-QBMDLBU2.js +0 -975
- package/dist/chunk-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TNQWPPE6.js +0 -37
- package/dist/chunk-UHNL42EF.js +0 -2730
- package/dist/chunk-UNXCEF6S.js +0 -21
- package/dist/chunk-V2XTI523.js +0 -347
- package/dist/chunk-VAU366PN.js +0 -2241
- package/dist/chunk-VMVDTCXB.js +0 -712
- package/dist/chunk-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- package/dist/chunk-WUHJISPP.js +0 -298
- package/dist/chunk-XYU6TZOW.js +0 -182
- package/dist/chunk-Y6GP4QGG.js +0 -276
- package/dist/chunk-YECR7UIA.js +0 -347
- package/dist/chunk-YUTWTI4B.js +0 -654
- package/dist/chunk-Z65KYU7I.js +0 -26
- package/dist/chunk-Z6POF5YC.js +0 -975
- package/dist/chunk-ZBJP6WFL.js +0 -482
- package/dist/contracts-DDrwxvJ-.d.cts +0 -245
- package/dist/contracts-DDrwxvJ-.d.ts +0 -245
- package/dist/contracts-DOrhwbke.d.cts +0 -245
- package/dist/contracts-DOrhwbke.d.ts +0 -245
- package/dist/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- package/dist/customElement-yz8uyk-0.d.cts +0 -308
- package/dist/customElement-yz8uyk-0.d.ts +0 -308
- package/dist/introspect-Cb0zgpi2.d.cts +0 -477
- package/dist/introspect-Y2xNXGSf.d.ts +0 -477
- package/dist/plugin-Bek4RhJY.d.cts +0 -43
- package/dist/plugin-Bek4RhJY.d.ts +0 -43
- package/dist/ssr-3RXHP5ES.js +0 -38
- package/dist/ssr-6GIMY5MX.js +0 -38
- package/dist/ssr-BA6sxxUd.d.cts +0 -135
- package/dist/ssr-BA6sxxUd.d.ts +0 -135
- package/dist/ssr-WKUPVSSK.js +0 -36
- package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
- package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
package/dist/browser.cjs
CHANGED
|
@@ -66,12 +66,12 @@ function isDev() {
|
|
|
66
66
|
var _isDev = isDev();
|
|
67
67
|
function devAssert(condition, message) {
|
|
68
68
|
if (_isDev && !condition) {
|
|
69
|
-
throw new Error(`[
|
|
69
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
function devWarn(message) {
|
|
73
73
|
if (_isDev) {
|
|
74
|
-
console.warn(`[
|
|
74
|
+
console.warn(`[SibuJS] ${message}`);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -81,11 +81,11 @@ var subscriberStack = new Array(32);
|
|
|
81
81
|
var stackCapacity = 32;
|
|
82
82
|
var stackTop = -1;
|
|
83
83
|
var currentSubscriber = null;
|
|
84
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
85
84
|
var SUBS = "__s";
|
|
86
85
|
var notifyDepth = 0;
|
|
87
86
|
var pendingQueue = [];
|
|
88
87
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
88
|
+
var propagateStack = [];
|
|
89
89
|
function safeInvoke(sub) {
|
|
90
90
|
try {
|
|
91
91
|
sub();
|
|
@@ -131,7 +131,6 @@ function recordDependency(signal2) {
|
|
|
131
131
|
let subs = signal2[SUBS];
|
|
132
132
|
if (!subs) {
|
|
133
133
|
subs = /* @__PURE__ */ new Set();
|
|
134
|
-
signalSubscribers.set(signal2, subs);
|
|
135
134
|
signal2[SUBS] = subs;
|
|
136
135
|
}
|
|
137
136
|
subs.add(currentSubscriber);
|
|
@@ -153,57 +152,71 @@ function queueSignalNotification(signal2) {
|
|
|
153
152
|
}
|
|
154
153
|
}
|
|
155
154
|
}
|
|
155
|
+
var maxDrainIterations = 1e5;
|
|
156
156
|
function drainNotificationQueue() {
|
|
157
157
|
if (notifyDepth > 0) return;
|
|
158
158
|
notifyDepth++;
|
|
159
159
|
try {
|
|
160
160
|
let i = 0;
|
|
161
161
|
while (i < pendingQueue.length) {
|
|
162
|
+
if (i >= maxDrainIterations) {
|
|
163
|
+
if (typeof console !== "undefined") {
|
|
164
|
+
console.error(
|
|
165
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
162
170
|
safeInvoke(pendingQueue[i]);
|
|
163
171
|
i++;
|
|
164
172
|
}
|
|
165
173
|
} finally {
|
|
166
|
-
pendingQueue.length = 0;
|
|
167
|
-
pendingSet.clear();
|
|
168
174
|
notifyDepth--;
|
|
175
|
+
if (notifyDepth === 0) {
|
|
176
|
+
pendingQueue.length = 0;
|
|
177
|
+
pendingSet.clear();
|
|
178
|
+
}
|
|
169
179
|
}
|
|
170
180
|
}
|
|
171
181
|
function propagateDirty(sub) {
|
|
172
182
|
sub();
|
|
173
|
-
|
|
174
|
-
|
|
183
|
+
const rootSig = sub._sig;
|
|
184
|
+
if (!rootSig) return;
|
|
185
|
+
const stack = propagateStack;
|
|
186
|
+
const baseLen = stack.length;
|
|
187
|
+
stack.push(rootSig);
|
|
188
|
+
while (stack.length > baseLen) {
|
|
189
|
+
const sig = stack.pop();
|
|
175
190
|
const first = sig.__f;
|
|
176
191
|
if (first) {
|
|
177
192
|
if (first._c) {
|
|
178
193
|
const nSig = first._sig;
|
|
179
|
-
nSig._d
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (!pendingSet.has(first)) {
|
|
194
|
+
if (!nSig._d) {
|
|
195
|
+
nSig._d = true;
|
|
196
|
+
stack.push(nSig);
|
|
197
|
+
}
|
|
198
|
+
} else if (!pendingSet.has(first)) {
|
|
184
199
|
pendingSet.add(first);
|
|
185
200
|
pendingQueue.push(first);
|
|
186
201
|
}
|
|
187
|
-
|
|
202
|
+
continue;
|
|
188
203
|
}
|
|
189
204
|
const subs = sig[SUBS];
|
|
190
|
-
if (!subs)
|
|
191
|
-
let nextSig;
|
|
205
|
+
if (!subs) continue;
|
|
192
206
|
for (const s of subs) {
|
|
193
207
|
if (s._c) {
|
|
194
|
-
s();
|
|
195
208
|
const nSig = s._sig;
|
|
196
|
-
if (nSig && !
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
209
|
+
if (nSig && !nSig._d) {
|
|
210
|
+
nSig._d = true;
|
|
211
|
+
stack.push(nSig);
|
|
212
|
+
} else if (!nSig) {
|
|
213
|
+
s();
|
|
200
214
|
}
|
|
201
215
|
} else if (!pendingSet.has(s)) {
|
|
202
216
|
pendingSet.add(s);
|
|
203
217
|
pendingQueue.push(s);
|
|
204
218
|
}
|
|
205
219
|
}
|
|
206
|
-
sig = nextSig;
|
|
207
220
|
}
|
|
208
221
|
}
|
|
209
222
|
function notifySubscribers(signal2) {
|
|
@@ -227,13 +240,23 @@ function notifySubscribers(signal2) {
|
|
|
227
240
|
}
|
|
228
241
|
let i = 0;
|
|
229
242
|
while (i < pendingQueue.length) {
|
|
243
|
+
if (i >= maxDrainIterations) {
|
|
244
|
+
if (typeof console !== "undefined") {
|
|
245
|
+
console.error(
|
|
246
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
230
251
|
safeInvoke(pendingQueue[i]);
|
|
231
252
|
i++;
|
|
232
253
|
}
|
|
233
254
|
} finally {
|
|
234
|
-
pendingQueue.length = 0;
|
|
235
|
-
pendingSet.clear();
|
|
236
255
|
notifyDepth--;
|
|
256
|
+
if (notifyDepth === 0) {
|
|
257
|
+
pendingQueue.length = 0;
|
|
258
|
+
pendingSet.clear();
|
|
259
|
+
}
|
|
237
260
|
}
|
|
238
261
|
return;
|
|
239
262
|
}
|
|
@@ -253,30 +276,48 @@ function notifySubscribers(signal2) {
|
|
|
253
276
|
notifyDepth++;
|
|
254
277
|
try {
|
|
255
278
|
let directCount = 0;
|
|
279
|
+
let hasComputedSub = false;
|
|
256
280
|
for (const sub of subs) {
|
|
281
|
+
if (sub._c) hasComputedSub = true;
|
|
257
282
|
pendingQueue[directCount++] = sub;
|
|
258
283
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
284
|
+
if (!hasComputedSub) {
|
|
285
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
286
|
+
safeInvoke(pendingQueue[i2]);
|
|
262
287
|
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
288
|
+
} else {
|
|
289
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
290
|
+
if (pendingQueue[i2]._c) {
|
|
291
|
+
propagateDirty(pendingQueue[i2]);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
295
|
+
const sub = pendingQueue[i2];
|
|
296
|
+
if (!sub._c && !pendingSet.has(sub)) {
|
|
297
|
+
pendingSet.add(sub);
|
|
298
|
+
safeInvoke(sub);
|
|
268
299
|
}
|
|
269
300
|
}
|
|
270
301
|
}
|
|
271
302
|
let i = directCount;
|
|
272
303
|
while (i < pendingQueue.length) {
|
|
304
|
+
if (i - directCount >= maxDrainIterations) {
|
|
305
|
+
if (typeof console !== "undefined") {
|
|
306
|
+
console.error(
|
|
307
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
273
312
|
safeInvoke(pendingQueue[i]);
|
|
274
313
|
i++;
|
|
275
314
|
}
|
|
276
315
|
} finally {
|
|
277
|
-
pendingQueue.length = 0;
|
|
278
|
-
pendingSet.clear();
|
|
279
316
|
notifyDepth--;
|
|
317
|
+
if (notifyDepth === 0) {
|
|
318
|
+
pendingQueue.length = 0;
|
|
319
|
+
pendingSet.clear();
|
|
320
|
+
}
|
|
280
321
|
}
|
|
281
322
|
}
|
|
282
323
|
function cleanup(subscriber) {
|
|
@@ -287,7 +328,9 @@ function cleanup(subscriber) {
|
|
|
287
328
|
if (subs) {
|
|
288
329
|
subs.delete(subscriber);
|
|
289
330
|
if (singleDep.__f === subscriber) {
|
|
290
|
-
singleDep.__f = void 0;
|
|
331
|
+
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
332
|
+
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
333
|
+
singleDep.__f = subs.values().next().value;
|
|
291
334
|
}
|
|
292
335
|
}
|
|
293
336
|
sub._dep = void 0;
|
|
@@ -300,7 +343,9 @@ function cleanup(subscriber) {
|
|
|
300
343
|
if (subs) {
|
|
301
344
|
subs.delete(subscriber);
|
|
302
345
|
if (signal2.__f === subscriber) {
|
|
303
|
-
signal2.__f = void 0;
|
|
346
|
+
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
347
|
+
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
348
|
+
signal2.__f = subs.values().next().value;
|
|
304
349
|
}
|
|
305
350
|
}
|
|
306
351
|
}
|
|
@@ -327,10 +372,13 @@ function enqueueBatchedSignal(signal2) {
|
|
|
327
372
|
return true;
|
|
328
373
|
}
|
|
329
374
|
function flushBatch() {
|
|
330
|
-
|
|
331
|
-
|
|
375
|
+
try {
|
|
376
|
+
for (const signal2 of pendingSignals) {
|
|
377
|
+
queueSignalNotification(signal2);
|
|
378
|
+
}
|
|
379
|
+
} finally {
|
|
380
|
+
pendingSignals.clear();
|
|
332
381
|
}
|
|
333
|
-
pendingSignals.clear();
|
|
334
382
|
drainNotificationQueue();
|
|
335
383
|
}
|
|
336
384
|
|
|
@@ -392,9 +440,28 @@ function media(query) {
|
|
|
392
440
|
}
|
|
393
441
|
|
|
394
442
|
// src/core/ssr-context.ts
|
|
395
|
-
var
|
|
443
|
+
var als = null;
|
|
444
|
+
try {
|
|
445
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
446
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
447
|
+
if (req) {
|
|
448
|
+
const mod = req("node:async_hooks");
|
|
449
|
+
als = new mod.AsyncLocalStorage();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
} catch {
|
|
453
|
+
als = null;
|
|
454
|
+
}
|
|
455
|
+
var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
456
|
+
function getSSRStore() {
|
|
457
|
+
if (als) {
|
|
458
|
+
const s = als.getStore();
|
|
459
|
+
if (s) return s;
|
|
460
|
+
}
|
|
461
|
+
return fallbackStore;
|
|
462
|
+
}
|
|
396
463
|
function isSSR() {
|
|
397
|
-
return
|
|
464
|
+
return getSSRStore().ssr;
|
|
398
465
|
}
|
|
399
466
|
|
|
400
467
|
// src/core/signals/effect.ts
|
|
@@ -404,26 +471,86 @@ function effect(effectFn, options) {
|
|
|
404
471
|
if (isSSR()) return () => {
|
|
405
472
|
};
|
|
406
473
|
const onError = options?.onError;
|
|
474
|
+
let userCleanups = [];
|
|
475
|
+
const onCleanup = (fn) => {
|
|
476
|
+
userCleanups.push(fn);
|
|
477
|
+
};
|
|
478
|
+
const runUserCleanups = () => {
|
|
479
|
+
if (userCleanups.length === 0) return;
|
|
480
|
+
const list = userCleanups;
|
|
481
|
+
userCleanups = [];
|
|
482
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
483
|
+
try {
|
|
484
|
+
list[i]();
|
|
485
|
+
} catch (err) {
|
|
486
|
+
if (typeof console !== "undefined") {
|
|
487
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
const invokeBody = () => effectFn(onCleanup);
|
|
407
493
|
const wrappedFn = onError ? () => {
|
|
408
494
|
try {
|
|
409
|
-
|
|
495
|
+
invokeBody();
|
|
410
496
|
} catch (err) {
|
|
411
497
|
onError(err);
|
|
412
498
|
}
|
|
413
|
-
} :
|
|
499
|
+
} : invokeBody;
|
|
414
500
|
let cleanupHandle = () => {
|
|
415
501
|
};
|
|
502
|
+
let running = false;
|
|
416
503
|
const subscriber = () => {
|
|
417
|
-
|
|
418
|
-
|
|
504
|
+
if (running) {
|
|
505
|
+
if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
506
|
+
console.warn(
|
|
507
|
+
"[SibuJS] effect re-entered itself while running \u2014 the triggering update will be ignored. Wrap mutual writes in `batch()` or split the effect to avoid this."
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
running = true;
|
|
513
|
+
try {
|
|
514
|
+
runUserCleanups();
|
|
515
|
+
cleanupHandle();
|
|
516
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
517
|
+
} finally {
|
|
518
|
+
running = false;
|
|
519
|
+
}
|
|
419
520
|
};
|
|
420
|
-
|
|
521
|
+
running = true;
|
|
522
|
+
try {
|
|
523
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
524
|
+
} finally {
|
|
525
|
+
running = false;
|
|
526
|
+
}
|
|
421
527
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
422
528
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
529
|
+
let disposed = false;
|
|
423
530
|
return () => {
|
|
531
|
+
if (disposed) return;
|
|
532
|
+
disposed = true;
|
|
424
533
|
const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
425
|
-
if (h)
|
|
426
|
-
|
|
534
|
+
if (h) {
|
|
535
|
+
try {
|
|
536
|
+
h.emit("effect:destroy", { effectFn });
|
|
537
|
+
} catch {
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
runUserCleanups();
|
|
542
|
+
} catch (err) {
|
|
543
|
+
if (typeof console !== "undefined") {
|
|
544
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
cleanupHandle();
|
|
549
|
+
} catch (err) {
|
|
550
|
+
if (typeof console !== "undefined") {
|
|
551
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
427
554
|
};
|
|
428
555
|
}
|
|
429
556
|
|
|
@@ -474,6 +601,8 @@ function scroll(target) {
|
|
|
474
601
|
const [y, setY] = signal(0);
|
|
475
602
|
const [isScrolling, setIsScrolling] = signal(false);
|
|
476
603
|
let scrollTimer = null;
|
|
604
|
+
let currentTarget = null;
|
|
605
|
+
let effectCleanup = null;
|
|
477
606
|
if (typeof window === "undefined") {
|
|
478
607
|
return { x, y, isScrolling, dispose: () => {
|
|
479
608
|
} };
|
|
@@ -496,11 +625,26 @@ function scroll(target) {
|
|
|
496
625
|
scrollTimer = null;
|
|
497
626
|
}, 150);
|
|
498
627
|
};
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
628
|
+
function attachListener(eventTarget) {
|
|
629
|
+
if (currentTarget === eventTarget) return;
|
|
630
|
+
if (currentTarget) currentTarget.removeEventListener("scroll", handler);
|
|
631
|
+
currentTarget = eventTarget;
|
|
632
|
+
currentTarget.addEventListener("scroll", handler, { passive: true });
|
|
633
|
+
}
|
|
634
|
+
if (target) {
|
|
635
|
+
effectCleanup = effect(() => {
|
|
636
|
+
const el = target();
|
|
637
|
+
attachListener(el || window);
|
|
638
|
+
});
|
|
639
|
+
} else {
|
|
640
|
+
attachListener(window);
|
|
641
|
+
}
|
|
502
642
|
function dispose() {
|
|
503
|
-
|
|
643
|
+
effectCleanup?.();
|
|
644
|
+
if (currentTarget) {
|
|
645
|
+
currentTarget.removeEventListener("scroll", handler);
|
|
646
|
+
currentTarget = null;
|
|
647
|
+
}
|
|
504
648
|
if (scrollTimer !== null) {
|
|
505
649
|
clearTimeout(scrollTimer);
|
|
506
650
|
scrollTimer = null;
|
|
@@ -784,7 +928,10 @@ function dropZone(element, options) {
|
|
|
784
928
|
const raw = e.dataTransfer.getData("application/json");
|
|
785
929
|
if (raw) {
|
|
786
930
|
try {
|
|
787
|
-
transferData = JSON.parse(
|
|
931
|
+
transferData = JSON.parse(
|
|
932
|
+
raw,
|
|
933
|
+
(k, v) => k === "__proto__" || k === "constructor" || k === "prototype" ? void 0 : v
|
|
934
|
+
);
|
|
788
935
|
} catch {
|
|
789
936
|
transferData = raw;
|
|
790
937
|
}
|
|
@@ -1019,31 +1166,44 @@ function urlState() {
|
|
|
1019
1166
|
}
|
|
1020
1167
|
};
|
|
1021
1168
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
const
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1169
|
+
let lastSearch = window.location.search;
|
|
1170
|
+
let lastHash = window.location.hash;
|
|
1171
|
+
const [params, setParamsSignal] = signal(new URLSearchParams(lastSearch));
|
|
1172
|
+
const [hash, setHashSignal] = signal(lastHash);
|
|
1173
|
+
function syncFromLocation() {
|
|
1174
|
+
const currentSearch = window.location.search;
|
|
1175
|
+
const currentHash = window.location.hash;
|
|
1176
|
+
if (currentSearch !== lastSearch) {
|
|
1177
|
+
lastSearch = currentSearch;
|
|
1178
|
+
setParamsSignal(new URLSearchParams(currentSearch));
|
|
1179
|
+
}
|
|
1180
|
+
if (currentHash !== lastHash) {
|
|
1181
|
+
lastHash = currentHash;
|
|
1182
|
+
setHashSignal(currentHash);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
window.addEventListener("popstate", syncFromLocation);
|
|
1186
|
+
window.addEventListener("hashchange", syncFromLocation);
|
|
1030
1187
|
function setParams(next, opts = {}) {
|
|
1031
1188
|
const p = next instanceof URLSearchParams ? next : new URLSearchParams(next);
|
|
1032
1189
|
const query = p.toString();
|
|
1033
1190
|
const newUrl = `${window.location.pathname}${query ? `?${query}` : ""}${window.location.hash}`;
|
|
1034
1191
|
if (opts.replace) window.history.replaceState(null, "", newUrl);
|
|
1035
1192
|
else window.history.pushState(null, "", newUrl);
|
|
1193
|
+
lastSearch = window.location.search;
|
|
1036
1194
|
setParamsSignal(new URLSearchParams(p));
|
|
1037
1195
|
}
|
|
1038
1196
|
function setHash(next, opts = {}) {
|
|
1039
|
-
const normalized = next.startsWith("#") ? next :
|
|
1197
|
+
const normalized = next && next !== "#" ? next.startsWith("#") ? next : `#${next}` : "";
|
|
1040
1198
|
const newUrl = `${window.location.pathname}${window.location.search}${normalized}`;
|
|
1041
1199
|
if (opts.replace) window.history.replaceState(null, "", newUrl);
|
|
1042
1200
|
else window.history.pushState(null, "", newUrl);
|
|
1201
|
+
lastHash = normalized;
|
|
1043
1202
|
setHashSignal(normalized);
|
|
1044
1203
|
}
|
|
1045
1204
|
function dispose() {
|
|
1046
|
-
window.removeEventListener("popstate",
|
|
1205
|
+
window.removeEventListener("popstate", syncFromLocation);
|
|
1206
|
+
window.removeEventListener("hashchange", syncFromLocation);
|
|
1047
1207
|
}
|
|
1048
1208
|
return { params, hash, setParams, setHash, dispose };
|
|
1049
1209
|
}
|
|
@@ -1151,13 +1311,21 @@ function wakeLock() {
|
|
|
1151
1311
|
}
|
|
1152
1312
|
const onVisibility = () => {
|
|
1153
1313
|
if (sentinel?.released && !document.hidden) {
|
|
1154
|
-
|
|
1314
|
+
request().catch((err) => {
|
|
1315
|
+
if (typeof console !== "undefined") {
|
|
1316
|
+
console.warn("[SibuJS wakeLock] re-acquire failed:", err);
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1155
1319
|
}
|
|
1156
1320
|
};
|
|
1157
1321
|
document.addEventListener("visibilitychange", onVisibility);
|
|
1158
1322
|
function dispose() {
|
|
1159
1323
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
1160
|
-
|
|
1324
|
+
release().catch((err) => {
|
|
1325
|
+
if (typeof console !== "undefined") {
|
|
1326
|
+
console.warn("[SibuJS wakeLock] release failed:", err);
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1161
1329
|
}
|
|
1162
1330
|
return { active, request, release, dispose };
|
|
1163
1331
|
}
|
|
@@ -1353,11 +1521,21 @@ function speech() {
|
|
|
1353
1521
|
};
|
|
1354
1522
|
}
|
|
1355
1523
|
const synth = window.speechSynthesis;
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1524
|
+
let interval = null;
|
|
1525
|
+
function startPolling() {
|
|
1526
|
+
if (interval !== null) return;
|
|
1527
|
+
interval = setInterval(() => {
|
|
1528
|
+
setSpeaking(synth.speaking);
|
|
1529
|
+
setPaused(synth.paused);
|
|
1530
|
+
if (!synth.speaking && !synth.paused) {
|
|
1531
|
+
clearInterval(interval);
|
|
1532
|
+
interval = null;
|
|
1533
|
+
}
|
|
1534
|
+
}, 200);
|
|
1535
|
+
}
|
|
1536
|
+
let disposed = false;
|
|
1360
1537
|
function speak(text, options = {}) {
|
|
1538
|
+
if (disposed) return;
|
|
1361
1539
|
const u = new SpeechSynthesisUtterance(text);
|
|
1362
1540
|
if (options.lang) u.lang = options.lang;
|
|
1363
1541
|
if (options.rate != null) u.rate = options.rate;
|
|
@@ -1368,19 +1546,41 @@ function speech() {
|
|
|
1368
1546
|
const match = voices.find((v) => v.name === options.voice);
|
|
1369
1547
|
if (match) u.voice = match;
|
|
1370
1548
|
}
|
|
1371
|
-
u.addEventListener(
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1549
|
+
u.addEventListener(
|
|
1550
|
+
"start",
|
|
1551
|
+
() => {
|
|
1552
|
+
if (!disposed) setSpeaking(true);
|
|
1553
|
+
},
|
|
1554
|
+
{ once: true }
|
|
1555
|
+
);
|
|
1556
|
+
u.addEventListener(
|
|
1557
|
+
"end",
|
|
1558
|
+
() => {
|
|
1559
|
+
if (disposed) return;
|
|
1560
|
+
setSpeaking(false);
|
|
1561
|
+
setPaused(false);
|
|
1562
|
+
},
|
|
1563
|
+
{ once: true }
|
|
1564
|
+
);
|
|
1565
|
+
u.addEventListener(
|
|
1566
|
+
"error",
|
|
1567
|
+
() => {
|
|
1568
|
+
if (disposed) return;
|
|
1569
|
+
setSpeaking(false);
|
|
1570
|
+
setPaused(false);
|
|
1571
|
+
},
|
|
1572
|
+
{ once: true }
|
|
1573
|
+
);
|
|
1380
1574
|
synth.speak(u);
|
|
1575
|
+
setSpeaking(true);
|
|
1576
|
+
startPolling();
|
|
1381
1577
|
}
|
|
1382
1578
|
function dispose() {
|
|
1383
|
-
|
|
1579
|
+
disposed = true;
|
|
1580
|
+
if (interval !== null) {
|
|
1581
|
+
clearInterval(interval);
|
|
1582
|
+
interval = null;
|
|
1583
|
+
}
|
|
1384
1584
|
synth.cancel();
|
|
1385
1585
|
}
|
|
1386
1586
|
return {
|
|
@@ -1609,13 +1809,21 @@ function imageLoader(src) {
|
|
|
1609
1809
|
};
|
|
1610
1810
|
img.src = url;
|
|
1611
1811
|
}
|
|
1812
|
+
let srcEffectTeardown = null;
|
|
1612
1813
|
if (typeof src === "function") {
|
|
1613
|
-
|
|
1814
|
+
srcEffectTeardown = effect(() => {
|
|
1815
|
+
const url = src();
|
|
1816
|
+
start(url);
|
|
1817
|
+
});
|
|
1614
1818
|
} else {
|
|
1615
1819
|
start(src);
|
|
1616
1820
|
}
|
|
1617
1821
|
function dispose() {
|
|
1618
1822
|
disposed = true;
|
|
1823
|
+
if (srcEffectTeardown) {
|
|
1824
|
+
srcEffectTeardown();
|
|
1825
|
+
srcEffectTeardown = null;
|
|
1826
|
+
}
|
|
1619
1827
|
if (current) {
|
|
1620
1828
|
current.onload = null;
|
|
1621
1829
|
current.onerror = null;
|
package/dist/browser.d.cts
CHANGED
|
@@ -31,6 +31,9 @@ declare function resize(target: ElementTarget$1): {
|
|
|
31
31
|
* Returns reactive x/y scroll positions and an isScrolling indicator
|
|
32
32
|
* that resets after 150ms of inactivity.
|
|
33
33
|
*
|
|
34
|
+
* If a reactive target getter is provided, the listener re-attaches
|
|
35
|
+
* whenever the target element changes (same pattern as resize/dragDrop).
|
|
36
|
+
*
|
|
34
37
|
* @param target Optional reactive getter for the scroll target element.
|
|
35
38
|
* If omitted or returns null, tracks window scroll.
|
|
36
39
|
* @returns Object with reactive x, y, isScrolling getters and a dispose function
|
|
@@ -336,7 +339,9 @@ declare function windowSize(): {
|
|
|
336
339
|
* to sync a handful of UI state bits with the URL (filters, tabs, modals)
|
|
337
340
|
* without a full router setup.
|
|
338
341
|
*
|
|
339
|
-
* Listens to `popstate`
|
|
342
|
+
* Listens to both `popstate` (back/forward) and `hashchange` (anchor clicks,
|
|
343
|
+
* direct `location.hash` assignments) so the signals stay in sync regardless
|
|
344
|
+
* of how the URL was changed.
|
|
340
345
|
*
|
|
341
346
|
* @example
|
|
342
347
|
* ```ts
|
|
@@ -365,6 +370,11 @@ declare function urlState(): {
|
|
|
365
370
|
};
|
|
366
371
|
|
|
367
372
|
/**
|
|
373
|
+
* Note on trust model: `BroadcastChannel` only delivers messages between
|
|
374
|
+
* same-origin browsing contexts (tabs, iframes, workers). We therefore treat
|
|
375
|
+
* incoming payloads as same-origin-trusted and pass them through unmodified.
|
|
376
|
+
* Do not use this transport for cross-origin messaging.
|
|
377
|
+
*
|
|
368
378
|
* broadcast wraps the BroadcastChannel API as a reactive signal.
|
|
369
379
|
* Unlike the `storage` event (which only fires for localStorage writes and
|
|
370
380
|
* sends only the serialized value), a `BroadcastChannel` can send arbitrary
|
|
@@ -406,10 +416,10 @@ declare function broadcast<T = unknown>(channelName: string): {
|
|
|
406
416
|
* @example
|
|
407
417
|
* ```ts
|
|
408
418
|
* const fs = fullscreen();
|
|
409
|
-
* button(
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
419
|
+
* button(
|
|
420
|
+
* { on: { click: () => fs.toggle(videoEl) } },
|
|
421
|
+
* () => (fs.isFullscreen() ? "Exit fullscreen" : "Enter fullscreen"),
|
|
422
|
+
* );
|
|
413
423
|
* ```
|
|
414
424
|
*/
|
|
415
425
|
declare function fullscreen(): {
|
|
@@ -594,10 +604,10 @@ interface SpeakOptions {
|
|
|
594
604
|
* @example
|
|
595
605
|
* ```ts
|
|
596
606
|
* const tts = speech();
|
|
597
|
-
* button(
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
607
|
+
* button(
|
|
608
|
+
* { on: { click: () => tts.speak("Hello, world!", { rate: 1.1 }) } },
|
|
609
|
+
* "Read it to me",
|
|
610
|
+
* );
|
|
601
611
|
* ```
|
|
602
612
|
*/
|
|
603
613
|
declare function speech(): {
|