sibujs 4.5.0 → 4.7.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 +1 -1
- package/dist/browser.cjs +326 -133
- package/dist/browser.d.cts +46 -14
- package/dist/browser.d.ts +46 -14
- package/dist/browser.js +8 -6
- package/dist/build.cjs +2094 -1033
- package/dist/build.d.cts +133 -44
- package/dist/build.d.ts +133 -44
- package/dist/build.js +1372 -574
- package/dist/cdn.dev.global.js +10 -10
- package/dist/cdn.full.dev.global.js +11 -11
- package/dist/cdn.full.global.js +10 -10
- package/dist/cdn.global.js +10 -10
- package/dist/{chunk-2DCGACUU.js → chunk-2BPG2XDA.js} +251 -66
- package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
- package/dist/{chunk-4PMLNECI.js → chunk-3QWBSL5R.js} +98 -29
- package/dist/{chunk-KKLW7YWL.js → chunk-4AWA2PVD.js} +275 -144
- package/dist/chunk-5HZXGZ6T.js +24 -0
- package/dist/{chunk-PCT43HW3.js → chunk-7LUJQAOJ.js} +1 -1
- package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
- package/dist/chunk-BC2SECJD.js +44 -0
- package/dist/{chunk-TBYTO6BS.js → chunk-BSY63EM6.js} +136 -80
- package/dist/{chunk-FTIR4QW2.js → chunk-DKXRACVN.js} +6 -8
- package/dist/{chunk-ONOHFDLG.js → chunk-FNJXNGYZ.js} +3 -3
- package/dist/{chunk-XZZOBQAY.js → chunk-FQRUXCEE.js} +6 -5
- package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
- package/dist/chunk-J6FW5TV6.js +233 -0
- package/dist/{chunk-UGRX3S57.js → chunk-JWKYU5GV.js} +22 -4
- package/dist/chunk-NYNYSPK7.js +318 -0
- package/dist/{chunk-RBTPLM32.js → chunk-RUSSKG6G.js} +13 -12
- package/dist/{chunk-7LN645I6.js → chunk-SLM3IA34.js} +3 -3
- package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
- package/dist/{chunk-B3WHI2QA.js → chunk-UNWRJRKC.js} +55 -31
- package/dist/{chunk-KEISJXBU.js → chunk-UOL2ECCS.js} +44 -17
- package/dist/{chunk-RJE2BNI4.js → chunk-VZSG24LS.js} +108 -45
- package/dist/{chunk-RIXRAYIU.js → chunk-WEQ3DMVL.js} +10 -4
- package/dist/{chunk-3JZ4L5TJ.js → chunk-WOLJZUFQ.js} +354 -90
- package/dist/{chunk-S373NSMK.js → chunk-XYV3EDB7.js} +283 -123
- package/dist/{chunk-VZKNK2V7.js → chunk-XZR4PXRE.js} +296 -38
- package/dist/{chunk-GW3SCCZG.js → chunk-Z3OHK6QT.js} +153 -110
- package/dist/{chunk-OMJJM3KM.js → chunk-ZVL7TY4K.js} +287 -130
- package/dist/{contracts-DBdg9J_a.d.ts → contracts-CLqzJnOV.d.ts} +36 -17
- package/dist/{contracts-DBdg9J_a.d.cts → contracts-CTOJXu-x.d.cts} +36 -17
- package/dist/{customElement-OB9CIsc5.d.cts → customElement-MmInOW1U.d.cts} +21 -0
- package/dist/{customElement-OB9CIsc5.d.ts → customElement-MmInOW1U.d.ts} +21 -0
- package/dist/data.cjs +410 -155
- package/dist/data.d.cts +166 -12
- package/dist/data.d.ts +166 -12
- package/dist/data.js +12 -9
- package/dist/devtools.cjs +98 -61
- package/dist/devtools.js +7 -8
- package/dist/dispose-GEIG2KOF.js +28 -0
- package/dist/ecosystem.cjs +372 -126
- package/dist/ecosystem.d.cts +20 -3
- package/dist/ecosystem.d.ts +20 -3
- package/dist/ecosystem.js +12 -12
- package/dist/extras.cjs +2366 -909
- package/dist/extras.d.cts +11 -9
- package/dist/extras.d.ts +11 -9
- package/dist/extras.js +39 -28
- package/dist/index.cjs +421 -158
- package/dist/index.d.cts +213 -171
- package/dist/index.d.ts +213 -171
- package/dist/index.js +24 -27
- package/dist/motion.cjs +118 -44
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +344 -53
- package/dist/patterns.d.cts +28 -9
- package/dist/patterns.d.ts +28 -9
- package/dist/patterns.js +8 -8
- package/dist/performance.cjs +325 -220
- 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 +664 -233
- package/dist/plugins.d.cts +127 -14
- package/dist/plugins.d.ts +127 -14
- package/dist/plugins.js +96 -42
- 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 +229 -84
- 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-8qL9LCIx.d.cts +156 -0
- package/dist/tagFactory-BL2fymez.d.ts +156 -0
- package/dist/testing.cjs +2503 -2191
- package/dist/testing.d.cts +56 -5
- package/dist/testing.d.ts +56 -5
- package/dist/testing.js +580 -307
- package/dist/types-CJFViL6Q.d.cts +26 -0
- package/dist/types-CJFViL6Q.d.ts +26 -0
- package/dist/ui.cjs +732 -329
- package/dist/ui.d.cts +41 -7
- package/dist/ui.d.ts +41 -7
- package/dist/ui.js +151 -56
- package/dist/widgets.cjs +267 -291
- package/dist/widgets.js +9 -10
- package/package.json +4 -2
- package/dist/chunk-2WLZ6757.js +0 -149
- package/dist/chunk-CCSJMTRN.js +0 -15
- package/dist/chunk-QKRPLZ2V.js +0 -108
- package/dist/chunk-VUF4ALSW.js +0 -60
- 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-DVoDpHye.d.cts +0 -215
- package/dist/tagFactory-DVoDpHye.d.ts +0 -215
|
@@ -4,16 +4,19 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
acquireTitle
|
|
6
6
|
} from "./chunk-52XFPGSN.js";
|
|
7
|
+
import {
|
|
8
|
+
globalSingleton
|
|
9
|
+
} from "./chunk-7ZHH77QA.js";
|
|
7
10
|
import {
|
|
8
11
|
effect
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WEQ3DMVL.js";
|
|
10
13
|
import {
|
|
11
14
|
batch,
|
|
12
15
|
signal
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-FQRUXCEE.js";
|
|
14
17
|
import {
|
|
15
18
|
reportError
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NYNYSPK7.js";
|
|
17
20
|
|
|
18
21
|
// src/browser/media.ts
|
|
19
22
|
function media(query) {
|
|
@@ -306,13 +309,15 @@ function clipboard() {
|
|
|
306
309
|
const [copied, setCopied] = signal(false);
|
|
307
310
|
let copiedTimer = null;
|
|
308
311
|
let disposed = false;
|
|
312
|
+
let generation = 0;
|
|
309
313
|
async function copy(value) {
|
|
310
314
|
if (disposed) return;
|
|
311
315
|
if (typeof navigator === "undefined" || !navigator.clipboard) {
|
|
312
316
|
return;
|
|
313
317
|
}
|
|
318
|
+
const mine = ++generation;
|
|
314
319
|
await navigator.clipboard.writeText(value);
|
|
315
|
-
if (disposed) return;
|
|
320
|
+
if (disposed || mine !== generation) return;
|
|
316
321
|
setText(value);
|
|
317
322
|
setCopied(true);
|
|
318
323
|
if (copiedTimer !== null) clearTimeout(copiedTimer);
|
|
@@ -324,6 +329,7 @@ function clipboard() {
|
|
|
324
329
|
}
|
|
325
330
|
function dispose() {
|
|
326
331
|
disposed = true;
|
|
332
|
+
generation++;
|
|
327
333
|
if (copiedTimer !== null) {
|
|
328
334
|
clearTimeout(copiedTimer);
|
|
329
335
|
copiedTimer = null;
|
|
@@ -345,15 +351,26 @@ function draggable(element, data) {
|
|
|
345
351
|
let currentEl = null;
|
|
346
352
|
let onDragStart = null;
|
|
347
353
|
let onDragEnd = null;
|
|
354
|
+
let prevDraggableAttr = null;
|
|
355
|
+
function detach() {
|
|
356
|
+
if (!currentEl) return;
|
|
357
|
+
if (onDragStart) currentEl.removeEventListener("dragstart", onDragStart);
|
|
358
|
+
if (onDragEnd) currentEl.removeEventListener("dragend", onDragEnd);
|
|
359
|
+
if (prevDraggableAttr === null) currentEl.removeAttribute("draggable");
|
|
360
|
+
else currentEl.setAttribute("draggable", prevDraggableAttr);
|
|
361
|
+
currentEl = null;
|
|
362
|
+
onDragStart = null;
|
|
363
|
+
onDragEnd = null;
|
|
364
|
+
setIsDragging(false);
|
|
365
|
+
}
|
|
348
366
|
const getter = resolveTarget2(element);
|
|
349
367
|
const cleanup = effect(() => {
|
|
350
|
-
if (currentEl && onDragStart && onDragEnd) {
|
|
351
|
-
currentEl.removeEventListener("dragstart", onDragStart);
|
|
352
|
-
currentEl.removeEventListener("dragend", onDragEnd);
|
|
353
|
-
}
|
|
354
368
|
const el = getter();
|
|
355
|
-
currentEl
|
|
369
|
+
if (el === currentEl) return;
|
|
370
|
+
detach();
|
|
356
371
|
if (!el) return;
|
|
372
|
+
currentEl = el;
|
|
373
|
+
prevDraggableAttr = el.getAttribute("draggable");
|
|
357
374
|
el.draggable = true;
|
|
358
375
|
onDragStart = (e) => {
|
|
359
376
|
setIsDragging(true);
|
|
@@ -367,16 +384,16 @@ function draggable(element, data) {
|
|
|
367
384
|
el.addEventListener("dragstart", onDragStart);
|
|
368
385
|
el.addEventListener("dragend", onDragEnd);
|
|
369
386
|
});
|
|
387
|
+
let disposed = false;
|
|
370
388
|
function dispose() {
|
|
389
|
+
if (disposed) return;
|
|
390
|
+
disposed = true;
|
|
371
391
|
cleanup();
|
|
372
|
-
|
|
373
|
-
currentEl.removeEventListener("dragstart", onDragStart);
|
|
374
|
-
currentEl.removeEventListener("dragend", onDragEnd);
|
|
375
|
-
currentEl = null;
|
|
376
|
-
}
|
|
392
|
+
detach();
|
|
377
393
|
}
|
|
378
394
|
return { isDragging, dispose };
|
|
379
395
|
}
|
|
396
|
+
var DROP_ZONE_EXIT_GRACE_MS = 600;
|
|
380
397
|
function dropZone(element, options) {
|
|
381
398
|
const [isOver, setIsOver] = signal(false);
|
|
382
399
|
if (typeof window === "undefined") {
|
|
@@ -388,30 +405,66 @@ function dropZone(element, options) {
|
|
|
388
405
|
let onDragEnter = null;
|
|
389
406
|
let onDragLeave = null;
|
|
390
407
|
let onDrop = null;
|
|
391
|
-
|
|
392
|
-
|
|
408
|
+
let depth = 0;
|
|
409
|
+
let exitTimer = null;
|
|
410
|
+
function cancelPendingExit() {
|
|
411
|
+
if (exitTimer !== null) {
|
|
412
|
+
clearTimeout(exitTimer);
|
|
413
|
+
exitTimer = null;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function resetOver() {
|
|
417
|
+
cancelPendingExit();
|
|
418
|
+
depth = 0;
|
|
419
|
+
setIsOver(false);
|
|
420
|
+
}
|
|
421
|
+
function detach() {
|
|
393
422
|
if (currentEl && onDragOver && onDragEnter && onDragLeave && onDrop) {
|
|
394
423
|
currentEl.removeEventListener("dragover", onDragOver);
|
|
395
424
|
currentEl.removeEventListener("dragenter", onDragEnter);
|
|
396
425
|
currentEl.removeEventListener("dragleave", onDragLeave);
|
|
397
426
|
currentEl.removeEventListener("drop", onDrop);
|
|
398
427
|
}
|
|
428
|
+
currentEl = null;
|
|
429
|
+
resetOver();
|
|
430
|
+
}
|
|
431
|
+
const getter = resolveTarget2(element);
|
|
432
|
+
const cleanup = effect(() => {
|
|
399
433
|
const el = getter();
|
|
400
|
-
currentEl
|
|
434
|
+
if (el === currentEl) return;
|
|
435
|
+
detach();
|
|
401
436
|
if (!el) return;
|
|
437
|
+
currentEl = el;
|
|
402
438
|
onDragOver = (e) => {
|
|
403
439
|
e.preventDefault();
|
|
440
|
+
cancelPendingExit();
|
|
404
441
|
};
|
|
405
442
|
onDragEnter = (e) => {
|
|
406
443
|
e.preventDefault();
|
|
444
|
+
cancelPendingExit();
|
|
445
|
+
depth++;
|
|
407
446
|
setIsOver(true);
|
|
408
447
|
};
|
|
409
|
-
onDragLeave = () => {
|
|
410
|
-
|
|
448
|
+
onDragLeave = (e) => {
|
|
449
|
+
depth = Math.max(0, depth - 1);
|
|
450
|
+
if (depth === 0) {
|
|
451
|
+
resetOver();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
const to = e.relatedTarget;
|
|
455
|
+
if (to != null && typeof to.nodeType === "number") {
|
|
456
|
+
if (!el.contains(to)) resetOver();
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
cancelPendingExit();
|
|
460
|
+
exitTimer = setTimeout(() => {
|
|
461
|
+
exitTimer = null;
|
|
462
|
+
resetOver();
|
|
463
|
+
}, DROP_ZONE_EXIT_GRACE_MS);
|
|
411
464
|
};
|
|
412
465
|
onDrop = (e) => {
|
|
413
466
|
e.preventDefault();
|
|
414
|
-
|
|
467
|
+
resetOver();
|
|
415
468
|
let transferData = null;
|
|
416
469
|
if (e.dataTransfer) {
|
|
417
470
|
const raw = e.dataTransfer.getData("application/json");
|
|
@@ -432,13 +485,7 @@ function dropZone(element, options) {
|
|
|
432
485
|
});
|
|
433
486
|
function dispose() {
|
|
434
487
|
cleanup();
|
|
435
|
-
|
|
436
|
-
currentEl.removeEventListener("dragover", onDragOver);
|
|
437
|
-
currentEl.removeEventListener("dragenter", onDragEnter);
|
|
438
|
-
currentEl.removeEventListener("dragleave", onDragLeave);
|
|
439
|
-
currentEl.removeEventListener("drop", onDrop);
|
|
440
|
-
currentEl = null;
|
|
441
|
-
}
|
|
488
|
+
detach();
|
|
442
489
|
}
|
|
443
490
|
return { isOver, dispose };
|
|
444
491
|
}
|
|
@@ -493,9 +540,9 @@ function formatNumber(value, options) {
|
|
|
493
540
|
function formatCurrency(value, currency, options) {
|
|
494
541
|
const { locale, ...formatOptions } = options ?? {};
|
|
495
542
|
return new Intl.NumberFormat(locale, {
|
|
543
|
+
...formatOptions,
|
|
496
544
|
style: "currency",
|
|
497
|
-
currency
|
|
498
|
-
...formatOptions
|
|
545
|
+
currency
|
|
499
546
|
}).format(value);
|
|
500
547
|
}
|
|
501
548
|
|
|
@@ -581,18 +628,36 @@ function swipe(target, options = {}) {
|
|
|
581
628
|
}
|
|
582
629
|
let startX = 0;
|
|
583
630
|
let startY = 0;
|
|
584
|
-
let
|
|
631
|
+
let trackedId = null;
|
|
632
|
+
const idOf = (t) => t.identifier ?? 0;
|
|
633
|
+
const findTracked = (list) => {
|
|
634
|
+
if (!list) return null;
|
|
635
|
+
for (let i = 0; i < list.length; i++) {
|
|
636
|
+
const t = list[i];
|
|
637
|
+
if (idOf(t) === trackedId) return t;
|
|
638
|
+
}
|
|
639
|
+
return null;
|
|
640
|
+
};
|
|
585
641
|
const onStart = (e) => {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
642
|
+
const onTarget = e.targetTouches ?? e.touches;
|
|
643
|
+
if (onTarget.length > 1) {
|
|
644
|
+
trackedId = null;
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const touch = e.changedTouches?.[0] ?? e.touches[0];
|
|
648
|
+
if (!touch) return;
|
|
649
|
+
trackedId = idOf(touch);
|
|
650
|
+
startX = touch.clientX;
|
|
651
|
+
startY = touch.clientY;
|
|
652
|
+
};
|
|
653
|
+
const onCancel = (e) => {
|
|
654
|
+
if (trackedId !== null && findTracked(e.changedTouches)) trackedId = null;
|
|
590
655
|
};
|
|
591
656
|
const onEnd = (e) => {
|
|
592
|
-
if (
|
|
593
|
-
|
|
594
|
-
const touch = e.changedTouches[0];
|
|
657
|
+
if (trackedId === null) return;
|
|
658
|
+
const touch = findTracked(e.changedTouches);
|
|
595
659
|
if (!touch) return;
|
|
660
|
+
trackedId = null;
|
|
596
661
|
const dx = touch.clientX - startX;
|
|
597
662
|
const dy = touch.clientY - startY;
|
|
598
663
|
const absX = Math.abs(dx);
|
|
@@ -609,9 +674,12 @@ function swipe(target, options = {}) {
|
|
|
609
674
|
};
|
|
610
675
|
target.addEventListener("touchstart", onStart, { passive: true });
|
|
611
676
|
target.addEventListener("touchend", onEnd, { passive: true });
|
|
677
|
+
target.addEventListener("touchcancel", onCancel, { passive: true });
|
|
612
678
|
function dispose() {
|
|
613
679
|
target.removeEventListener("touchstart", onStart);
|
|
614
680
|
target.removeEventListener("touchend", onEnd);
|
|
681
|
+
target.removeEventListener("touchcancel", onCancel);
|
|
682
|
+
trackedId = null;
|
|
615
683
|
}
|
|
616
684
|
return { direction, dispose };
|
|
617
685
|
}
|
|
@@ -638,6 +706,18 @@ function windowSize() {
|
|
|
638
706
|
}
|
|
639
707
|
|
|
640
708
|
// src/browser/urlState.ts
|
|
709
|
+
var _url = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.urlState.v1"), () => ({
|
|
710
|
+
instances: /* @__PURE__ */ new Set()
|
|
711
|
+
}));
|
|
712
|
+
function notifyUrlWrite() {
|
|
713
|
+
for (const sync of Array.from(_url.instances)) sync();
|
|
714
|
+
}
|
|
715
|
+
var SCROLL_ENTRY_KEY = "__sibuScrollKey";
|
|
716
|
+
function withoutEntryIdentity(state) {
|
|
717
|
+
if (state === null || typeof state !== "object" || !Object.hasOwn(state, SCROLL_ENTRY_KEY)) return state;
|
|
718
|
+
const { [SCROLL_ENTRY_KEY]: _identity, ...rest } = state;
|
|
719
|
+
return rest;
|
|
720
|
+
}
|
|
641
721
|
function urlState() {
|
|
642
722
|
if (typeof window === "undefined") {
|
|
643
723
|
const [params2] = signal(new URLSearchParams());
|
|
@@ -671,26 +751,36 @@ function urlState() {
|
|
|
671
751
|
}
|
|
672
752
|
window.addEventListener("popstate", syncFromLocation);
|
|
673
753
|
window.addEventListener("hashchange", syncFromLocation);
|
|
754
|
+
_url.instances.add(syncFromLocation);
|
|
755
|
+
function writeHistory(newUrl, opts) {
|
|
756
|
+
const state = "state" in opts ? opts.state : window.history.state;
|
|
757
|
+
if (opts.replace) window.history.replaceState(state, "", newUrl);
|
|
758
|
+
else window.history.pushState("state" in opts ? state : withoutEntryIdentity(state), "", newUrl);
|
|
759
|
+
}
|
|
674
760
|
function setParams(next, opts = {}) {
|
|
675
761
|
const p = next instanceof URLSearchParams ? next : new URLSearchParams(next);
|
|
676
762
|
const query = p.toString();
|
|
677
763
|
const newUrl = `${window.location.pathname}${query ? `?${query}` : ""}${window.location.hash}`;
|
|
678
|
-
|
|
679
|
-
else window.history.pushState(null, "", newUrl);
|
|
764
|
+
writeHistory(newUrl, opts);
|
|
680
765
|
lastSearch = window.location.search;
|
|
681
766
|
setParamsSignal(new URLSearchParams(p));
|
|
767
|
+
notifyUrlWrite();
|
|
682
768
|
}
|
|
683
769
|
function setHash(next, opts = {}) {
|
|
684
770
|
const normalized = next && next !== "#" ? next.startsWith("#") ? next : `#${next}` : "";
|
|
685
771
|
const newUrl = `${window.location.pathname}${window.location.search}${normalized}`;
|
|
686
|
-
|
|
687
|
-
else window.history.pushState(null, "", newUrl);
|
|
772
|
+
writeHistory(newUrl, opts);
|
|
688
773
|
lastHash = normalized;
|
|
689
774
|
setHashSignal(normalized);
|
|
775
|
+
notifyUrlWrite();
|
|
690
776
|
}
|
|
777
|
+
let disposed = false;
|
|
691
778
|
function dispose() {
|
|
779
|
+
if (disposed) return;
|
|
780
|
+
disposed = true;
|
|
692
781
|
window.removeEventListener("popstate", syncFromLocation);
|
|
693
782
|
window.removeEventListener("hashchange", syncFromLocation);
|
|
783
|
+
_url.instances.delete(syncFromLocation);
|
|
694
784
|
}
|
|
695
785
|
return { params, hash, setParams, setHash, dispose };
|
|
696
786
|
}
|
|
@@ -707,10 +797,14 @@ function broadcast(channelName) {
|
|
|
707
797
|
const channel = new BroadcastChannel(channelName);
|
|
708
798
|
const handler = (ev) => setLast(ev.data);
|
|
709
799
|
channel.addEventListener("message", handler);
|
|
800
|
+
let disposed = false;
|
|
710
801
|
function post(message) {
|
|
802
|
+
if (disposed) return;
|
|
711
803
|
channel.postMessage(message);
|
|
712
804
|
}
|
|
713
805
|
function dispose() {
|
|
806
|
+
if (disposed) return;
|
|
807
|
+
disposed = true;
|
|
714
808
|
channel.removeEventListener("message", handler);
|
|
715
809
|
channel.close();
|
|
716
810
|
}
|
|
@@ -909,31 +1003,42 @@ function animationFrame(options = {}) {
|
|
|
909
1003
|
let prev = -1;
|
|
910
1004
|
let start = -1;
|
|
911
1005
|
let disposed = false;
|
|
1006
|
+
let active = false;
|
|
1007
|
+
let generation = 0;
|
|
912
1008
|
const minFrameMs = options.fpsLimit ? 1e3 / options.fpsLimit : 0;
|
|
913
1009
|
const step = (now) => {
|
|
1010
|
+
id = null;
|
|
1011
|
+
if (!active) return;
|
|
1012
|
+
const frameGeneration = generation;
|
|
914
1013
|
if (start < 0) start = now;
|
|
915
1014
|
const firstTick = prev < 0;
|
|
916
1015
|
const dt = firstTick ? 0 : now - prev;
|
|
917
1016
|
if (firstTick || dt >= minFrameMs) {
|
|
918
|
-
setDelta(dt);
|
|
919
|
-
setElapsed(now - start);
|
|
920
1017
|
prev = now;
|
|
1018
|
+
const elapsedValue = now - start;
|
|
1019
|
+
setDelta(dt);
|
|
1020
|
+
if (!active || generation !== frameGeneration) return;
|
|
1021
|
+
setElapsed(elapsedValue);
|
|
1022
|
+
if (!active || generation !== frameGeneration) return;
|
|
921
1023
|
}
|
|
922
|
-
id = requestAnimationFrame(step);
|
|
1024
|
+
if (id === null) id = requestAnimationFrame(step);
|
|
923
1025
|
};
|
|
924
1026
|
function resume() {
|
|
925
|
-
if (disposed ||
|
|
926
|
-
|
|
1027
|
+
if (disposed || active) return;
|
|
1028
|
+
active = true;
|
|
927
1029
|
id = requestAnimationFrame(step);
|
|
1030
|
+
setRunning(true);
|
|
928
1031
|
}
|
|
929
1032
|
function pause() {
|
|
1033
|
+
generation++;
|
|
1034
|
+
active = false;
|
|
930
1035
|
if (id !== null) {
|
|
931
1036
|
cancelAnimationFrame(id);
|
|
932
1037
|
id = null;
|
|
933
1038
|
}
|
|
934
|
-
setRunning(false);
|
|
935
1039
|
prev = -1;
|
|
936
1040
|
start = -1;
|
|
1041
|
+
setRunning(false);
|
|
937
1042
|
}
|
|
938
1043
|
function dispose() {
|
|
939
1044
|
disposed = true;
|
|
@@ -1063,6 +1168,35 @@ function keyboard(options = {}) {
|
|
|
1063
1168
|
}
|
|
1064
1169
|
|
|
1065
1170
|
// src/browser/speech.ts
|
|
1171
|
+
var _speech = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.speech.v1"), () => ({
|
|
1172
|
+
queue: [],
|
|
1173
|
+
active: null,
|
|
1174
|
+
owners: /* @__PURE__ */ new Set()
|
|
1175
|
+
}));
|
|
1176
|
+
function syncOwners() {
|
|
1177
|
+
for (const owner of Array.from(_speech.owners)) owner.sync();
|
|
1178
|
+
}
|
|
1179
|
+
function pump(synth) {
|
|
1180
|
+
if (_speech.active) return;
|
|
1181
|
+
const index = _speech.queue.findIndex((entry2) => !entry2.owner.paused);
|
|
1182
|
+
if (index === -1) return;
|
|
1183
|
+
const [entry] = _speech.queue.splice(index, 1);
|
|
1184
|
+
_speech.active = entry;
|
|
1185
|
+
const finish = () => {
|
|
1186
|
+
if (_speech.active !== entry) return;
|
|
1187
|
+
_speech.active = null;
|
|
1188
|
+
pump(synth);
|
|
1189
|
+
syncOwners();
|
|
1190
|
+
};
|
|
1191
|
+
entry.utterance.addEventListener("end", finish, { once: true });
|
|
1192
|
+
entry.utterance.addEventListener("error", finish, { once: true });
|
|
1193
|
+
synth.speak(entry.utterance);
|
|
1194
|
+
}
|
|
1195
|
+
function __resetSpeechCoordinator() {
|
|
1196
|
+
_speech.queue.length = 0;
|
|
1197
|
+
_speech.active = null;
|
|
1198
|
+
_speech.owners.clear();
|
|
1199
|
+
}
|
|
1066
1200
|
function speech() {
|
|
1067
1201
|
const [speaking, setSpeaking] = signal(false);
|
|
1068
1202
|
const [paused, setPaused] = signal(false);
|
|
@@ -1083,19 +1217,16 @@ function speech() {
|
|
|
1083
1217
|
};
|
|
1084
1218
|
}
|
|
1085
1219
|
const synth = window.speechSynthesis;
|
|
1086
|
-
let interval = null;
|
|
1087
|
-
function startPolling() {
|
|
1088
|
-
if (interval !== null) return;
|
|
1089
|
-
interval = setInterval(() => {
|
|
1090
|
-
setSpeaking(synth.speaking);
|
|
1091
|
-
setPaused(synth.paused);
|
|
1092
|
-
if (!synth.speaking && !synth.paused) {
|
|
1093
|
-
clearInterval(interval);
|
|
1094
|
-
interval = null;
|
|
1095
|
-
}
|
|
1096
|
-
}, 200);
|
|
1097
|
-
}
|
|
1098
1220
|
let disposed = false;
|
|
1221
|
+
const owner = {
|
|
1222
|
+
paused: false,
|
|
1223
|
+
sync: () => {
|
|
1224
|
+
const mine = _speech.active?.owner === owner || _speech.queue.some((entry) => entry.owner === owner);
|
|
1225
|
+
setSpeaking(mine);
|
|
1226
|
+
setPaused(owner.paused);
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
_speech.owners.add(owner);
|
|
1099
1230
|
function speak(text, options = {}) {
|
|
1100
1231
|
if (disposed) return;
|
|
1101
1232
|
const u = new SpeechSynthesisUtterance(text);
|
|
@@ -1108,52 +1239,48 @@ function speech() {
|
|
|
1108
1239
|
const match = voices.find((v) => v.name === options.voice);
|
|
1109
1240
|
if (match) u.voice = match;
|
|
1110
1241
|
}
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
);
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1242
|
+
_speech.queue.push({ owner, utterance: u });
|
|
1243
|
+
pump(synth);
|
|
1244
|
+
syncOwners();
|
|
1245
|
+
}
|
|
1246
|
+
function pause() {
|
|
1247
|
+
if (disposed || owner.paused) return;
|
|
1248
|
+
owner.paused = true;
|
|
1249
|
+
if (_speech.active?.owner === owner) synth.pause();
|
|
1250
|
+
syncOwners();
|
|
1251
|
+
}
|
|
1252
|
+
function resume() {
|
|
1253
|
+
if (disposed || !owner.paused) return;
|
|
1254
|
+
owner.paused = false;
|
|
1255
|
+
if (_speech.active?.owner === owner) synth.resume();
|
|
1256
|
+
else pump(synth);
|
|
1257
|
+
syncOwners();
|
|
1258
|
+
}
|
|
1259
|
+
function cancel() {
|
|
1260
|
+
if (disposed) return;
|
|
1261
|
+
cancelOwned();
|
|
1262
|
+
syncOwners();
|
|
1263
|
+
}
|
|
1264
|
+
function cancelOwned() {
|
|
1265
|
+
for (let i = _speech.queue.length - 1; i >= 0; i--) {
|
|
1266
|
+
if (_speech.queue[i].owner === owner) _speech.queue.splice(i, 1);
|
|
1267
|
+
}
|
|
1268
|
+
owner.paused = false;
|
|
1269
|
+
if (_speech.active?.owner === owner) {
|
|
1270
|
+
_speech.active = null;
|
|
1271
|
+
if (synth.paused) synth.resume();
|
|
1272
|
+
synth.cancel();
|
|
1273
|
+
pump(synth);
|
|
1274
|
+
}
|
|
1139
1275
|
}
|
|
1140
1276
|
function dispose() {
|
|
1277
|
+
if (disposed) return;
|
|
1278
|
+
cancelOwned();
|
|
1141
1279
|
disposed = true;
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
interval = null;
|
|
1145
|
-
}
|
|
1146
|
-
synth.cancel();
|
|
1280
|
+
syncOwners();
|
|
1281
|
+
_speech.owners.delete(owner);
|
|
1147
1282
|
}
|
|
1148
|
-
return {
|
|
1149
|
-
speaking,
|
|
1150
|
-
paused,
|
|
1151
|
-
speak,
|
|
1152
|
-
pause: () => synth.pause(),
|
|
1153
|
-
resume: () => synth.resume(),
|
|
1154
|
-
cancel: () => synth.cancel(),
|
|
1155
|
-
dispose
|
|
1156
|
-
};
|
|
1283
|
+
return { speaking, paused, speak, pause, resume, cancel, dispose };
|
|
1157
1284
|
}
|
|
1158
1285
|
|
|
1159
1286
|
// src/browser/gamepad.ts
|
|
@@ -1164,6 +1291,7 @@ function gamepad() {
|
|
|
1164
1291
|
} };
|
|
1165
1292
|
}
|
|
1166
1293
|
let rafId = null;
|
|
1294
|
+
let disposed = false;
|
|
1167
1295
|
function snapshot(pad) {
|
|
1168
1296
|
return {
|
|
1169
1297
|
index: pad.index,
|
|
@@ -1178,7 +1306,7 @@ function gamepad() {
|
|
|
1178
1306
|
for (let i = 0; i < a.length; i++) {
|
|
1179
1307
|
const pa = a[i];
|
|
1180
1308
|
const pb = b[i];
|
|
1181
|
-
if (pa.index !== pb.index || pa.connected !== pb.connected) return false;
|
|
1309
|
+
if (pa.index !== pb.index || pa.id !== pb.id || pa.connected !== pb.connected) return false;
|
|
1182
1310
|
if (pa.buttons.length !== pb.buttons.length) return false;
|
|
1183
1311
|
for (let j = 0; j < pa.buttons.length; j++) {
|
|
1184
1312
|
if (pa.buttons[j].pressed !== pb.buttons[j].pressed) return false;
|
|
@@ -1191,15 +1319,19 @@ function gamepad() {
|
|
|
1191
1319
|
}
|
|
1192
1320
|
return true;
|
|
1193
1321
|
}
|
|
1322
|
+
function publish() {
|
|
1323
|
+
const snap = Array.from(navigator.getGamepads()).filter((g) => g !== null).map(snapshot);
|
|
1324
|
+
if (!equal(pads(), snap)) setPads(snap);
|
|
1325
|
+
return snap;
|
|
1326
|
+
}
|
|
1194
1327
|
function poll() {
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
if (!
|
|
1199
|
-
rafId = requestAnimationFrame(poll);
|
|
1328
|
+
rafId = null;
|
|
1329
|
+
if (disposed) return;
|
|
1330
|
+
publish();
|
|
1331
|
+
if (!disposed && rafId === null) rafId = requestAnimationFrame(poll);
|
|
1200
1332
|
}
|
|
1201
1333
|
function startPolling() {
|
|
1202
|
-
if (rafId === null) poll();
|
|
1334
|
+
if (!disposed && rafId === null) poll();
|
|
1203
1335
|
}
|
|
1204
1336
|
function stopPolling() {
|
|
1205
1337
|
if (rafId !== null) {
|
|
@@ -1209,15 +1341,14 @@ function gamepad() {
|
|
|
1209
1341
|
}
|
|
1210
1342
|
const onConnect = () => startPolling();
|
|
1211
1343
|
const onDisconnect = () => {
|
|
1212
|
-
|
|
1213
|
-
const hasAny = Array.from(raw).some((g) => g !== null);
|
|
1214
|
-
if (!hasAny) stopPolling();
|
|
1344
|
+
if (publish().length === 0) stopPolling();
|
|
1215
1345
|
};
|
|
1216
1346
|
window.addEventListener("gamepadconnected", onConnect);
|
|
1217
1347
|
window.addEventListener("gamepaddisconnected", onDisconnect);
|
|
1218
1348
|
const initial = Array.from(navigator.getGamepads()).some((g) => g !== null);
|
|
1219
1349
|
if (initial) startPolling();
|
|
1220
1350
|
function dispose() {
|
|
1351
|
+
disposed = true;
|
|
1221
1352
|
stopPolling();
|
|
1222
1353
|
window.removeEventListener("gamepadconnected", onConnect);
|
|
1223
1354
|
window.removeEventListener("gamepaddisconnected", onDisconnect);
|
|
@@ -1231,8 +1362,7 @@ function pointerLock() {
|
|
|
1231
1362
|
if (typeof document === "undefined") {
|
|
1232
1363
|
return {
|
|
1233
1364
|
locked,
|
|
1234
|
-
request: () =>
|
|
1235
|
-
},
|
|
1365
|
+
request: () => Promise.resolve(),
|
|
1236
1366
|
exit: () => {
|
|
1237
1367
|
},
|
|
1238
1368
|
dispose: () => {
|
|
@@ -1244,8 +1374,14 @@ function pointerLock() {
|
|
|
1244
1374
|
};
|
|
1245
1375
|
document.addEventListener("pointerlockchange", handler);
|
|
1246
1376
|
function request(element) {
|
|
1247
|
-
if (typeof element.requestPointerLock
|
|
1248
|
-
|
|
1377
|
+
if (typeof element.requestPointerLock !== "function") {
|
|
1378
|
+
return Promise.resolve();
|
|
1379
|
+
}
|
|
1380
|
+
try {
|
|
1381
|
+
const result = element.requestPointerLock();
|
|
1382
|
+
return Promise.resolve(result).then(() => void 0);
|
|
1383
|
+
} catch (err) {
|
|
1384
|
+
return Promise.reject(err);
|
|
1249
1385
|
}
|
|
1250
1386
|
}
|
|
1251
1387
|
function exit() {
|
|
@@ -1348,25 +1484,46 @@ function imageLoader(src) {
|
|
|
1348
1484
|
};
|
|
1349
1485
|
}
|
|
1350
1486
|
let current = null;
|
|
1487
|
+
let currentSettled = false;
|
|
1351
1488
|
let disposed = false;
|
|
1489
|
+
let startToken = 0;
|
|
1490
|
+
function resetState() {
|
|
1491
|
+
batch(() => {
|
|
1492
|
+
setStatus("pending");
|
|
1493
|
+
setImage(null);
|
|
1494
|
+
setWidth(0);
|
|
1495
|
+
setHeight(0);
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
function abandonCurrent() {
|
|
1499
|
+
if (!current) return;
|
|
1500
|
+
const prev = current;
|
|
1501
|
+
current = null;
|
|
1502
|
+
prev.onload = null;
|
|
1503
|
+
prev.onerror = null;
|
|
1504
|
+
if (!currentSettled) prev.src = "";
|
|
1505
|
+
}
|
|
1352
1506
|
function start(url) {
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
setStatus("pending");
|
|
1358
|
-
setImage(null);
|
|
1507
|
+
const token = ++startToken;
|
|
1508
|
+
abandonCurrent();
|
|
1509
|
+
resetState();
|
|
1510
|
+
if (disposed || token !== startToken) return;
|
|
1359
1511
|
const img = new Image();
|
|
1360
1512
|
current = img;
|
|
1513
|
+
currentSettled = false;
|
|
1361
1514
|
img.onload = () => {
|
|
1362
1515
|
if (disposed || current !== img) return;
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1516
|
+
currentSettled = true;
|
|
1517
|
+
batch(() => {
|
|
1518
|
+
setImage(img);
|
|
1519
|
+
setWidth(img.naturalWidth);
|
|
1520
|
+
setHeight(img.naturalHeight);
|
|
1521
|
+
setStatus("loaded");
|
|
1522
|
+
});
|
|
1367
1523
|
};
|
|
1368
1524
|
img.onerror = () => {
|
|
1369
1525
|
if (disposed || current !== img) return;
|
|
1526
|
+
currentSettled = true;
|
|
1370
1527
|
setStatus("error");
|
|
1371
1528
|
};
|
|
1372
1529
|
img.src = url;
|
|
@@ -1381,16 +1538,15 @@ function imageLoader(src) {
|
|
|
1381
1538
|
start(src);
|
|
1382
1539
|
}
|
|
1383
1540
|
function dispose() {
|
|
1541
|
+
if (disposed) return;
|
|
1384
1542
|
disposed = true;
|
|
1543
|
+
startToken++;
|
|
1385
1544
|
if (srcEffectTeardown) {
|
|
1386
1545
|
srcEffectTeardown();
|
|
1387
1546
|
srcEffectTeardown = null;
|
|
1388
1547
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
current.onerror = null;
|
|
1392
|
-
current = null;
|
|
1393
|
-
}
|
|
1548
|
+
abandonCurrent();
|
|
1549
|
+
resetState();
|
|
1394
1550
|
}
|
|
1395
1551
|
return { status, image, width, height, dispose };
|
|
1396
1552
|
}
|
|
@@ -1424,6 +1580,7 @@ export {
|
|
|
1424
1580
|
mutationObserver,
|
|
1425
1581
|
bounds,
|
|
1426
1582
|
keyboard,
|
|
1583
|
+
__resetSpeechCoordinator,
|
|
1427
1584
|
speech,
|
|
1428
1585
|
gamepad,
|
|
1429
1586
|
pointerLock,
|