@surdeddd/bottom-sheet 0.12.0 → 0.14.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 +85 -1
- package/dist/{BottomSheetEngine-D6oiEfZ4.d.cts → BottomSheetCore-Cp7dWy91.d.cts} +85 -5
- package/dist/{BottomSheetEngine-Dhy0X_e9.d.ts → BottomSheetCore-DJYwWOqt.d.ts} +85 -5
- package/dist/BottomSheetEngine-Lm7HIVHv.d.cts +7 -0
- package/dist/BottomSheetEngine-O5PbeKfe.d.ts +7 -0
- package/dist/core.cjs +3680 -0
- package/dist/core.d.cts +3 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +3678 -0
- package/dist/debug.cjs +109 -0
- package/dist/debug.d.cts +22 -0
- package/dist/debug.d.ts +22 -0
- package/dist/debug.js +107 -0
- package/dist/element.cjs +1314 -829
- package/dist/element.d.cts +2 -1
- package/dist/element.d.ts +2 -1
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +1314 -829
- package/dist/features.cjs +489 -0
- package/dist/features.d.cts +13 -0
- package/dist/features.d.ts +13 -0
- package/dist/features.js +482 -0
- package/dist/index-Bb5TRmyg.d.cts +9 -0
- package/dist/index-Cl9ebCP2.d.ts +9 -0
- package/dist/index.cjs +979 -1293
- package/dist/index.d.cts +43 -55
- package/dist/index.d.ts +43 -55
- package/dist/index.js +973 -1280
- package/dist/integrations/formik.d.cts +1 -1
- package/dist/integrations/formik.d.ts +1 -1
- package/dist/integrations/react-hook-form.d.cts +1 -1
- package/dist/integrations/react-hook-form.d.ts +1 -1
- package/dist/overlay.cjs +11 -10
- package/dist/overlay.js +11 -10
- package/dist/preact.d.cts +2 -1
- package/dist/preact.d.ts +2 -1
- package/dist/qwik-lib/index.qwik.cjs +4418 -0
- package/dist/qwik-lib/index.qwik.mjs +4418 -0
- package/dist/qwik.cjs +1089 -657
- package/dist/qwik.d.cts +4 -2
- package/dist/qwik.d.ts +4 -2
- package/dist/qwik.js +1089 -657
- package/dist/react.cjs +1100 -665
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/react.js +1100 -665
- package/dist/solid.cjs +1095 -657
- package/dist/solid.d.cts +90 -4
- package/dist/solid.d.ts +90 -4
- package/dist/solid.js +1095 -657
- package/dist/solid.source.jsx +1103 -657
- package/dist/styles.css +24 -4
- package/dist/svelte-core.cjs +981 -557
- package/dist/svelte-core.js +981 -557
- package/dist/svelte-src/BottomSheet.svelte +14 -0
- package/dist/svelte.cjs +1091 -657
- package/dist/svelte.d.cts +2 -0
- package/dist/svelte.d.ts +2 -0
- package/dist/svelte.js +1091 -657
- package/dist/vue.cjs +1105 -657
- package/dist/vue.js +1105 -657
- package/dist/webgl.cjs +583 -0
- package/dist/webgl.d.cts +17 -0
- package/dist/webgl.d.ts +17 -0
- package/dist/webgl.js +581 -0
- package/package.json +88 -12
package/dist/svelte.cjs
CHANGED
|
@@ -28,7 +28,7 @@ var __defProp = Object.defineProperty;
|
|
|
28
28
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
29
29
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
30
30
|
|
|
31
|
-
// src/core/lifecycle/
|
|
31
|
+
// src/core/lifecycle/sheet-stack.ts
|
|
32
32
|
var BASE_Z = 100;
|
|
33
33
|
var STEP = 10;
|
|
34
34
|
var SheetStack = class {
|
|
@@ -153,7 +153,7 @@ function createEventBus() {
|
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
// src/core/primitives/
|
|
156
|
+
// src/core/primitives/css-length.ts
|
|
157
157
|
var probe = null;
|
|
158
158
|
var PROBE_ATTR = "data-bs-probe";
|
|
159
159
|
var ensureProbe = (axis) => {
|
|
@@ -207,7 +207,7 @@ var resolveSnap = (point, mode, measureFit) => {
|
|
|
207
207
|
return Math.max(0, el.getBoundingClientRect().width);
|
|
208
208
|
};
|
|
209
209
|
|
|
210
|
-
// src/core/primitives/
|
|
210
|
+
// src/core/primitives/dev-warn.ts
|
|
211
211
|
function devWarn(...args) {
|
|
212
212
|
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
|
|
213
213
|
console.warn(...args);
|
|
@@ -372,74 +372,6 @@ var SnapResolver = class {
|
|
|
372
372
|
}
|
|
373
373
|
};
|
|
374
374
|
|
|
375
|
-
// src/core/features/persist.ts
|
|
376
|
-
function readPersistedId(key) {
|
|
377
|
-
if (!key) return null;
|
|
378
|
-
if (typeof window === "undefined") return null;
|
|
379
|
-
if (typeof localStorage === "undefined") return null;
|
|
380
|
-
try {
|
|
381
|
-
return localStorage.getItem(key);
|
|
382
|
-
} catch {
|
|
383
|
-
return null;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
function installPersist(engine, key) {
|
|
387
|
-
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
388
|
-
if (typeof window === "undefined") return;
|
|
389
|
-
if (typeof localStorage === "undefined") return;
|
|
390
|
-
try {
|
|
391
|
-
localStorage.setItem(key, id);
|
|
392
|
-
} catch {
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
return unsubscribe;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// src/core/features/auto-collapse.ts
|
|
399
|
-
function installAutoCollapse(deps) {
|
|
400
|
-
const { ms } = deps;
|
|
401
|
-
if (ms === void 0 || ms <= 0) {
|
|
402
|
-
return () => {
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
let timer = null;
|
|
406
|
-
const clearTimer = () => {
|
|
407
|
-
if (timer !== null) {
|
|
408
|
-
clearTimeout(timer);
|
|
409
|
-
timer = null;
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
const fire = () => {
|
|
413
|
-
if (deps.isDestroyed()) return;
|
|
414
|
-
if (deps.isDragging()) return;
|
|
415
|
-
const active = deps.resolveSnap(deps.getActiveId());
|
|
416
|
-
if (!active || active.size === 0) return;
|
|
417
|
-
let target = null;
|
|
418
|
-
for (const id of deps.getAllowedIds()) {
|
|
419
|
-
const snap = deps.resolveSnap(id);
|
|
420
|
-
if (!snap || snap.size <= 0) continue;
|
|
421
|
-
if (!target || snap.size < target.size) target = snap;
|
|
422
|
-
}
|
|
423
|
-
if (!target) return;
|
|
424
|
-
if (target.id === active.id || target.size >= active.size) return;
|
|
425
|
-
deps.snapTo(target.id);
|
|
426
|
-
};
|
|
427
|
-
const reset2 = () => {
|
|
428
|
-
clearTimer();
|
|
429
|
-
if (deps.isDestroyed()) return;
|
|
430
|
-
timer = setTimeout(() => {
|
|
431
|
-
timer = null;
|
|
432
|
-
fire();
|
|
433
|
-
}, ms);
|
|
434
|
-
};
|
|
435
|
-
const unsubscribe = deps.on("snap", () => reset2());
|
|
436
|
-
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset2();
|
|
437
|
-
return () => {
|
|
438
|
-
clearTimer();
|
|
439
|
-
unsubscribe();
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
|
|
443
375
|
// src/core/features/linked-sheets.ts
|
|
444
376
|
function notifyLinkedSheets(sheets, self) {
|
|
445
377
|
if (sheets.length === 0) return;
|
|
@@ -462,394 +394,65 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
462
394
|
}
|
|
463
395
|
}
|
|
464
396
|
|
|
465
|
-
// src/core/features/
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
var pendingRebrand = null;
|
|
471
|
-
var listenerInstalled = false;
|
|
472
|
-
var patchInstalled = false;
|
|
473
|
-
var origPushState = null;
|
|
474
|
-
var origReplaceState = null;
|
|
475
|
-
var patchedPushState = null;
|
|
476
|
-
var patchedReplaceState = null;
|
|
477
|
-
var hasWindow = () => typeof window !== "undefined";
|
|
478
|
-
var hasHistory = () => typeof history !== "undefined";
|
|
479
|
-
var brandMarker = (surface) => ({
|
|
480
|
-
...surface.markerState(),
|
|
481
|
-
__bs: true
|
|
482
|
-
});
|
|
483
|
-
var runInternal = (fn) => {
|
|
484
|
-
internalDepth += 1;
|
|
485
|
-
try {
|
|
486
|
-
fn();
|
|
487
|
-
} finally {
|
|
488
|
-
internalDepth -= 1;
|
|
489
|
-
}
|
|
490
|
-
};
|
|
491
|
-
var notifyRouteChange = () => {
|
|
492
|
-
const snapshot = Array.from(subscribers);
|
|
493
|
-
for (const fn of snapshot) fn();
|
|
494
|
-
};
|
|
495
|
-
var ensureListener = () => {
|
|
496
|
-
if (listenerInstalled || !hasWindow()) return;
|
|
497
|
-
window.addEventListener("popstate", onPopState);
|
|
498
|
-
listenerInstalled = true;
|
|
499
|
-
};
|
|
500
|
-
var maybeTeardownListener = () => {
|
|
501
|
-
if (!listenerInstalled) return;
|
|
502
|
-
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
503
|
-
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
504
|
-
listenerInstalled = false;
|
|
505
|
-
};
|
|
506
|
-
var installPatch = () => {
|
|
507
|
-
if (patchInstalled || !hasHistory()) return;
|
|
508
|
-
origPushState = history.pushState;
|
|
509
|
-
origReplaceState = history.replaceState;
|
|
510
|
-
patchedPushState = function(...args) {
|
|
511
|
-
origPushState.apply(this, args);
|
|
512
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
513
|
-
};
|
|
514
|
-
patchedReplaceState = function(...args) {
|
|
515
|
-
origReplaceState.apply(this, args);
|
|
516
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
517
|
-
};
|
|
518
|
-
history.pushState = patchedPushState;
|
|
519
|
-
history.replaceState = patchedReplaceState;
|
|
520
|
-
patchInstalled = true;
|
|
521
|
-
};
|
|
522
|
-
var removePatch = () => {
|
|
523
|
-
if (!patchInstalled) return;
|
|
524
|
-
if (history.pushState === patchedPushState && origPushState) {
|
|
525
|
-
history.pushState = origPushState;
|
|
526
|
-
}
|
|
527
|
-
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
528
|
-
history.replaceState = origReplaceState;
|
|
529
|
-
}
|
|
530
|
-
origPushState = null;
|
|
531
|
-
origReplaceState = null;
|
|
532
|
-
patchedPushState = null;
|
|
533
|
-
patchedReplaceState = null;
|
|
534
|
-
patchInstalled = false;
|
|
535
|
-
};
|
|
536
|
-
function onPopState() {
|
|
537
|
-
if (suppress > 0) {
|
|
538
|
-
suppress -= 1;
|
|
539
|
-
const rebrand = pendingRebrand;
|
|
540
|
-
pendingRebrand = null;
|
|
541
|
-
if (rebrand) rebrand();
|
|
542
|
-
maybeTeardownListener();
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
if (entries.length === 0) {
|
|
546
|
-
notifyRouteChange();
|
|
547
|
-
maybeTeardownListener();
|
|
548
|
-
return;
|
|
397
|
+
// src/core/features/resize-observer.ts
|
|
398
|
+
function installResizeObserver(deps) {
|
|
399
|
+
if (typeof window === "undefined") {
|
|
400
|
+
return () => {
|
|
401
|
+
};
|
|
549
402
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
403
|
+
const onResize = () => {
|
|
404
|
+
if (deps.isDestroyed()) return;
|
|
405
|
+
deps.recomputeSnaps();
|
|
406
|
+
const mode = deps.getMode();
|
|
407
|
+
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
408
|
+
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
409
|
+
const max = deps.getMaxAxisSize();
|
|
410
|
+
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
411
|
+
deps.setMaxAxisSize(viewportSize2);
|
|
558
412
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
413
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
414
|
+
deps.cancelInFlight();
|
|
415
|
+
deps.newCycle();
|
|
416
|
+
const current = deps.resolveActiveSnap();
|
|
417
|
+
const newMax = deps.getMaxAxisSize();
|
|
418
|
+
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
419
|
+
deps.setSize(targetSize);
|
|
420
|
+
if (current && !deps.isDragging()) {
|
|
421
|
+
deps.applySize(targetSize);
|
|
422
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
563
423
|
}
|
|
424
|
+
};
|
|
425
|
+
let resizeObserver = null;
|
|
426
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
427
|
+
resizeObserver = new ResizeObserver(onResize);
|
|
428
|
+
resizeObserver.observe(document.documentElement);
|
|
429
|
+
} else {
|
|
430
|
+
window.addEventListener("resize", onResize);
|
|
564
431
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
if (
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}
|
|
577
|
-
maybeTeardownListener();
|
|
432
|
+
window.addEventListener("orientationchange", onResize);
|
|
433
|
+
const onVisibility = () => {
|
|
434
|
+
if (deps.isDestroyed()) return;
|
|
435
|
+
if (document.hidden) deps.cancelInFlight();
|
|
436
|
+
};
|
|
437
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
438
|
+
return () => {
|
|
439
|
+
resizeObserver?.disconnect();
|
|
440
|
+
window.removeEventListener("resize", onResize);
|
|
441
|
+
window.removeEventListener("orientationchange", onResize);
|
|
442
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
443
|
+
};
|
|
578
444
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
entries.push(entry);
|
|
591
|
-
ensureListener();
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
function pushBackMarker(surface) {
|
|
595
|
-
const entry = { surface, priorUrl: void 0, live: false };
|
|
596
|
-
if (!hasWindow() || !hasHistory()) {
|
|
597
|
-
return entry;
|
|
598
|
-
}
|
|
599
|
-
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
600
|
-
runInternal(() => {
|
|
601
|
-
try {
|
|
602
|
-
history.pushState(brandMarker(surface), "", surface.url);
|
|
603
|
-
entry.live = true;
|
|
604
|
-
} catch {
|
|
605
|
-
entry.live = false;
|
|
606
|
-
}
|
|
607
|
-
});
|
|
608
|
-
if (entry.live) {
|
|
609
|
-
entries.push(entry);
|
|
610
|
-
ensureListener();
|
|
611
|
-
}
|
|
612
|
-
return entry;
|
|
613
|
-
}
|
|
614
|
-
function popBackMarker(handle) {
|
|
615
|
-
if (!hasWindow() || !hasHistory()) return;
|
|
616
|
-
const entry = handle;
|
|
617
|
-
const idx = entries.indexOf(entry);
|
|
618
|
-
if (idx === -1 || !entry.live) return;
|
|
619
|
-
const last = entries.length - 1;
|
|
620
|
-
entry.live = false;
|
|
621
|
-
entries.splice(idx, 1);
|
|
622
|
-
if (idx !== last) {
|
|
623
|
-
const rebrandSurface = entries[entries.length - 1].surface;
|
|
624
|
-
const rebrandUrl = entry.priorUrl;
|
|
625
|
-
pendingRebrand = () => {
|
|
626
|
-
runInternal(() => {
|
|
627
|
-
history.replaceState(
|
|
628
|
-
brandMarker(rebrandSurface),
|
|
629
|
-
"",
|
|
630
|
-
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
631
|
-
);
|
|
632
|
-
});
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
suppress += 1;
|
|
636
|
-
runInternal(() => {
|
|
637
|
-
try {
|
|
638
|
-
history.back();
|
|
639
|
-
} catch {
|
|
640
|
-
suppress = Math.max(0, suppress - 1);
|
|
641
|
-
pendingRebrand = null;
|
|
642
|
-
}
|
|
643
|
-
});
|
|
644
|
-
maybeTeardownListener();
|
|
645
|
-
}
|
|
646
|
-
function subscribeRouteChange(fn) {
|
|
647
|
-
if (!hasWindow() || !hasHistory()) return () => {
|
|
648
|
-
};
|
|
649
|
-
subscribers.add(fn);
|
|
650
|
-
if (subscribers.size === 1) installPatch();
|
|
651
|
-
ensureListener();
|
|
652
|
-
return () => {
|
|
653
|
-
if (!subscribers.has(fn)) return;
|
|
654
|
-
subscribers.delete(fn);
|
|
655
|
-
if (subscribers.size === 0) removePatch();
|
|
656
|
-
maybeTeardownListener();
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
// src/core/features/route.ts
|
|
661
|
-
function installRoute(deps) {
|
|
662
|
-
if (typeof window === "undefined") {
|
|
663
|
-
return () => {
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
if (!deps.routedTo && !deps.closeOnBack) {
|
|
667
|
-
return () => {
|
|
668
|
-
};
|
|
669
|
-
}
|
|
670
|
-
let handle = null;
|
|
671
|
-
const onOpen = () => {
|
|
672
|
-
if (handle) return;
|
|
673
|
-
handle = pushBackMarker({
|
|
674
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
675
|
-
isTop: deps.isTopSheet,
|
|
676
|
-
close: deps.close,
|
|
677
|
-
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
678
|
-
url: deps.routedTo
|
|
679
|
-
});
|
|
680
|
-
};
|
|
681
|
-
const onClose = () => {
|
|
682
|
-
if (!handle) return;
|
|
683
|
-
popBackMarker(handle);
|
|
684
|
-
handle = null;
|
|
685
|
-
};
|
|
686
|
-
const unsubscribeOpen = deps.on("open", onOpen);
|
|
687
|
-
const unsubscribeClose = deps.on("close", onClose);
|
|
688
|
-
if (deps.getSize() > 0) onOpen();
|
|
689
|
-
return () => {
|
|
690
|
-
unsubscribeOpen();
|
|
691
|
-
unsubscribeClose();
|
|
692
|
-
if (handle) {
|
|
693
|
-
popBackMarker(handle);
|
|
694
|
-
handle = null;
|
|
695
|
-
}
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
function installRouteChange(deps) {
|
|
699
|
-
return subscribeRouteChange(() => {
|
|
700
|
-
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
701
|
-
void deps.close();
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// src/core/features/content-swipe.ts
|
|
706
|
-
var CONTENT_PULL_THRESHOLD = 60;
|
|
707
|
-
function installContentSwipe(deps) {
|
|
708
|
-
const { container } = deps;
|
|
709
|
-
let startY = 0;
|
|
710
|
-
let startScrollTop = 0;
|
|
711
|
-
let moved = false;
|
|
712
|
-
const onTouchStart = (e) => {
|
|
713
|
-
const t = e.touches[0];
|
|
714
|
-
if (!t) return;
|
|
715
|
-
startY = t.clientY;
|
|
716
|
-
startScrollTop = container.scrollTop;
|
|
717
|
-
moved = false;
|
|
718
|
-
};
|
|
719
|
-
const onTouchMove = (e) => {
|
|
720
|
-
const t = e.touches[0];
|
|
721
|
-
if (!t) return;
|
|
722
|
-
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
723
|
-
};
|
|
724
|
-
const onTouchEnd = (e) => {
|
|
725
|
-
if (!moved) return;
|
|
726
|
-
if (deps.isDragging() || deps.isAnimating()) return;
|
|
727
|
-
if (container.scrollTop !== startScrollTop) return;
|
|
728
|
-
const t = e.changedTouches[0];
|
|
729
|
-
if (!t) return;
|
|
730
|
-
const deltaY = t.clientY - startY;
|
|
731
|
-
const atTop = container.scrollTop <= 0;
|
|
732
|
-
const allowed = deps.getAllowedIds();
|
|
733
|
-
const idx = allowed.indexOf(deps.getActiveId());
|
|
734
|
-
if (idx === -1) return;
|
|
735
|
-
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
736
|
-
deps.snapTo(allowed[idx - 1]);
|
|
737
|
-
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
738
|
-
deps.snapTo(allowed[idx + 1]);
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
742
|
-
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
743
|
-
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
744
|
-
return () => {
|
|
745
|
-
container.removeEventListener("touchstart", onTouchStart);
|
|
746
|
-
container.removeEventListener("touchmove", onTouchMove);
|
|
747
|
-
container.removeEventListener("touchend", onTouchEnd);
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// src/core/features/visual-viewport.ts
|
|
752
|
-
var SAFETY_PAD = 8;
|
|
753
|
-
function installVisualViewport(deps) {
|
|
754
|
-
if (typeof window === "undefined" || !window.visualViewport) {
|
|
755
|
-
return () => {
|
|
756
|
-
};
|
|
757
|
-
}
|
|
758
|
-
const vv = window.visualViewport;
|
|
759
|
-
let rafId = null;
|
|
760
|
-
const onResize = () => {
|
|
761
|
-
if (rafId !== null) return;
|
|
762
|
-
rafId = requestAnimationFrame(() => {
|
|
763
|
-
rafId = null;
|
|
764
|
-
if (deps.isDestroyed()) return;
|
|
765
|
-
deps.recomputeSnaps();
|
|
766
|
-
const isVertical = deps.isVerticalAxis();
|
|
767
|
-
const visible = isVertical ? vv.height : vv.width;
|
|
768
|
-
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
769
|
-
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
770
|
-
if (clamp < deps.getMaxAxisSize()) {
|
|
771
|
-
deps.setMaxAxisSize(clamp);
|
|
772
|
-
}
|
|
773
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
774
|
-
deps.cancelInFlight();
|
|
775
|
-
deps.newCycle();
|
|
776
|
-
const max = deps.getMaxAxisSize();
|
|
777
|
-
deps.setSize(Math.min(deps.getSize(), max));
|
|
778
|
-
const current = deps.resolveActiveSnap();
|
|
779
|
-
if (current && !deps.isDragging()) {
|
|
780
|
-
deps.applySize(Math.min(current.size, max));
|
|
781
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
782
|
-
} else {
|
|
783
|
-
deps.applySize(deps.getSize());
|
|
784
|
-
}
|
|
785
|
-
});
|
|
786
|
-
};
|
|
787
|
-
vv.addEventListener("resize", onResize);
|
|
788
|
-
return () => {
|
|
789
|
-
vv.removeEventListener("resize", onResize);
|
|
790
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
// src/core/features/resize-observer.ts
|
|
795
|
-
function installResizeObserver(deps) {
|
|
796
|
-
if (typeof window === "undefined") {
|
|
797
|
-
return () => {
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
const onResize = () => {
|
|
801
|
-
if (deps.isDestroyed()) return;
|
|
802
|
-
deps.recomputeSnaps();
|
|
803
|
-
const mode = deps.getMode();
|
|
804
|
-
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
805
|
-
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
806
|
-
const max = deps.getMaxAxisSize();
|
|
807
|
-
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
808
|
-
deps.setMaxAxisSize(viewportSize2);
|
|
809
|
-
}
|
|
810
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
811
|
-
deps.cancelInFlight();
|
|
812
|
-
deps.newCycle();
|
|
813
|
-
const current = deps.resolveActiveSnap();
|
|
814
|
-
const newMax = deps.getMaxAxisSize();
|
|
815
|
-
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
816
|
-
deps.setSize(targetSize);
|
|
817
|
-
if (current && !deps.isDragging()) {
|
|
818
|
-
deps.applySize(targetSize);
|
|
819
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
let resizeObserver = null;
|
|
823
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
824
|
-
resizeObserver = new ResizeObserver(onResize);
|
|
825
|
-
resizeObserver.observe(document.documentElement);
|
|
826
|
-
} else {
|
|
827
|
-
window.addEventListener("resize", onResize);
|
|
828
|
-
}
|
|
829
|
-
window.addEventListener("orientationchange", onResize);
|
|
830
|
-
const onVisibility = () => {
|
|
831
|
-
if (deps.isDestroyed()) return;
|
|
832
|
-
if (document.hidden) deps.cancelInFlight();
|
|
833
|
-
};
|
|
834
|
-
document.addEventListener("visibilitychange", onVisibility);
|
|
835
|
-
return () => {
|
|
836
|
-
resizeObserver?.disconnect();
|
|
837
|
-
window.removeEventListener("resize", onResize);
|
|
838
|
-
window.removeEventListener("orientationchange", onResize);
|
|
839
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
// src/core/features/fit-observer.ts
|
|
844
|
-
var contentTargets = (scroller) => {
|
|
845
|
-
if (!scroller) return [];
|
|
846
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
847
|
-
const out = [];
|
|
848
|
-
for (const child2 of Array.from(scroller.children)) {
|
|
849
|
-
if (hasSlot && child2 instanceof HTMLSlotElement) {
|
|
850
|
-
for (const el of child2.assignedElements()) out.push(el);
|
|
851
|
-
} else {
|
|
852
|
-
out.push(child2);
|
|
445
|
+
|
|
446
|
+
// src/core/features/fit-observer.ts
|
|
447
|
+
var contentTargets = (scroller) => {
|
|
448
|
+
if (!scroller) return [];
|
|
449
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
450
|
+
const out = [];
|
|
451
|
+
for (const child2 of Array.from(scroller.children)) {
|
|
452
|
+
if (hasSlot && child2 instanceof HTMLSlotElement) {
|
|
453
|
+
for (const el of child2.assignedElements()) out.push(el);
|
|
454
|
+
} else {
|
|
455
|
+
out.push(child2);
|
|
853
456
|
}
|
|
854
457
|
}
|
|
855
458
|
return out;
|
|
@@ -1691,6 +1294,52 @@ function resolveAnimationPreset(animation) {
|
|
|
1691
1294
|
}
|
|
1692
1295
|
}
|
|
1693
1296
|
|
|
1297
|
+
// src/core/animation/waapi-settle.ts
|
|
1298
|
+
var SIM_HZ = 240;
|
|
1299
|
+
var SAMPLE_STRIDE = 4;
|
|
1300
|
+
var MAX_SIM_MS = 3e3;
|
|
1301
|
+
function sampleSpringSettle(from, to, velocityPxPerS, config) {
|
|
1302
|
+
const cfg = { ...DEFAULT_SPRING, ...config };
|
|
1303
|
+
const subDt = 1 / SIM_HZ;
|
|
1304
|
+
const stepMs = SAMPLE_STRIDE / SIM_HZ * 1e3;
|
|
1305
|
+
const maxSteps = Math.ceil(MAX_SIM_MS / 1e3 * SIM_HZ);
|
|
1306
|
+
const values = [from];
|
|
1307
|
+
let x = from;
|
|
1308
|
+
let v = velocityPxPerS;
|
|
1309
|
+
for (let i = 1; i <= maxSteps; i += 1) {
|
|
1310
|
+
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1311
|
+
v += force / cfg.mass * subDt;
|
|
1312
|
+
x += v * subDt;
|
|
1313
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1314
|
+
values.push(to);
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
if (i % SAMPLE_STRIDE === 0) values.push(x);
|
|
1318
|
+
const atRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1319
|
+
if (atRest) break;
|
|
1320
|
+
}
|
|
1321
|
+
if (values[values.length - 1] !== to) values.push(to);
|
|
1322
|
+
return {
|
|
1323
|
+
values,
|
|
1324
|
+
stepMs,
|
|
1325
|
+
durationMs: (values.length - 1) * stepMs
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function sampleTweenSettle(from, to, durationMs, easing) {
|
|
1329
|
+
const count = Math.max(2, Math.min(60, Math.round(durationMs / 16)));
|
|
1330
|
+
const values = [];
|
|
1331
|
+
for (let i = 0; i <= count; i += 1) {
|
|
1332
|
+
const t = i / count;
|
|
1333
|
+
values.push(from + (to - from) * easing(t));
|
|
1334
|
+
}
|
|
1335
|
+
values[values.length - 1] = to;
|
|
1336
|
+
return {
|
|
1337
|
+
values,
|
|
1338
|
+
stepMs: durationMs / count,
|
|
1339
|
+
durationMs
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1694
1343
|
// src/core/controllers/animation-runner.ts
|
|
1695
1344
|
var DEFAULT_DURATION2 = 220;
|
|
1696
1345
|
var VELOCITY_PX_PER_S = 1e3;
|
|
@@ -1701,6 +1350,10 @@ var AnimationRunner = class {
|
|
|
1701
1350
|
__publicField(this, "applySizeFn");
|
|
1702
1351
|
__publicField(this, "getSize");
|
|
1703
1352
|
__publicField(this, "isDragging");
|
|
1353
|
+
__publicField(this, "applyAux");
|
|
1354
|
+
__publicField(this, "getTransformFor");
|
|
1355
|
+
__publicField(this, "settleWaapi");
|
|
1356
|
+
__publicField(this, "currentWaapi", null);
|
|
1704
1357
|
__publicField(this, "animationKind");
|
|
1705
1358
|
__publicField(this, "springConfig");
|
|
1706
1359
|
__publicField(this, "duration");
|
|
@@ -1716,6 +1369,9 @@ var AnimationRunner = class {
|
|
|
1716
1369
|
this.applySizeFn = deps.applySize;
|
|
1717
1370
|
this.getSize = deps.getSize;
|
|
1718
1371
|
this.isDragging = deps.isDragging;
|
|
1372
|
+
this.applyAux = deps.applyAux;
|
|
1373
|
+
this.getTransformFor = deps.getTransformFor;
|
|
1374
|
+
this.settleWaapi = opts.settleAnimation === "waapi";
|
|
1719
1375
|
const preset = resolveAnimationPreset(opts.animation);
|
|
1720
1376
|
this.animationKind = preset.kind;
|
|
1721
1377
|
this.duration = opts.duration ?? preset.duration ?? DEFAULT_DURATION2;
|
|
@@ -1740,11 +1396,20 @@ var AnimationRunner = class {
|
|
|
1740
1396
|
}
|
|
1741
1397
|
}
|
|
1742
1398
|
get isAnimating() {
|
|
1743
|
-
return this.currentTween !== null || this.currentSpring !== null;
|
|
1399
|
+
return this.currentTween !== null || this.currentSpring !== null || this.currentWaapi !== null;
|
|
1744
1400
|
}
|
|
1745
1401
|
cancel() {
|
|
1746
1402
|
this.currentTween?.cancel();
|
|
1747
1403
|
this.currentSpring?.cancel();
|
|
1404
|
+
if (this.currentWaapi) {
|
|
1405
|
+
const entry = this.currentWaapi;
|
|
1406
|
+
this.currentWaapi = null;
|
|
1407
|
+
entry.stop();
|
|
1408
|
+
try {
|
|
1409
|
+
entry.anim.cancel();
|
|
1410
|
+
} catch {
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1748
1413
|
}
|
|
1749
1414
|
async animateTo(target, velocityPxPerMs) {
|
|
1750
1415
|
if (target === this.getSize()) {
|
|
@@ -1763,6 +1428,27 @@ var AnimationRunner = class {
|
|
|
1763
1428
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1764
1429
|
return;
|
|
1765
1430
|
}
|
|
1431
|
+
if (this.settleWaapi && this.applyAux && this.getTransformFor && typeof this.element.animate === "function") {
|
|
1432
|
+
const samples = this.animationKind === "spring" ? sampleSpringSettle(
|
|
1433
|
+
this.getSize(),
|
|
1434
|
+
target,
|
|
1435
|
+
velocityPxPerMs * VELOCITY_PX_PER_S,
|
|
1436
|
+
this.springConfig
|
|
1437
|
+
) : sampleTweenSettle(
|
|
1438
|
+
this.getSize(),
|
|
1439
|
+
target,
|
|
1440
|
+
this.duration,
|
|
1441
|
+
this.easing
|
|
1442
|
+
);
|
|
1443
|
+
if (samples.values.length >= 2 && samples.durationMs > 0) {
|
|
1444
|
+
await this.runWaapiSettle(samples, target);
|
|
1445
|
+
if (!this.isAnimating) {
|
|
1446
|
+
this.getRootEl()?.removeAttribute("data-animating");
|
|
1447
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1448
|
+
}
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1766
1452
|
if (this.animationKind === "spring") {
|
|
1767
1453
|
const spring = runSpring({
|
|
1768
1454
|
from: this.getSize(),
|
|
@@ -1791,15 +1477,70 @@ var AnimationRunner = class {
|
|
|
1791
1477
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1792
1478
|
}
|
|
1793
1479
|
}
|
|
1480
|
+
async runWaapiSettle(samples, target) {
|
|
1481
|
+
const applyAux = this.applyAux;
|
|
1482
|
+
const getTransformFor = this.getTransformFor;
|
|
1483
|
+
const frames = samples.values.map((v) => ({
|
|
1484
|
+
transform: getTransformFor(v)
|
|
1485
|
+
}));
|
|
1486
|
+
const anim = this.element.animate(frames, {
|
|
1487
|
+
duration: samples.durationMs,
|
|
1488
|
+
easing: "linear",
|
|
1489
|
+
fill: "forwards"
|
|
1490
|
+
});
|
|
1491
|
+
let stopped = false;
|
|
1492
|
+
let auxRaf = 0;
|
|
1493
|
+
const start = performance.now();
|
|
1494
|
+
const lastIdx = samples.values.length - 1;
|
|
1495
|
+
const auxTick = () => {
|
|
1496
|
+
if (stopped) return;
|
|
1497
|
+
const elapsed = performance.now() - start;
|
|
1498
|
+
const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
|
|
1499
|
+
applyAux(samples.values[idx]);
|
|
1500
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1501
|
+
};
|
|
1502
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1503
|
+
const entry = {
|
|
1504
|
+
anim,
|
|
1505
|
+
stop: () => {
|
|
1506
|
+
stopped = true;
|
|
1507
|
+
cancelAnimationFrame(auxRaf);
|
|
1508
|
+
}
|
|
1509
|
+
};
|
|
1510
|
+
this.currentWaapi = entry;
|
|
1511
|
+
try {
|
|
1512
|
+
await anim.finished;
|
|
1513
|
+
} catch {
|
|
1514
|
+
}
|
|
1515
|
+
entry.stop();
|
|
1516
|
+
const wasCurrent = this.currentWaapi === entry;
|
|
1517
|
+
if (wasCurrent) this.currentWaapi = null;
|
|
1518
|
+
if (wasCurrent && anim.playState === "finished") {
|
|
1519
|
+
this.applySizeFn(target);
|
|
1520
|
+
try {
|
|
1521
|
+
anim.cancel();
|
|
1522
|
+
} catch {
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1794
1526
|
destroy() {
|
|
1795
1527
|
this.detachReducedMotion?.();
|
|
1796
1528
|
this.detachReducedMotion = null;
|
|
1797
1529
|
this.currentTween = null;
|
|
1798
1530
|
this.currentSpring = null;
|
|
1531
|
+
if (this.currentWaapi) {
|
|
1532
|
+
const entry = this.currentWaapi;
|
|
1533
|
+
this.currentWaapi = null;
|
|
1534
|
+
entry.stop();
|
|
1535
|
+
try {
|
|
1536
|
+
entry.anim.cancel();
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1799
1540
|
}
|
|
1800
1541
|
};
|
|
1801
1542
|
|
|
1802
|
-
// src/core/lifecycle/
|
|
1543
|
+
// src/core/lifecycle/focus-trap.ts
|
|
1803
1544
|
var FOCUSABLE = [
|
|
1804
1545
|
"a[href]",
|
|
1805
1546
|
"area[href]",
|
|
@@ -1917,7 +1658,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1917
1658
|
};
|
|
1918
1659
|
};
|
|
1919
1660
|
|
|
1920
|
-
// src/core/lifecycle/
|
|
1661
|
+
// src/core/lifecycle/scroll-lock.ts
|
|
1921
1662
|
var lockCount = 0;
|
|
1922
1663
|
var savedStyles = null;
|
|
1923
1664
|
var lockBodyScroll = () => {
|
|
@@ -2099,30 +1840,44 @@ var SampleRing = class {
|
|
|
2099
1840
|
this.size = 0;
|
|
2100
1841
|
}
|
|
2101
1842
|
};
|
|
2102
|
-
var installGestures = (handle, mode, callbacks) => {
|
|
1843
|
+
var installGestures = (handle, mode, callbacks, options = {}) => {
|
|
2103
1844
|
let activePointerId = null;
|
|
2104
1845
|
let activePointerType = "touch";
|
|
2105
1846
|
let startCoord = 0;
|
|
2106
1847
|
let lastCoord = 0;
|
|
1848
|
+
let pendingStart = false;
|
|
2107
1849
|
const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
|
|
2108
1850
|
const MAX_SAMPLES = 32;
|
|
2109
1851
|
const samples = new SampleRing(MAX_SAMPLES);
|
|
2110
1852
|
const axis = isAxisVertical(mode) ? "Y" : "X";
|
|
2111
1853
|
const sign = mode === "bottom" || mode === "right" ? -1 : 1;
|
|
2112
1854
|
const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
|
|
1855
|
+
const capture = (pointerId) => {
|
|
1856
|
+
try {
|
|
1857
|
+
handle.setPointerCapture(pointerId);
|
|
1858
|
+
} catch {
|
|
1859
|
+
}
|
|
1860
|
+
};
|
|
1861
|
+
const releaseTracking = () => {
|
|
1862
|
+
activePointerId = null;
|
|
1863
|
+
pendingStart = false;
|
|
1864
|
+
samples.reset();
|
|
1865
|
+
};
|
|
2113
1866
|
const onPointerDown = (e) => {
|
|
2114
1867
|
if (activePointerId !== null) return;
|
|
2115
1868
|
if (e.button !== void 0 && e.button !== 0) return;
|
|
1869
|
+
if (options.shouldStart && !options.shouldStart(e)) return;
|
|
2116
1870
|
activePointerId = e.pointerId;
|
|
2117
1871
|
activePointerType = e.pointerType || "touch";
|
|
2118
1872
|
startCoord = coordOf(e);
|
|
2119
1873
|
lastCoord = startCoord;
|
|
2120
1874
|
samples.reset();
|
|
2121
1875
|
samples.push(e.timeStamp, startCoord);
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
1876
|
+
if (options.deferStart) {
|
|
1877
|
+
pendingStart = true;
|
|
1878
|
+
return;
|
|
2125
1879
|
}
|
|
1880
|
+
capture(e.pointerId);
|
|
2126
1881
|
callbacks.onStart(startCoord, activePointerType);
|
|
2127
1882
|
};
|
|
2128
1883
|
const onPointerMove = (e) => {
|
|
@@ -2130,6 +1885,22 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2130
1885
|
const coord = coordOf(e);
|
|
2131
1886
|
const rawDelta = coord - startCoord;
|
|
2132
1887
|
const delta = rawDelta * sign;
|
|
1888
|
+
if (pendingStart) {
|
|
1889
|
+
const verdict = options.deferStart(e, delta);
|
|
1890
|
+
if (verdict === false) {
|
|
1891
|
+
releaseTracking();
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
if (verdict !== true) return;
|
|
1895
|
+
pendingStart = false;
|
|
1896
|
+
startCoord = coord;
|
|
1897
|
+
lastCoord = coord;
|
|
1898
|
+
samples.reset();
|
|
1899
|
+
samples.push(e.timeStamp, coord);
|
|
1900
|
+
capture(e.pointerId);
|
|
1901
|
+
callbacks.onStart(startCoord, activePointerType);
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
2133
1904
|
lastCoord = coord;
|
|
2134
1905
|
samples.push(e.timeStamp, coord);
|
|
2135
1906
|
const cutoff = e.timeStamp - VELOCITY_WINDOW_MS(activePointerType);
|
|
@@ -2138,6 +1909,10 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2138
1909
|
};
|
|
2139
1910
|
const finishGesture = (e) => {
|
|
2140
1911
|
if (e.pointerId !== activePointerId) return;
|
|
1912
|
+
if (pendingStart) {
|
|
1913
|
+
releaseTracking();
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
2141
1916
|
const rawDelta = lastCoord - startCoord;
|
|
2142
1917
|
const delta = rawDelta * sign;
|
|
2143
1918
|
let velocity = 0;
|
|
@@ -2160,22 +1935,26 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2160
1935
|
};
|
|
2161
1936
|
const onPointerCancel = (e) => {
|
|
2162
1937
|
if (e.pointerId !== activePointerId) return;
|
|
2163
|
-
|
|
2164
|
-
|
|
1938
|
+
const wasPending = pendingStart;
|
|
1939
|
+
releaseTracking();
|
|
1940
|
+
if (wasPending) return;
|
|
2165
1941
|
callbacks.onCancel?.();
|
|
2166
1942
|
};
|
|
2167
1943
|
handle.addEventListener("pointerdown", onPointerDown);
|
|
2168
1944
|
handle.addEventListener("pointermove", onPointerMove);
|
|
2169
1945
|
handle.addEventListener("pointerup", finishGesture);
|
|
2170
1946
|
handle.addEventListener("pointercancel", onPointerCancel);
|
|
1947
|
+
const managesTouchAction = options.manageTouchAction !== false;
|
|
2171
1948
|
const prevTouchAction = handle.style.touchAction;
|
|
2172
|
-
|
|
1949
|
+
if (managesTouchAction) {
|
|
1950
|
+
handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
|
|
1951
|
+
}
|
|
2173
1952
|
return () => {
|
|
2174
1953
|
handle.removeEventListener("pointerdown", onPointerDown);
|
|
2175
1954
|
handle.removeEventListener("pointermove", onPointerMove);
|
|
2176
1955
|
handle.removeEventListener("pointerup", finishGesture);
|
|
2177
1956
|
handle.removeEventListener("pointercancel", onPointerCancel);
|
|
2178
|
-
handle.style.touchAction = prevTouchAction;
|
|
1957
|
+
if (managesTouchAction) handle.style.touchAction = prevTouchAction;
|
|
2179
1958
|
if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
|
|
2180
1959
|
handle.releasePointerCapture(activePointerId);
|
|
2181
1960
|
}
|
|
@@ -2294,7 +2073,7 @@ var GestureController = class {
|
|
|
2294
2073
|
const restoreTo = this.dragStartSize;
|
|
2295
2074
|
void this.deps.animateTo(restoreTo, 0);
|
|
2296
2075
|
}
|
|
2297
|
-
});
|
|
2076
|
+
}, this.deps.gestureOptions);
|
|
2298
2077
|
return this.detach;
|
|
2299
2078
|
}
|
|
2300
2079
|
forceClearDragState() {
|
|
@@ -2306,6 +2085,41 @@ var GestureController = class {
|
|
|
2306
2085
|
}
|
|
2307
2086
|
};
|
|
2308
2087
|
|
|
2088
|
+
// src/core/primitives/drag-zones.ts
|
|
2089
|
+
var DRAG_ZONE_SELECTOR = "[data-bs-drag]";
|
|
2090
|
+
var NO_DRAG_SELECTOR = "[data-bs-no-drag]";
|
|
2091
|
+
var asElement = (target) => {
|
|
2092
|
+
const candidate = target;
|
|
2093
|
+
return candidate && typeof candidate.closest === "function" ? candidate : null;
|
|
2094
|
+
};
|
|
2095
|
+
function isDragAllowedFrom(target, mode) {
|
|
2096
|
+
const el = asElement(target);
|
|
2097
|
+
if (!el) return mode !== "zones";
|
|
2098
|
+
if (el.closest(NO_DRAG_SELECTOR)) return false;
|
|
2099
|
+
if (mode === "zones") return el.closest(DRAG_ZONE_SELECTOR) !== null;
|
|
2100
|
+
return true;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
// src/core/primitives/content-gesture.ts
|
|
2104
|
+
var CONTENT_DRAG_SLOP = 6;
|
|
2105
|
+
function decideContentGesture(input) {
|
|
2106
|
+
const slop = input.slop ?? CONTENT_DRAG_SLOP;
|
|
2107
|
+
if (Math.abs(input.delta) < slop) return "pending";
|
|
2108
|
+
if (input.scrollTop > 0) return "scroll";
|
|
2109
|
+
if (input.delta > 0 && input.atMaxSnap) return "scroll";
|
|
2110
|
+
return "drag";
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
// src/core/primitives/touch-scroll-guard.ts
|
|
2114
|
+
function installTouchScrollGuard(surface, isDragging) {
|
|
2115
|
+
const onTouchMove = (e) => {
|
|
2116
|
+
if (!isDragging()) return;
|
|
2117
|
+
if (e.cancelable) e.preventDefault();
|
|
2118
|
+
};
|
|
2119
|
+
surface.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
2120
|
+
return () => surface.removeEventListener("touchmove", onTouchMove);
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2309
2123
|
// src/core/primitives/aria-slider-writer.ts
|
|
2310
2124
|
var AriaSliderWriter = class {
|
|
2311
2125
|
constructor(handle, mode) {
|
|
@@ -2652,7 +2466,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2652
2466
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2653
2467
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2654
2468
|
if (opts.persistKey) {
|
|
2655
|
-
const restored =
|
|
2469
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2656
2470
|
if (restored && initialAllowed.includes(restored)) {
|
|
2657
2471
|
initialId = restored;
|
|
2658
2472
|
}
|
|
@@ -2661,6 +2475,8 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2661
2475
|
mode: opts.mode ?? "bottom",
|
|
2662
2476
|
flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
|
|
2663
2477
|
dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
|
|
2478
|
+
dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
|
|
2479
|
+
dragFromContent: opts.dragFromContent ?? true,
|
|
2664
2480
|
rubberBandEnabled: opts.rubberBand ?? true,
|
|
2665
2481
|
closeOnBack: opts.closeOnBack ?? false,
|
|
2666
2482
|
persistent: opts.persistent ?? false,
|
|
@@ -2683,6 +2499,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2683
2499
|
},
|
|
2684
2500
|
animation: {
|
|
2685
2501
|
animation: opts.animation,
|
|
2502
|
+
settleAnimation: opts.settleAnimation,
|
|
2686
2503
|
duration: opts.duration,
|
|
2687
2504
|
easing: opts.easing,
|
|
2688
2505
|
spring: opts.spring,
|
|
@@ -2700,6 +2517,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2700
2517
|
}
|
|
2701
2518
|
};
|
|
2702
2519
|
}
|
|
2520
|
+
var readPersistedIdSafe = (key) => {
|
|
2521
|
+
if (typeof window === "undefined") return null;
|
|
2522
|
+
if (typeof localStorage === "undefined") return null;
|
|
2523
|
+
try {
|
|
2524
|
+
return localStorage.getItem(key);
|
|
2525
|
+
} catch {
|
|
2526
|
+
return null;
|
|
2527
|
+
}
|
|
2528
|
+
};
|
|
2703
2529
|
|
|
2704
2530
|
// src/core/primitives/teardown-stack.ts
|
|
2705
2531
|
var TeardownStack = class {
|
|
@@ -2722,9 +2548,9 @@ var TeardownStack = class {
|
|
|
2722
2548
|
}
|
|
2723
2549
|
};
|
|
2724
2550
|
|
|
2725
|
-
// src/core/
|
|
2551
|
+
// src/core/BottomSheetCore.ts
|
|
2726
2552
|
var HAPTIC_DURATION_MS = 8;
|
|
2727
|
-
var
|
|
2553
|
+
var BottomSheetCore = class {
|
|
2728
2554
|
constructor(opts) {
|
|
2729
2555
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
2730
2556
|
__publicField(this, "element");
|
|
@@ -2736,6 +2562,8 @@ var BottomSheetEngine = class {
|
|
|
2736
2562
|
__publicField(this, "mode");
|
|
2737
2563
|
__publicField(this, "flickVelocity");
|
|
2738
2564
|
__publicField(this, "dragThreshold");
|
|
2565
|
+
__publicField(this, "dragFromMode");
|
|
2566
|
+
__publicField(this, "dragFromContentDefault");
|
|
2739
2567
|
__publicField(this, "rubberBandEnabled");
|
|
2740
2568
|
__publicField(this, "scrim");
|
|
2741
2569
|
__publicField(this, "aria");
|
|
@@ -2753,8 +2581,11 @@ var BottomSheetEngine = class {
|
|
|
2753
2581
|
__publicField(this, "activeId");
|
|
2754
2582
|
__publicField(this, "size", 0);
|
|
2755
2583
|
__publicField(this, "gesture");
|
|
2584
|
+
__publicField(this, "contentGesture");
|
|
2585
|
+
__publicField(this, "detachSheetGesture", null);
|
|
2756
2586
|
__publicField(this, "rootEl", null);
|
|
2757
2587
|
__publicField(this, "destroyed", false);
|
|
2588
|
+
__publicField(this, "restClosed", false);
|
|
2758
2589
|
__publicField(this, "currentViewTransition", null);
|
|
2759
2590
|
__publicField(this, "currentAbort", new AbortController());
|
|
2760
2591
|
__publicField(this, "sizeWriteSentinel", new WriteSentinel());
|
|
@@ -2785,6 +2616,8 @@ var BottomSheetEngine = class {
|
|
|
2785
2616
|
__publicField(this, "stackEffectPrimed", false);
|
|
2786
2617
|
__publicField(this, "fitDeps");
|
|
2787
2618
|
__publicField(this, "transformTemplate");
|
|
2619
|
+
__publicField(this, "featureList", []);
|
|
2620
|
+
__publicField(this, "featureCtx");
|
|
2788
2621
|
const resolved = resolveEngineOptions(opts, {
|
|
2789
2622
|
shouldApplyInertSiblings: () => {
|
|
2790
2623
|
if (typeof document === "undefined") return false;
|
|
@@ -2805,6 +2638,8 @@ var BottomSheetEngine = class {
|
|
|
2805
2638
|
this.aria = new AriaSliderWriter(this.handle, this.mode);
|
|
2806
2639
|
this.flickVelocity = resolved.flickVelocity;
|
|
2807
2640
|
this.dragThreshold = resolved.dragThreshold;
|
|
2641
|
+
this.dragFromMode = resolved.dragFrom;
|
|
2642
|
+
this.dragFromContentDefault = resolved.dragFromContent;
|
|
2808
2643
|
this.rubberBandEnabled = resolved.rubberBandEnabled;
|
|
2809
2644
|
this.scrim = new ScrimController(
|
|
2810
2645
|
{
|
|
@@ -2831,7 +2666,9 @@ var BottomSheetEngine = class {
|
|
|
2831
2666
|
getRootEl: () => this.rootEl,
|
|
2832
2667
|
applySize: (size) => this.applySize(size),
|
|
2833
2668
|
getSize: () => this.size,
|
|
2834
|
-
isDragging: () => this.
|
|
2669
|
+
isDragging: () => this.isDraggingAny(),
|
|
2670
|
+
applyAux: (size) => this.applySize(size, true),
|
|
2671
|
+
getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
|
|
2835
2672
|
},
|
|
2836
2673
|
resolved.animation
|
|
2837
2674
|
);
|
|
@@ -2854,6 +2691,11 @@ var BottomSheetEngine = class {
|
|
|
2854
2691
|
if (opts.linkedSheets) {
|
|
2855
2692
|
this.linkedSheets = opts.linkedSheets;
|
|
2856
2693
|
}
|
|
2694
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2695
|
+
for (const feature of opts.features ?? []) {
|
|
2696
|
+
byName.set(feature.name, feature);
|
|
2697
|
+
}
|
|
2698
|
+
this.featureList = Array.from(byName.values());
|
|
2857
2699
|
this.activeId = resolved.initialId;
|
|
2858
2700
|
auditVhUsage(this.snapPointsRaw);
|
|
2859
2701
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
@@ -2885,11 +2727,13 @@ var BottomSheetEngine = class {
|
|
|
2885
2727
|
const initial = this.snaps.findById(this.activeId);
|
|
2886
2728
|
if (initial) this.size = initial.size;
|
|
2887
2729
|
this.applySize(this.size);
|
|
2730
|
+
this.setRestClosed(this.size === 0);
|
|
2888
2731
|
this.updateAriaSlider();
|
|
2889
2732
|
this.scrollCache = createScrollCache({
|
|
2890
2733
|
scrollContainer: this.scrollContainer,
|
|
2891
2734
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize()
|
|
2892
2735
|
});
|
|
2736
|
+
this.featureCtx = this.buildFeatureContext(opts.autoCollapseAfter);
|
|
2893
2737
|
this.attach();
|
|
2894
2738
|
this.registerInStack();
|
|
2895
2739
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
@@ -2914,60 +2758,92 @@ var BottomSheetEngine = class {
|
|
|
2914
2758
|
(p) => p.size === "fit" || p.size === "content"
|
|
2915
2759
|
),
|
|
2916
2760
|
isDestroyed: () => this.destroyed,
|
|
2917
|
-
isDragging: () => this.
|
|
2761
|
+
isDragging: () => this.isDraggingAny(),
|
|
2918
2762
|
recompute: () => this.recompute()
|
|
2919
2763
|
})
|
|
2920
2764
|
);
|
|
2921
2765
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2922
2766
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2923
2767
|
this.applyAutoAriaLabelledBy();
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
getSize: () => this.size,
|
|
2929
|
-
close: () => this.close()
|
|
2930
|
-
})
|
|
2931
|
-
);
|
|
2932
|
-
}
|
|
2933
|
-
if (this.persistKey) {
|
|
2934
|
-
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2768
|
+
this.runFeatureStage("post");
|
|
2769
|
+
this.warnOrphanFeatureOptions();
|
|
2770
|
+
if (this.size > 0) {
|
|
2771
|
+
this.handleOpen();
|
|
2935
2772
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
resolveSnap: (id) => this.snaps.findById(id),
|
|
2944
|
-
snapTo: (id) => {
|
|
2945
|
-
void this.snapTo(id);
|
|
2946
|
-
},
|
|
2947
|
-
on: (event, fn) => this.on(event, fn)
|
|
2948
|
-
})
|
|
2949
|
-
);
|
|
2950
|
-
this.teardowns.add(
|
|
2951
|
-
installRoute({
|
|
2773
|
+
}
|
|
2774
|
+
buildFeatureContext(autoCollapseAfter) {
|
|
2775
|
+
return {
|
|
2776
|
+
element: this.element,
|
|
2777
|
+
scrollContainer: this.scrollContainer,
|
|
2778
|
+
sheetId: this.id,
|
|
2779
|
+
options: {
|
|
2952
2780
|
routedTo: this.routedTo,
|
|
2953
2781
|
closeOnBack: this.closeOnBack,
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
this.
|
|
2782
|
+
closeOnRouteChange: this.closeOnRouteChange,
|
|
2783
|
+
persistKey: this.persistKey,
|
|
2784
|
+
autoCollapseAfter
|
|
2785
|
+
},
|
|
2786
|
+
isDestroyed: () => this.destroyed,
|
|
2787
|
+
isDragging: () => this.isDraggingAny(),
|
|
2788
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2789
|
+
isTopSheet: () => this.isTopSheet,
|
|
2790
|
+
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
2791
|
+
getSize: () => this.size,
|
|
2792
|
+
getActiveId: () => this.activeId,
|
|
2793
|
+
getAllowedIds: () => this.snaps.getAllowedIds().slice(),
|
|
2794
|
+
allowedIdsBySize: () => this.allowedIdsBySize(),
|
|
2795
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2796
|
+
resolveSnap: (id) => this.snaps.findById(id),
|
|
2797
|
+
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
2798
|
+
setSize: (size) => {
|
|
2799
|
+
this.size = size;
|
|
2800
|
+
},
|
|
2801
|
+
setMaxAxisSize: (size) => {
|
|
2802
|
+
this.snaps.setMaxAxisSize(size);
|
|
2803
|
+
},
|
|
2804
|
+
applySize: (size) => this.applySize(size),
|
|
2805
|
+
recomputeSnaps: () => this.recomputeSnaps(),
|
|
2806
|
+
newCycle: () => {
|
|
2807
|
+
this.newCycle();
|
|
2808
|
+
},
|
|
2809
|
+
cancelInFlight: () => {
|
|
2810
|
+
this.animation.cancel();
|
|
2811
|
+
},
|
|
2812
|
+
resyncAfterResize: () => this.resyncAfterResize(),
|
|
2813
|
+
snapTo: (id) => {
|
|
2814
|
+
void this.snapTo(id);
|
|
2815
|
+
},
|
|
2816
|
+
close: (reason) => this.close(reason),
|
|
2817
|
+
attachDragSurface: (surface, kind) => this.attachDragSurface(surface, kind),
|
|
2818
|
+
on: (event, fn) => this.on(event, fn),
|
|
2819
|
+
addTeardown: (fn) => this.teardowns.add(fn)
|
|
2820
|
+
};
|
|
2821
|
+
}
|
|
2822
|
+
runFeatureStage(stage) {
|
|
2823
|
+
for (const feature of this.featureList) {
|
|
2824
|
+
if ((feature.stage ?? "post") !== stage) continue;
|
|
2825
|
+
const teardown = feature.install(this.featureCtx);
|
|
2826
|
+
if (teardown) this.teardowns.add(teardown);
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
warnOrphanFeatureOptions() {
|
|
2830
|
+
const names = new Set(this.featureList.map((f) => f.name));
|
|
2831
|
+
if ((this.closeOnBack || this.routedTo !== void 0 || this.closeOnRouteChange) && !names.has("route")) {
|
|
2832
|
+
devWarn(
|
|
2833
|
+
"[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
|
|
2834
|
+
);
|
|
2835
|
+
}
|
|
2836
|
+
if (this.persistKey && !names.has("persist")) {
|
|
2837
|
+
devWarn(
|
|
2838
|
+
"[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
|
|
2839
|
+
);
|
|
2964
2840
|
}
|
|
2965
2841
|
}
|
|
2966
2842
|
get state() {
|
|
2967
2843
|
return {
|
|
2968
2844
|
size: this.size,
|
|
2969
2845
|
activeId: this.activeId,
|
|
2970
|
-
isDragging: this.
|
|
2846
|
+
isDragging: this.isDraggingAny(),
|
|
2971
2847
|
isAnimating: this.animation.isAnimating,
|
|
2972
2848
|
progress: this.computeProgress(this.size)
|
|
2973
2849
|
};
|
|
@@ -3087,9 +2963,16 @@ var BottomSheetEngine = class {
|
|
|
3087
2963
|
progress: this.computeProgress(this.size)
|
|
3088
2964
|
});
|
|
3089
2965
|
if (withHaptic) this.haptic();
|
|
2966
|
+
this.setRestClosed(targetSize === 0);
|
|
3090
2967
|
if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
|
|
3091
2968
|
if (targetSize === 0) this.emitCloseSequence();
|
|
3092
2969
|
}
|
|
2970
|
+
setRestClosed(closed) {
|
|
2971
|
+
if (closed === this.restClosed) return;
|
|
2972
|
+
this.restClosed = closed;
|
|
2973
|
+
if (closed) this.element.setAttribute("data-bs-rest", "closed");
|
|
2974
|
+
else this.element.removeAttribute("data-bs-rest");
|
|
2975
|
+
}
|
|
3093
2976
|
emitOpenSequence(id) {
|
|
3094
2977
|
this.emit("open", { id });
|
|
3095
2978
|
this.handleOpen();
|
|
@@ -3145,6 +3028,20 @@ var BottomSheetEngine = class {
|
|
|
3145
3028
|
if (this.destroyed) return;
|
|
3146
3029
|
this.disableDragFlag = value;
|
|
3147
3030
|
}
|
|
3031
|
+
setDragFromContent(value) {
|
|
3032
|
+
if (this.destroyed) return;
|
|
3033
|
+
this.dragFromContentDefault = value;
|
|
3034
|
+
}
|
|
3035
|
+
setDragFrom(mode) {
|
|
3036
|
+
if (this.destroyed || mode === this.dragFromMode) return;
|
|
3037
|
+
this.gesture?.forceClearDragState();
|
|
3038
|
+
this.detachSheetGesture?.();
|
|
3039
|
+
this.dragFromMode = mode;
|
|
3040
|
+
this.mountSheetGesture();
|
|
3041
|
+
}
|
|
3042
|
+
getDragFrom() {
|
|
3043
|
+
return this.dragFromMode;
|
|
3044
|
+
}
|
|
3148
3045
|
isTop() {
|
|
3149
3046
|
return this.isTopSheet;
|
|
3150
3047
|
}
|
|
@@ -3299,12 +3196,24 @@ var BottomSheetEngine = class {
|
|
|
3299
3196
|
auditVhUsage(points);
|
|
3300
3197
|
this.auditDuplicateSnapIds(points);
|
|
3301
3198
|
this.snaps.setRaw(points);
|
|
3302
|
-
if (allowed)
|
|
3199
|
+
if (allowed) {
|
|
3200
|
+
this.snaps.setAllowedIds(allowed);
|
|
3201
|
+
} else {
|
|
3202
|
+
const present = this.snaps.getResolvedSnaps().map((s) => s.id);
|
|
3203
|
+
const kept = this.snaps.getAllowedIds().filter((id) => present.includes(id));
|
|
3204
|
+
this.snaps.setAllowedIds(kept.length ? kept : present);
|
|
3205
|
+
}
|
|
3303
3206
|
this.scrollCache.clear();
|
|
3304
3207
|
this.scrim.invalidateOpacityCache();
|
|
3305
3208
|
const current = this.snaps.findById(this.activeId);
|
|
3306
3209
|
if (current) {
|
|
3307
3210
|
this.applySize(current.size);
|
|
3211
|
+
} else {
|
|
3212
|
+
const fallback = this.snaps.getResolvedSnaps().find((s) => this.snaps.getAllowedIds().includes(s.id)) ?? this.snaps.getResolvedSnaps()[0];
|
|
3213
|
+
if (fallback) {
|
|
3214
|
+
this.activeId = fallback.id;
|
|
3215
|
+
this.applySize(fallback.size);
|
|
3216
|
+
}
|
|
3308
3217
|
}
|
|
3309
3218
|
this.updateAriaSlider();
|
|
3310
3219
|
}
|
|
@@ -3314,7 +3223,7 @@ var BottomSheetEngine = class {
|
|
|
3314
3223
|
this.snaps.recompute();
|
|
3315
3224
|
this.maxHeight.clampTo();
|
|
3316
3225
|
this.scrim.invalidateOpacityCache();
|
|
3317
|
-
if (this.
|
|
3226
|
+
if (this.isDraggingAny()) return;
|
|
3318
3227
|
this.healActiveSnap();
|
|
3319
3228
|
}
|
|
3320
3229
|
healActiveSnap() {
|
|
@@ -3336,6 +3245,8 @@ var BottomSheetEngine = class {
|
|
|
3336
3245
|
this.bus.clear();
|
|
3337
3246
|
this.animation.cancel();
|
|
3338
3247
|
this.gesture?.forceClearDragState();
|
|
3248
|
+
this.contentGesture?.forceClearDragState();
|
|
3249
|
+
this.setRestClosed(false);
|
|
3339
3250
|
this.teardowns.drain();
|
|
3340
3251
|
this.scrim.destroy();
|
|
3341
3252
|
this.animation.destroy();
|
|
@@ -3448,11 +3359,12 @@ var BottomSheetEngine = class {
|
|
|
3448
3359
|
const scale = Math.max(1 - depth * 0.04, 0.86);
|
|
3449
3360
|
this.element.style.scale = scale === 1 ? "" : String(scale);
|
|
3450
3361
|
}
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
handle:
|
|
3362
|
+
buildGestureDeps(surface, gestureOptions) {
|
|
3363
|
+
return {
|
|
3364
|
+
handle: surface,
|
|
3454
3365
|
element: this.element,
|
|
3455
3366
|
mode: this.mode,
|
|
3367
|
+
gestureOptions,
|
|
3456
3368
|
getRoot: () => this.rootEl,
|
|
3457
3369
|
getDragContext: () => {
|
|
3458
3370
|
const buf = this.dragContextBuf;
|
|
@@ -3471,8 +3383,88 @@ var BottomSheetEngine = class {
|
|
|
3471
3383
|
settleAfterDrag: (delta, velocity, kind) => this.settleAfterDrag(delta, velocity, kind),
|
|
3472
3384
|
emit: (event, payload) => this.emit(event, payload),
|
|
3473
3385
|
listenerCount: (event) => this.bus.listenerCount(event)
|
|
3386
|
+
};
|
|
3387
|
+
}
|
|
3388
|
+
isContentDragAllowed() {
|
|
3389
|
+
if (this.disableDragFlag) return false;
|
|
3390
|
+
const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
|
|
3391
|
+
return point?.dragFromContent ?? this.dragFromContentDefault;
|
|
3392
|
+
}
|
|
3393
|
+
decideContentDrag(surface, e, delta) {
|
|
3394
|
+
if (this.destroyed) return false;
|
|
3395
|
+
if (e.pointerType === "mouse") return false;
|
|
3396
|
+
if (this.gesture?.isDragging) return false;
|
|
3397
|
+
if (!this.isContentDragAllowed()) return false;
|
|
3398
|
+
if (!isDragAllowedFrom(e.target, "sheet")) return false;
|
|
3399
|
+
const decision = decideContentGesture({
|
|
3400
|
+
delta,
|
|
3401
|
+
scrollTop: surface.scrollTop,
|
|
3402
|
+
atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
|
|
3403
|
+
});
|
|
3404
|
+
if (decision === "pending") return null;
|
|
3405
|
+
return decision === "drag";
|
|
3406
|
+
}
|
|
3407
|
+
attachDragSurface(surface, kind) {
|
|
3408
|
+
if (this.destroyed || kind !== "content") return;
|
|
3409
|
+
if (this.contentGesture) return;
|
|
3410
|
+
const controller = new GestureController(
|
|
3411
|
+
this.buildGestureDeps(surface, {
|
|
3412
|
+
manageTouchAction: false,
|
|
3413
|
+
deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
|
|
3414
|
+
})
|
|
3415
|
+
);
|
|
3416
|
+
this.contentGesture = controller;
|
|
3417
|
+
const detachGestures = controller.install();
|
|
3418
|
+
const detachGuard = installTouchScrollGuard(
|
|
3419
|
+
surface,
|
|
3420
|
+
() => controller.isDragging
|
|
3421
|
+
);
|
|
3422
|
+
return () => {
|
|
3423
|
+
detachGuard();
|
|
3424
|
+
detachGestures();
|
|
3425
|
+
if (this.contentGesture === controller) this.contentGesture = void 0;
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
sheetDragSurface() {
|
|
3429
|
+
return this.dragFromMode === "handle" ? this.handle : this.element;
|
|
3430
|
+
}
|
|
3431
|
+
canStartSheetDrag(e) {
|
|
3432
|
+
if (this.contentGesture?.isDragging) return false;
|
|
3433
|
+
const target = e.target;
|
|
3434
|
+
const scoped = typeof target?.closest === "function";
|
|
3435
|
+
if (scoped && target.closest(NO_DRAG_SELECTOR)) return false;
|
|
3436
|
+
if (this.handle !== this.element && scoped && this.handle.contains(target)) {
|
|
3437
|
+
return true;
|
|
3438
|
+
}
|
|
3439
|
+
if (!isDragAllowedFrom(e.target, this.dragFromMode)) return false;
|
|
3440
|
+
if (this.dragFromMode === "handle") return true;
|
|
3441
|
+
if (this.scrollContainer && scoped && this.scrollContainer.contains(target) && !target.closest(DRAG_ZONE_SELECTOR)) {
|
|
3442
|
+
return false;
|
|
3443
|
+
}
|
|
3444
|
+
return true;
|
|
3445
|
+
}
|
|
3446
|
+
mountSheetGesture() {
|
|
3447
|
+
const surface = this.sheetDragSurface();
|
|
3448
|
+
const controller = new GestureController(
|
|
3449
|
+
this.buildGestureDeps(surface, {
|
|
3450
|
+
shouldStart: (e) => this.canStartSheetDrag(e),
|
|
3451
|
+
manageTouchAction: this.dragFromMode === "handle"
|
|
3452
|
+
})
|
|
3453
|
+
);
|
|
3454
|
+
this.gesture = controller;
|
|
3455
|
+
const detachGestures = controller.install();
|
|
3456
|
+
const detachGuard = this.dragFromMode === "handle" ? null : installTouchScrollGuard(surface, () => controller.isDragging);
|
|
3457
|
+
this.detachSheetGesture = () => {
|
|
3458
|
+
detachGuard?.();
|
|
3459
|
+
detachGestures();
|
|
3460
|
+
};
|
|
3461
|
+
}
|
|
3462
|
+
attach() {
|
|
3463
|
+
this.mountSheetGesture();
|
|
3464
|
+
this.teardowns.add(() => {
|
|
3465
|
+
this.detachSheetGesture?.();
|
|
3466
|
+
this.detachSheetGesture = null;
|
|
3474
3467
|
});
|
|
3475
|
-
this.teardowns.add(this.gesture.install());
|
|
3476
3468
|
try {
|
|
3477
3469
|
this.attachFeatures();
|
|
3478
3470
|
} catch (err) {
|
|
@@ -3503,24 +3495,13 @@ var BottomSheetEngine = class {
|
|
|
3503
3495
|
}
|
|
3504
3496
|
}
|
|
3505
3497
|
attachFeatures() {
|
|
3506
|
-
|
|
3507
|
-
this.teardowns.add(installContentSwipe({
|
|
3508
|
-
container: this.scrollContainer,
|
|
3509
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3510
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3511
|
-
getAllowedIds: () => this.allowedIdsBySize(),
|
|
3512
|
-
getActiveId: () => this.activeId,
|
|
3513
|
-
snapTo: (id) => {
|
|
3514
|
-
void this.snapTo(id);
|
|
3515
|
-
}
|
|
3516
|
-
}));
|
|
3517
|
-
}
|
|
3498
|
+
this.runFeatureStage("attach");
|
|
3518
3499
|
if (typeof window !== "undefined") {
|
|
3519
3500
|
this.teardowns.add(installResizeObserver({
|
|
3520
3501
|
element: this.element,
|
|
3521
3502
|
getMode: () => this.mode,
|
|
3522
3503
|
isDestroyed: () => this.destroyed,
|
|
3523
|
-
isDragging: () => this.
|
|
3504
|
+
isDragging: () => this.isDraggingAny(),
|
|
3524
3505
|
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3525
3506
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3526
3507
|
getSize: () => this.size,
|
|
@@ -3554,31 +3535,6 @@ var BottomSheetEngine = class {
|
|
|
3554
3535
|
() => document.removeEventListener("keydown", onKey)
|
|
3555
3536
|
);
|
|
3556
3537
|
}
|
|
3557
|
-
this.teardowns.add(installVisualViewport({
|
|
3558
|
-
element: this.element,
|
|
3559
|
-
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
3560
|
-
isDestroyed: () => this.destroyed,
|
|
3561
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3562
|
-
recomputeSnaps: () => this.recomputeSnaps(),
|
|
3563
|
-
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3564
|
-
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3565
|
-
getSize: () => this.size,
|
|
3566
|
-
setMaxAxisSize: (size) => {
|
|
3567
|
-
this.snaps.setMaxAxisSize(size);
|
|
3568
|
-
},
|
|
3569
|
-
setSize: (size) => {
|
|
3570
|
-
this.size = size;
|
|
3571
|
-
},
|
|
3572
|
-
applySize: (size) => this.applySize(size),
|
|
3573
|
-
cancelInFlight: () => {
|
|
3574
|
-
this.animation.cancel();
|
|
3575
|
-
},
|
|
3576
|
-
newCycle: () => {
|
|
3577
|
-
this.newCycle();
|
|
3578
|
-
},
|
|
3579
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3580
|
-
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3581
|
-
}));
|
|
3582
3538
|
}
|
|
3583
3539
|
this.teardowns.add(installSliderKeyboard({
|
|
3584
3540
|
handle: this.handle,
|
|
@@ -3619,123 +3575,591 @@ var BottomSheetEngine = class {
|
|
|
3619
3575
|
}
|
|
3620
3576
|
return;
|
|
3621
3577
|
}
|
|
3622
|
-
const previousSize = this.size;
|
|
3623
|
-
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
3624
|
-
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
3625
|
-
this.activeId = target.id;
|
|
3626
|
-
if (previousSnapSize === 0 && target.size > 0) {
|
|
3627
|
-
this.opening = true;
|
|
3628
|
-
sheetStack.promote(this.id);
|
|
3578
|
+
const previousSize = this.size;
|
|
3579
|
+
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
3580
|
+
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
3581
|
+
this.activeId = target.id;
|
|
3582
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
3583
|
+
this.opening = true;
|
|
3584
|
+
sheetStack.promote(this.id);
|
|
3585
|
+
}
|
|
3586
|
+
const settleCap = this.snaps.getMaxAxisSize();
|
|
3587
|
+
const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
|
|
3588
|
+
this.allowOvershoot = true;
|
|
3589
|
+
void this.animation.animateTo(settleSize, velocity).then(() => {
|
|
3590
|
+
if (signal.aborted) return;
|
|
3591
|
+
this.allowOvershoot = false;
|
|
3592
|
+
this.opening = false;
|
|
3593
|
+
this.completeSnap(
|
|
3594
|
+
target.id,
|
|
3595
|
+
target.size,
|
|
3596
|
+
previousSize,
|
|
3597
|
+
previousSnapSize === 0,
|
|
3598
|
+
true
|
|
3599
|
+
);
|
|
3600
|
+
});
|
|
3601
|
+
}
|
|
3602
|
+
isDraggingAny() {
|
|
3603
|
+
return (this.gesture?.isDragging ?? false) || (this.contentGesture?.isDragging ?? false);
|
|
3604
|
+
}
|
|
3605
|
+
clearWillChangeIfIdle() {
|
|
3606
|
+
if (this.animation.isAnimating || this.isDraggingAny()) return;
|
|
3607
|
+
this.element.style.willChange = "";
|
|
3608
|
+
}
|
|
3609
|
+
haptic() {
|
|
3610
|
+
if (typeof navigator !== "undefined" && "vibrate" in navigator) {
|
|
3611
|
+
try {
|
|
3612
|
+
navigator.vibrate(HAPTIC_DURATION_MS);
|
|
3613
|
+
} catch {
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
applySize(size, skipTransform = false) {
|
|
3618
|
+
const cap = this.snaps.getMaxAxisSize();
|
|
3619
|
+
const clamped = cap > 0 && size > cap && !this.isDraggingAny() && !this.allowOvershoot ? cap : size;
|
|
3620
|
+
this.size = clamped;
|
|
3621
|
+
if (clamped > 0) this.setRestClosed(false);
|
|
3622
|
+
const offset = cap - clamped;
|
|
3623
|
+
const style = this.element.style;
|
|
3624
|
+
if (!skipTransform) style.transform = this.transformTemplate(offset);
|
|
3625
|
+
if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
|
|
3626
|
+
style.setProperty("--bs-size", `${clamped}px`);
|
|
3627
|
+
if (this.scrimParent) {
|
|
3628
|
+
this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
|
|
3629
|
+
}
|
|
3630
|
+
if (this.anchorHost && this.anchorHost !== this.scrimParent) {
|
|
3631
|
+
this.anchorHost.style.setProperty("--bs-size", `${clamped}px`);
|
|
3632
|
+
}
|
|
3633
|
+
if (this.rootEl && this.rootEl !== this.scrimParent && this.rootEl !== this.anchorHost) {
|
|
3634
|
+
this.rootEl.style.setProperty("--bs-size", `${clamped}px`);
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
const progress = this.computeProgress(clamped);
|
|
3638
|
+
const progressChanged = this.progressWriteSentinel.shouldWrite(
|
|
3639
|
+
progress,
|
|
3640
|
+
OPACITY_WRITE_EPSILON
|
|
3641
|
+
);
|
|
3642
|
+
if (progressChanged) {
|
|
3643
|
+
style.setProperty("--bs-progress", String(progress));
|
|
3644
|
+
if (this.anchorHost) {
|
|
3645
|
+
this.anchorHost.style.setProperty("--bs-progress", String(progress));
|
|
3646
|
+
}
|
|
3647
|
+
if (this.rootEl && this.rootEl !== this.anchorHost) {
|
|
3648
|
+
this.rootEl.style.setProperty("--bs-progress", String(progress));
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
this.scrim.applyOpacity(progress, progressChanged);
|
|
3652
|
+
if (progressChanged && this.bus.listenerCount("progress") > 0) {
|
|
3653
|
+
this.progressPayload.value = progress;
|
|
3654
|
+
this.progressPayload.size = clamped;
|
|
3655
|
+
this.emit("progress", this.progressPayload);
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
computeProgress(size) {
|
|
3659
|
+
const { min, max } = this.getAllowedRange();
|
|
3660
|
+
const reachableMax = Math.min(max, this.snaps.getMaxAxisSize());
|
|
3661
|
+
if (reachableMax <= min) return 0;
|
|
3662
|
+
return Math.min(Math.max((size - min) / (reachableMax - min), 0), 1);
|
|
3663
|
+
}
|
|
3664
|
+
handleOpen() {
|
|
3665
|
+
sheetStack.promote(this.id);
|
|
3666
|
+
try {
|
|
3667
|
+
this.lifecycle.install();
|
|
3668
|
+
} catch (err) {
|
|
3669
|
+
if (!this.destroyed) this.newCycle();
|
|
3670
|
+
this.handleClose();
|
|
3671
|
+
this.applySize(0);
|
|
3672
|
+
this.activeId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.activeId;
|
|
3673
|
+
this.size = 0;
|
|
3674
|
+
queueMicrotask(() => {
|
|
3675
|
+
throw err;
|
|
3676
|
+
});
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
resyncAfterResize() {
|
|
3680
|
+
if (this.destroyed) return;
|
|
3681
|
+
const target = this.snaps.findById(this.activeId);
|
|
3682
|
+
if (!target) return;
|
|
3683
|
+
this.updateAriaSlider();
|
|
3684
|
+
this.emit("snap", {
|
|
3685
|
+
id: target.id,
|
|
3686
|
+
size: this.size,
|
|
3687
|
+
progress: this.computeProgress(this.size)
|
|
3688
|
+
});
|
|
3689
|
+
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3690
|
+
this.emitOpenSequence(target.id);
|
|
3691
|
+
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3692
|
+
this.emitCloseSequence();
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
handleClose() {
|
|
3696
|
+
this.opening = false;
|
|
3697
|
+
this.lifecycle.release();
|
|
3698
|
+
sheetStack.update();
|
|
3699
|
+
}
|
|
3700
|
+
};
|
|
3701
|
+
|
|
3702
|
+
// src/core/features/history-coordinator.ts
|
|
3703
|
+
var entries = [];
|
|
3704
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3705
|
+
var suppress = 0;
|
|
3706
|
+
var internalDepth = 0;
|
|
3707
|
+
var pendingRebrands = [];
|
|
3708
|
+
var listenerInstalled = false;
|
|
3709
|
+
var patchInstalled = false;
|
|
3710
|
+
var origPushState = null;
|
|
3711
|
+
var origReplaceState = null;
|
|
3712
|
+
var patchedPushState = null;
|
|
3713
|
+
var patchedReplaceState = null;
|
|
3714
|
+
var hasWindow = () => typeof window !== "undefined";
|
|
3715
|
+
var hasHistory = () => typeof history !== "undefined";
|
|
3716
|
+
var brandMarker = (surface) => ({
|
|
3717
|
+
...surface.markerState(),
|
|
3718
|
+
__bs: true
|
|
3719
|
+
});
|
|
3720
|
+
var runInternal = (fn) => {
|
|
3721
|
+
internalDepth += 1;
|
|
3722
|
+
try {
|
|
3723
|
+
fn();
|
|
3724
|
+
} finally {
|
|
3725
|
+
internalDepth -= 1;
|
|
3726
|
+
}
|
|
3727
|
+
};
|
|
3728
|
+
var notifyRouteChange = () => {
|
|
3729
|
+
const snapshot = Array.from(subscribers);
|
|
3730
|
+
for (const fn of snapshot) fn();
|
|
3731
|
+
};
|
|
3732
|
+
var ensureListener = () => {
|
|
3733
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
3734
|
+
window.addEventListener("popstate", onPopState);
|
|
3735
|
+
listenerInstalled = true;
|
|
3736
|
+
};
|
|
3737
|
+
var maybeTeardownListener = () => {
|
|
3738
|
+
if (!listenerInstalled) return;
|
|
3739
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
3740
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
3741
|
+
listenerInstalled = false;
|
|
3742
|
+
};
|
|
3743
|
+
var installPatch = () => {
|
|
3744
|
+
if (patchInstalled || !hasHistory()) return;
|
|
3745
|
+
origPushState = history.pushState;
|
|
3746
|
+
origReplaceState = history.replaceState;
|
|
3747
|
+
patchedPushState = function(...args) {
|
|
3748
|
+
origPushState.apply(this, args);
|
|
3749
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3750
|
+
};
|
|
3751
|
+
patchedReplaceState = function(...args) {
|
|
3752
|
+
origReplaceState.apply(this, args);
|
|
3753
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3754
|
+
};
|
|
3755
|
+
history.pushState = patchedPushState;
|
|
3756
|
+
history.replaceState = patchedReplaceState;
|
|
3757
|
+
patchInstalled = true;
|
|
3758
|
+
};
|
|
3759
|
+
var removePatch = () => {
|
|
3760
|
+
if (!patchInstalled) return;
|
|
3761
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
3762
|
+
history.pushState = origPushState;
|
|
3763
|
+
}
|
|
3764
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
3765
|
+
history.replaceState = origReplaceState;
|
|
3766
|
+
}
|
|
3767
|
+
origPushState = null;
|
|
3768
|
+
origReplaceState = null;
|
|
3769
|
+
patchedPushState = null;
|
|
3770
|
+
patchedReplaceState = null;
|
|
3771
|
+
patchInstalled = false;
|
|
3772
|
+
};
|
|
3773
|
+
function onPopState() {
|
|
3774
|
+
if (suppress > 0) {
|
|
3775
|
+
suppress -= 1;
|
|
3776
|
+
const rebrand = pendingRebrands.shift();
|
|
3777
|
+
if (rebrand) rebrand();
|
|
3778
|
+
maybeTeardownListener();
|
|
3779
|
+
return;
|
|
3780
|
+
}
|
|
3781
|
+
if (entries.length === 0) {
|
|
3782
|
+
notifyRouteChange();
|
|
3783
|
+
maybeTeardownListener();
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3786
|
+
let target = null;
|
|
3787
|
+
let targetIdx = -1;
|
|
3788
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3789
|
+
const entry = entries[i];
|
|
3790
|
+
if (!entry.surface.isOpen()) continue;
|
|
3791
|
+
if (!target) {
|
|
3792
|
+
target = entry;
|
|
3793
|
+
targetIdx = i;
|
|
3794
|
+
}
|
|
3795
|
+
if (entry.surface.isTop()) {
|
|
3796
|
+
target = entry;
|
|
3797
|
+
targetIdx = i;
|
|
3798
|
+
break;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
if (!target) {
|
|
3802
|
+
const removed = entries.pop();
|
|
3803
|
+
if (removed) removed.live = false;
|
|
3804
|
+
maybeTeardownListener();
|
|
3805
|
+
return;
|
|
3806
|
+
}
|
|
3807
|
+
target.live = false;
|
|
3808
|
+
entries.splice(targetIdx, 1);
|
|
3809
|
+
const settled = target;
|
|
3810
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
3811
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
3812
|
+
});
|
|
3813
|
+
maybeTeardownListener();
|
|
3814
|
+
}
|
|
3815
|
+
function restore(entry) {
|
|
3816
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3817
|
+
entry.live = true;
|
|
3818
|
+
runInternal(() => {
|
|
3819
|
+
try {
|
|
3820
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
3821
|
+
} catch {
|
|
3822
|
+
entry.live = false;
|
|
3823
|
+
}
|
|
3824
|
+
});
|
|
3825
|
+
if (entry.live) {
|
|
3826
|
+
entries.push(entry);
|
|
3827
|
+
ensureListener();
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
function pushBackMarker(surface) {
|
|
3831
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
3832
|
+
if (!hasWindow() || !hasHistory()) {
|
|
3833
|
+
return entry;
|
|
3834
|
+
}
|
|
3835
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
3836
|
+
runInternal(() => {
|
|
3837
|
+
try {
|
|
3838
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
3839
|
+
entry.live = true;
|
|
3840
|
+
} catch {
|
|
3841
|
+
entry.live = false;
|
|
3842
|
+
}
|
|
3843
|
+
});
|
|
3844
|
+
if (entry.live) {
|
|
3845
|
+
entries.push(entry);
|
|
3846
|
+
ensureListener();
|
|
3847
|
+
}
|
|
3848
|
+
return entry;
|
|
3849
|
+
}
|
|
3850
|
+
function popBackMarker(handle) {
|
|
3851
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3852
|
+
const entry = handle;
|
|
3853
|
+
const idx = entries.indexOf(entry);
|
|
3854
|
+
if (idx === -1 || !entry.live) return;
|
|
3855
|
+
const last = entries.length - 1;
|
|
3856
|
+
entry.live = false;
|
|
3857
|
+
entries.splice(idx, 1);
|
|
3858
|
+
let rebrand = null;
|
|
3859
|
+
if (idx !== last) {
|
|
3860
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
3861
|
+
const rebrandUrl = entry.priorUrl;
|
|
3862
|
+
rebrand = () => {
|
|
3863
|
+
runInternal(() => {
|
|
3864
|
+
history.replaceState(
|
|
3865
|
+
brandMarker(rebrandSurface),
|
|
3866
|
+
"",
|
|
3867
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
3868
|
+
);
|
|
3869
|
+
});
|
|
3870
|
+
};
|
|
3871
|
+
}
|
|
3872
|
+
pendingRebrands.push(rebrand);
|
|
3873
|
+
suppress += 1;
|
|
3874
|
+
runInternal(() => {
|
|
3875
|
+
try {
|
|
3876
|
+
history.back();
|
|
3877
|
+
} catch {
|
|
3878
|
+
suppress = Math.max(0, suppress - 1);
|
|
3879
|
+
pendingRebrands.pop();
|
|
3880
|
+
}
|
|
3881
|
+
});
|
|
3882
|
+
maybeTeardownListener();
|
|
3883
|
+
}
|
|
3884
|
+
function subscribeRouteChange(fn) {
|
|
3885
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
3886
|
+
};
|
|
3887
|
+
subscribers.add(fn);
|
|
3888
|
+
if (subscribers.size === 1) installPatch();
|
|
3889
|
+
ensureListener();
|
|
3890
|
+
return () => {
|
|
3891
|
+
if (!subscribers.has(fn)) return;
|
|
3892
|
+
subscribers.delete(fn);
|
|
3893
|
+
if (subscribers.size === 0) removePatch();
|
|
3894
|
+
maybeTeardownListener();
|
|
3895
|
+
};
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
// src/core/features/route.ts
|
|
3899
|
+
function installRoute(deps) {
|
|
3900
|
+
if (typeof window === "undefined") {
|
|
3901
|
+
return () => {
|
|
3902
|
+
};
|
|
3903
|
+
}
|
|
3904
|
+
if (!deps.routedTo && !deps.closeOnBack) {
|
|
3905
|
+
return () => {
|
|
3906
|
+
};
|
|
3907
|
+
}
|
|
3908
|
+
let handle = null;
|
|
3909
|
+
const onOpen = () => {
|
|
3910
|
+
if (handle) return;
|
|
3911
|
+
handle = pushBackMarker({
|
|
3912
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
3913
|
+
isTop: deps.isTopSheet,
|
|
3914
|
+
close: deps.close,
|
|
3915
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
3916
|
+
url: deps.routedTo
|
|
3917
|
+
});
|
|
3918
|
+
};
|
|
3919
|
+
const onClose = () => {
|
|
3920
|
+
if (!handle) return;
|
|
3921
|
+
popBackMarker(handle);
|
|
3922
|
+
handle = null;
|
|
3923
|
+
};
|
|
3924
|
+
const unsubscribeOpen = deps.on("open", onOpen);
|
|
3925
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
3926
|
+
if (deps.getSize() > 0) onOpen();
|
|
3927
|
+
return () => {
|
|
3928
|
+
unsubscribeOpen();
|
|
3929
|
+
unsubscribeClose();
|
|
3930
|
+
if (handle) {
|
|
3931
|
+
popBackMarker(handle);
|
|
3932
|
+
handle = null;
|
|
3933
|
+
}
|
|
3934
|
+
};
|
|
3935
|
+
}
|
|
3936
|
+
function installRouteChange(deps) {
|
|
3937
|
+
return subscribeRouteChange(() => {
|
|
3938
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
3939
|
+
void deps.close();
|
|
3940
|
+
});
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
// src/core/features/persist.ts
|
|
3944
|
+
function installPersist(engine, key) {
|
|
3945
|
+
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
3946
|
+
if (typeof window === "undefined") return;
|
|
3947
|
+
if (typeof localStorage === "undefined") return;
|
|
3948
|
+
try {
|
|
3949
|
+
localStorage.setItem(key, id);
|
|
3950
|
+
} catch {
|
|
3629
3951
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
previousSize,
|
|
3641
|
-
previousSnapSize === 0,
|
|
3642
|
-
true
|
|
3643
|
-
);
|
|
3644
|
-
});
|
|
3645
|
-
}
|
|
3646
|
-
clearWillChangeIfIdle() {
|
|
3647
|
-
if (this.animation.isAnimating || this.gesture?.isDragging) return;
|
|
3648
|
-
this.element.style.willChange = "";
|
|
3952
|
+
});
|
|
3953
|
+
return unsubscribe;
|
|
3954
|
+
}
|
|
3955
|
+
|
|
3956
|
+
// src/core/features/auto-collapse.ts
|
|
3957
|
+
function installAutoCollapse(deps) {
|
|
3958
|
+
const { ms } = deps;
|
|
3959
|
+
if (ms === void 0 || ms <= 0) {
|
|
3960
|
+
return () => {
|
|
3961
|
+
};
|
|
3649
3962
|
}
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3963
|
+
let timer = null;
|
|
3964
|
+
const clearTimer = () => {
|
|
3965
|
+
if (timer !== null) {
|
|
3966
|
+
clearTimeout(timer);
|
|
3967
|
+
timer = null;
|
|
3968
|
+
}
|
|
3969
|
+
};
|
|
3970
|
+
const fire = () => {
|
|
3971
|
+
if (deps.isDestroyed()) return;
|
|
3972
|
+
if (deps.isDragging()) return;
|
|
3973
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
3974
|
+
if (!active || active.size === 0) return;
|
|
3975
|
+
let target = null;
|
|
3976
|
+
for (const id of deps.getAllowedIds()) {
|
|
3977
|
+
const snap = deps.resolveSnap(id);
|
|
3978
|
+
if (!snap || snap.size <= 0) continue;
|
|
3979
|
+
if (!target || snap.size < target.size) target = snap;
|
|
3656
3980
|
}
|
|
3981
|
+
if (!target) return;
|
|
3982
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
3983
|
+
deps.snapTo(target.id);
|
|
3984
|
+
};
|
|
3985
|
+
const reset2 = () => {
|
|
3986
|
+
clearTimer();
|
|
3987
|
+
if (deps.isDestroyed()) return;
|
|
3988
|
+
timer = setTimeout(() => {
|
|
3989
|
+
timer = null;
|
|
3990
|
+
fire();
|
|
3991
|
+
}, ms);
|
|
3992
|
+
};
|
|
3993
|
+
const unsubscribe = deps.on("snap", () => reset2());
|
|
3994
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset2();
|
|
3995
|
+
return () => {
|
|
3996
|
+
clearTimer();
|
|
3997
|
+
unsubscribe();
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
|
|
4001
|
+
// src/core/features/content-drag.ts
|
|
4002
|
+
function installContentDrag(deps) {
|
|
4003
|
+
const detach = deps.attachDragSurface(deps.container, "content");
|
|
4004
|
+
return () => detach?.();
|
|
4005
|
+
}
|
|
4006
|
+
|
|
4007
|
+
// src/core/features/visual-viewport.ts
|
|
4008
|
+
var SAFETY_PAD = 8;
|
|
4009
|
+
function installVisualViewport(deps) {
|
|
4010
|
+
if (typeof window === "undefined" || !window.visualViewport) {
|
|
4011
|
+
return () => {
|
|
4012
|
+
};
|
|
3657
4013
|
}
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
4014
|
+
const vv = window.visualViewport;
|
|
4015
|
+
let rafId = null;
|
|
4016
|
+
const onResize = () => {
|
|
4017
|
+
if (rafId !== null) return;
|
|
4018
|
+
rafId = requestAnimationFrame(() => {
|
|
4019
|
+
rafId = null;
|
|
4020
|
+
if (deps.isDestroyed()) return;
|
|
4021
|
+
deps.recomputeSnaps();
|
|
4022
|
+
const isVertical = deps.isVerticalAxis();
|
|
4023
|
+
const visible = isVertical ? vv.height : vv.width;
|
|
4024
|
+
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
4025
|
+
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
4026
|
+
if (clamp < deps.getMaxAxisSize()) {
|
|
4027
|
+
deps.setMaxAxisSize(clamp);
|
|
3669
4028
|
}
|
|
3670
|
-
|
|
3671
|
-
|
|
4029
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
4030
|
+
deps.cancelInFlight();
|
|
4031
|
+
deps.newCycle();
|
|
4032
|
+
const max = deps.getMaxAxisSize();
|
|
4033
|
+
deps.setSize(Math.min(deps.getSize(), max));
|
|
4034
|
+
const current = deps.resolveActiveSnap();
|
|
4035
|
+
if (current && !deps.isDragging()) {
|
|
4036
|
+
deps.applySize(Math.min(current.size, max));
|
|
4037
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
4038
|
+
} else {
|
|
4039
|
+
deps.applySize(deps.getSize());
|
|
3672
4040
|
}
|
|
3673
|
-
|
|
3674
|
-
|
|
4041
|
+
});
|
|
4042
|
+
};
|
|
4043
|
+
vv.addEventListener("resize", onResize);
|
|
4044
|
+
return () => {
|
|
4045
|
+
vv.removeEventListener("resize", onResize);
|
|
4046
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
4047
|
+
};
|
|
4048
|
+
}
|
|
4049
|
+
|
|
4050
|
+
// src/core/features/engine-features.ts
|
|
4051
|
+
function routeFeature() {
|
|
4052
|
+
return {
|
|
4053
|
+
name: "route",
|
|
4054
|
+
install: (ctx) => {
|
|
4055
|
+
const teardowns = new TeardownStack();
|
|
4056
|
+
if (ctx.options.closeOnRouteChange) {
|
|
4057
|
+
teardowns.add(
|
|
4058
|
+
installRouteChange({
|
|
4059
|
+
isDestroyed: ctx.isDestroyed,
|
|
4060
|
+
getSize: ctx.getSize,
|
|
4061
|
+
close: () => ctx.close()
|
|
4062
|
+
})
|
|
4063
|
+
);
|
|
3675
4064
|
}
|
|
4065
|
+
teardowns.add(
|
|
4066
|
+
installRoute({
|
|
4067
|
+
routedTo: ctx.options.routedTo,
|
|
4068
|
+
closeOnBack: ctx.options.closeOnBack,
|
|
4069
|
+
isTopSheet: ctx.isTopSheet,
|
|
4070
|
+
getSize: ctx.getSize,
|
|
4071
|
+
isDestroyed: ctx.isDestroyed,
|
|
4072
|
+
close: () => ctx.close("back"),
|
|
4073
|
+
on: ctx.on,
|
|
4074
|
+
sheetId: ctx.sheetId
|
|
4075
|
+
})
|
|
4076
|
+
);
|
|
4077
|
+
return () => teardowns.drain();
|
|
3676
4078
|
}
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
if (
|
|
3685
|
-
|
|
3686
|
-
}
|
|
3687
|
-
if (this.rootEl && this.rootEl !== this.anchorHost) {
|
|
3688
|
-
this.rootEl.style.setProperty("--bs-progress", String(progress));
|
|
3689
|
-
}
|
|
4079
|
+
};
|
|
4080
|
+
}
|
|
4081
|
+
function persistFeature() {
|
|
4082
|
+
return {
|
|
4083
|
+
name: "persist",
|
|
4084
|
+
install: (ctx) => {
|
|
4085
|
+
const key = ctx.options.persistKey;
|
|
4086
|
+
if (!key) return;
|
|
4087
|
+
return installPersist({ on: ctx.on }, key);
|
|
3690
4088
|
}
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
4089
|
+
};
|
|
4090
|
+
}
|
|
4091
|
+
function autoCollapseFeature() {
|
|
4092
|
+
return {
|
|
4093
|
+
name: "auto-collapse",
|
|
4094
|
+
install: (ctx) => installAutoCollapse({
|
|
4095
|
+
ms: ctx.options.autoCollapseAfter,
|
|
4096
|
+
isDestroyed: ctx.isDestroyed,
|
|
4097
|
+
isDragging: ctx.isDragging,
|
|
4098
|
+
getAllowedIds: ctx.getAllowedIds,
|
|
4099
|
+
getActiveId: ctx.getActiveId,
|
|
4100
|
+
resolveSnap: ctx.resolveSnap,
|
|
4101
|
+
snapTo: ctx.snapTo,
|
|
4102
|
+
on: ctx.on
|
|
4103
|
+
})
|
|
4104
|
+
};
|
|
4105
|
+
}
|
|
4106
|
+
function contentSwipeFeature() {
|
|
4107
|
+
return {
|
|
4108
|
+
name: "content-swipe",
|
|
4109
|
+
stage: "attach",
|
|
4110
|
+
install: (ctx) => {
|
|
4111
|
+
if (!ctx.scrollContainer) return;
|
|
4112
|
+
return installContentDrag({
|
|
4113
|
+
container: ctx.scrollContainer,
|
|
4114
|
+
attachDragSurface: ctx.attachDragSurface
|
|
4115
|
+
});
|
|
3696
4116
|
}
|
|
3697
|
-
}
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
4117
|
+
};
|
|
4118
|
+
}
|
|
4119
|
+
function visualViewportFeature() {
|
|
4120
|
+
return {
|
|
4121
|
+
name: "visual-viewport",
|
|
4122
|
+
install: (ctx) => {
|
|
4123
|
+
if (typeof window === "undefined") return;
|
|
4124
|
+
return installVisualViewport({
|
|
4125
|
+
element: ctx.element,
|
|
4126
|
+
isVerticalAxis: ctx.isVerticalAxis,
|
|
4127
|
+
isDestroyed: ctx.isDestroyed,
|
|
4128
|
+
isDragging: ctx.isDragging,
|
|
4129
|
+
recomputeSnaps: ctx.recomputeSnaps,
|
|
4130
|
+
resolveActiveSnap: ctx.resolveActiveSnap,
|
|
4131
|
+
getMaxAxisSize: ctx.getMaxAxisSize,
|
|
4132
|
+
getSize: ctx.getSize,
|
|
4133
|
+
setMaxAxisSize: ctx.setMaxAxisSize,
|
|
4134
|
+
setSize: ctx.setSize,
|
|
4135
|
+
applySize: ctx.applySize,
|
|
4136
|
+
cancelInFlight: ctx.cancelInFlight,
|
|
4137
|
+
newCycle: ctx.newCycle,
|
|
4138
|
+
isAnimating: ctx.isAnimating,
|
|
4139
|
+
resyncAfterCancel: ctx.resyncAfterResize
|
|
3716
4140
|
});
|
|
3717
4141
|
}
|
|
3718
|
-
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
4142
|
+
};
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
// src/core/default-features.ts
|
|
4146
|
+
function defaultEngineFeatures() {
|
|
4147
|
+
return [
|
|
4148
|
+
contentSwipeFeature(),
|
|
4149
|
+
visualViewportFeature(),
|
|
4150
|
+
persistFeature(),
|
|
4151
|
+
autoCollapseFeature(),
|
|
4152
|
+
routeFeature()
|
|
4153
|
+
];
|
|
4154
|
+
}
|
|
4155
|
+
|
|
4156
|
+
// src/core/BottomSheetEngine.ts
|
|
4157
|
+
var BottomSheetEngine = class extends BottomSheetCore {
|
|
4158
|
+
constructor(opts) {
|
|
4159
|
+
super({
|
|
4160
|
+
...opts,
|
|
4161
|
+
features: [...defaultEngineFeatures(), ...opts.features ?? []]
|
|
3728
4162
|
});
|
|
3729
|
-
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3730
|
-
this.emitOpenSequence(target.id);
|
|
3731
|
-
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3732
|
-
this.emitCloseSequence();
|
|
3733
|
-
}
|
|
3734
|
-
}
|
|
3735
|
-
handleClose() {
|
|
3736
|
-
this.opening = false;
|
|
3737
|
-
this.lifecycle.release();
|
|
3738
|
-
sheetStack.update();
|
|
3739
4163
|
}
|
|
3740
4164
|
};
|
|
3741
4165
|
|
|
@@ -3899,6 +4323,8 @@ function BottomSheet($$anchor, $$props) {
|
|
|
3899
4323
|
persistent: persistent(),
|
|
3900
4324
|
disableClose: disableClose(),
|
|
3901
4325
|
disableDrag: disableDrag(),
|
|
4326
|
+
dragFrom: $$props.dragFrom,
|
|
4327
|
+
dragFromContent: $$props.dragFromContent,
|
|
3902
4328
|
closeOnRouteChange: closeOnRouteChange(),
|
|
3903
4329
|
stackEffect: stackEffect(),
|
|
3904
4330
|
radius: $$props.radius,
|
|
@@ -3995,6 +4421,14 @@ function BottomSheet($$anchor, $$props) {
|
|
|
3995
4421
|
$2__namespace.user_effect(() => {
|
|
3996
4422
|
engine?.setDisableDrag(disableDrag());
|
|
3997
4423
|
});
|
|
4424
|
+
$2__namespace.user_effect(() => {
|
|
4425
|
+
if ($$props.dragFromContent !== void 0) {
|
|
4426
|
+
engine?.setDragFromContent($$props.dragFromContent);
|
|
4427
|
+
}
|
|
4428
|
+
});
|
|
4429
|
+
$2__namespace.user_effect(() => {
|
|
4430
|
+
if ($$props.dragFrom !== void 0) engine?.setDragFrom($$props.dragFrom);
|
|
4431
|
+
});
|
|
3998
4432
|
$2__namespace.user_effect(() => {
|
|
3999
4433
|
if ($$props.radius !== void 0) engine?.setRadius($$props.radius);
|
|
4000
4434
|
});
|