@surdeddd/bottom-sheet 0.12.0 → 0.13.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 +52 -1
- package/dist/{BottomSheetEngine-D6oiEfZ4.d.cts → BottomSheetCore-CsIjyq7C.d.cts} +60 -5
- package/dist/{BottomSheetEngine-Dhy0X_e9.d.ts → BottomSheetCore-D16lsa6g.d.ts} +60 -5
- package/dist/BottomSheetEngine-BYjAVrmd.d.cts +7 -0
- package/dist/BottomSheetEngine-YuCNugZn.d.ts +7 -0
- package/dist/core.cjs +3476 -0
- package/dist/core.d.cts +3 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +3474 -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 +972 -685
- 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 +972 -685
- package/dist/features.cjs +533 -0
- package/dist/features.d.cts +13 -0
- package/dist/features.d.ts +13 -0
- package/dist/features.js +526 -0
- package/dist/index-DdYLOIIT.d.ts +15 -0
- package/dist/index-dfrzw-lI.d.cts +15 -0
- package/dist/index.cjs +805 -534
- package/dist/index.d.cts +6 -15
- package/dist/index.d.ts +6 -15
- package/dist/index.js +799 -535
- 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 +6 -5
- package/dist/overlay.js +6 -5
- package/dist/preact.d.cts +2 -1
- package/dist/preact.d.ts +2 -1
- package/dist/qwik-lib/index.qwik.cjs +4267 -0
- package/dist/qwik-lib/index.qwik.mjs +4267 -0
- package/dist/qwik.cjs +798 -534
- package/dist/qwik.d.cts +2 -2
- package/dist/qwik.d.ts +2 -2
- package/dist/qwik.js +798 -534
- package/dist/react.cjs +798 -534
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +798 -534
- package/dist/solid.cjs +798 -534
- package/dist/solid.d.cts +63 -4
- package/dist/solid.d.ts +63 -4
- package/dist/solid.js +798 -534
- package/dist/solid.source.jsx +798 -534
- package/dist/svelte-core.cjs +798 -534
- package/dist/svelte-core.js +798 -534
- package/dist/svelte.cjs +798 -534
- package/dist/svelte.js +798 -534
- package/dist/vue.cjs +909 -637
- package/dist/vue.js +909 -637
- package/package.json +63 -11
package/dist/svelte.cjs
CHANGED
|
@@ -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,13 +1396,22 @@ 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();
|
|
1748
|
-
|
|
1749
|
-
|
|
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
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
async animateTo(target, velocityPxPerMs) {
|
|
1750
1415
|
if (target === this.getSize()) {
|
|
1751
1416
|
if (!this.isAnimating && !this.isDragging()) {
|
|
1752
1417
|
this.element.style.willChange = "";
|
|
@@ -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,11 +1477,66 @@ 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
|
|
|
@@ -2652,7 +2393,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2652
2393
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2653
2394
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2654
2395
|
if (opts.persistKey) {
|
|
2655
|
-
const restored =
|
|
2396
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2656
2397
|
if (restored && initialAllowed.includes(restored)) {
|
|
2657
2398
|
initialId = restored;
|
|
2658
2399
|
}
|
|
@@ -2683,6 +2424,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2683
2424
|
},
|
|
2684
2425
|
animation: {
|
|
2685
2426
|
animation: opts.animation,
|
|
2427
|
+
settleAnimation: opts.settleAnimation,
|
|
2686
2428
|
duration: opts.duration,
|
|
2687
2429
|
easing: opts.easing,
|
|
2688
2430
|
spring: opts.spring,
|
|
@@ -2700,6 +2442,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2700
2442
|
}
|
|
2701
2443
|
};
|
|
2702
2444
|
}
|
|
2445
|
+
var readPersistedIdSafe = (key) => {
|
|
2446
|
+
if (typeof window === "undefined") return null;
|
|
2447
|
+
if (typeof localStorage === "undefined") return null;
|
|
2448
|
+
try {
|
|
2449
|
+
return localStorage.getItem(key);
|
|
2450
|
+
} catch {
|
|
2451
|
+
return null;
|
|
2452
|
+
}
|
|
2453
|
+
};
|
|
2703
2454
|
|
|
2704
2455
|
// src/core/primitives/teardown-stack.ts
|
|
2705
2456
|
var TeardownStack = class {
|
|
@@ -2722,9 +2473,9 @@ var TeardownStack = class {
|
|
|
2722
2473
|
}
|
|
2723
2474
|
};
|
|
2724
2475
|
|
|
2725
|
-
// src/core/
|
|
2476
|
+
// src/core/BottomSheetCore.ts
|
|
2726
2477
|
var HAPTIC_DURATION_MS = 8;
|
|
2727
|
-
var
|
|
2478
|
+
var BottomSheetCore = class {
|
|
2728
2479
|
constructor(opts) {
|
|
2729
2480
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
2730
2481
|
__publicField(this, "element");
|
|
@@ -2785,6 +2536,8 @@ var BottomSheetEngine = class {
|
|
|
2785
2536
|
__publicField(this, "stackEffectPrimed", false);
|
|
2786
2537
|
__publicField(this, "fitDeps");
|
|
2787
2538
|
__publicField(this, "transformTemplate");
|
|
2539
|
+
__publicField(this, "featureList", []);
|
|
2540
|
+
__publicField(this, "featureCtx");
|
|
2788
2541
|
const resolved = resolveEngineOptions(opts, {
|
|
2789
2542
|
shouldApplyInertSiblings: () => {
|
|
2790
2543
|
if (typeof document === "undefined") return false;
|
|
@@ -2831,7 +2584,9 @@ var BottomSheetEngine = class {
|
|
|
2831
2584
|
getRootEl: () => this.rootEl,
|
|
2832
2585
|
applySize: (size) => this.applySize(size),
|
|
2833
2586
|
getSize: () => this.size,
|
|
2834
|
-
isDragging: () => this.gesture?.isDragging ?? false
|
|
2587
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2588
|
+
applyAux: (size) => this.applySize(size, true),
|
|
2589
|
+
getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
|
|
2835
2590
|
},
|
|
2836
2591
|
resolved.animation
|
|
2837
2592
|
);
|
|
@@ -2854,6 +2609,11 @@ var BottomSheetEngine = class {
|
|
|
2854
2609
|
if (opts.linkedSheets) {
|
|
2855
2610
|
this.linkedSheets = opts.linkedSheets;
|
|
2856
2611
|
}
|
|
2612
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2613
|
+
for (const feature of opts.features ?? []) {
|
|
2614
|
+
byName.set(feature.name, feature);
|
|
2615
|
+
}
|
|
2616
|
+
this.featureList = Array.from(byName.values());
|
|
2857
2617
|
this.activeId = resolved.initialId;
|
|
2858
2618
|
auditVhUsage(this.snapPointsRaw);
|
|
2859
2619
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
@@ -2890,6 +2650,7 @@ var BottomSheetEngine = class {
|
|
|
2890
2650
|
scrollContainer: this.scrollContainer,
|
|
2891
2651
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize()
|
|
2892
2652
|
});
|
|
2653
|
+
this.featureCtx = this.buildFeatureContext(opts.autoCollapseAfter);
|
|
2893
2654
|
this.attach();
|
|
2894
2655
|
this.registerInStack();
|
|
2895
2656
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
@@ -2921,46 +2682,77 @@ var BottomSheetEngine = class {
|
|
|
2921
2682
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2922
2683
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2923
2684
|
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));
|
|
2685
|
+
this.runFeatureStage("post");
|
|
2686
|
+
this.warnOrphanFeatureOptions();
|
|
2687
|
+
if (this.size > 0) {
|
|
2688
|
+
this.handleOpen();
|
|
2935
2689
|
}
|
|
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({
|
|
2690
|
+
}
|
|
2691
|
+
buildFeatureContext(autoCollapseAfter) {
|
|
2692
|
+
return {
|
|
2693
|
+
element: this.element,
|
|
2694
|
+
scrollContainer: this.scrollContainer,
|
|
2695
|
+
sheetId: this.id,
|
|
2696
|
+
options: {
|
|
2952
2697
|
routedTo: this.routedTo,
|
|
2953
2698
|
closeOnBack: this.closeOnBack,
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
this.
|
|
2699
|
+
closeOnRouteChange: this.closeOnRouteChange,
|
|
2700
|
+
persistKey: this.persistKey,
|
|
2701
|
+
autoCollapseAfter
|
|
2702
|
+
},
|
|
2703
|
+
isDestroyed: () => this.destroyed,
|
|
2704
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2705
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2706
|
+
isTopSheet: () => this.isTopSheet,
|
|
2707
|
+
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
2708
|
+
getSize: () => this.size,
|
|
2709
|
+
getActiveId: () => this.activeId,
|
|
2710
|
+
getAllowedIds: () => this.snaps.getAllowedIds().slice(),
|
|
2711
|
+
allowedIdsBySize: () => this.allowedIdsBySize(),
|
|
2712
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2713
|
+
resolveSnap: (id) => this.snaps.findById(id),
|
|
2714
|
+
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
2715
|
+
setSize: (size) => {
|
|
2716
|
+
this.size = size;
|
|
2717
|
+
},
|
|
2718
|
+
setMaxAxisSize: (size) => {
|
|
2719
|
+
this.snaps.setMaxAxisSize(size);
|
|
2720
|
+
},
|
|
2721
|
+
applySize: (size) => this.applySize(size),
|
|
2722
|
+
recomputeSnaps: () => this.recomputeSnaps(),
|
|
2723
|
+
newCycle: () => {
|
|
2724
|
+
this.newCycle();
|
|
2725
|
+
},
|
|
2726
|
+
cancelInFlight: () => {
|
|
2727
|
+
this.animation.cancel();
|
|
2728
|
+
},
|
|
2729
|
+
resyncAfterResize: () => this.resyncAfterResize(),
|
|
2730
|
+
snapTo: (id) => {
|
|
2731
|
+
void this.snapTo(id);
|
|
2732
|
+
},
|
|
2733
|
+
close: (reason) => this.close(reason),
|
|
2734
|
+
on: (event, fn) => this.on(event, fn),
|
|
2735
|
+
addTeardown: (fn) => this.teardowns.add(fn)
|
|
2736
|
+
};
|
|
2737
|
+
}
|
|
2738
|
+
runFeatureStage(stage) {
|
|
2739
|
+
for (const feature of this.featureList) {
|
|
2740
|
+
if ((feature.stage ?? "post") !== stage) continue;
|
|
2741
|
+
const teardown = feature.install(this.featureCtx);
|
|
2742
|
+
if (teardown) this.teardowns.add(teardown);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
warnOrphanFeatureOptions() {
|
|
2746
|
+
const names = new Set(this.featureList.map((f) => f.name));
|
|
2747
|
+
if ((this.closeOnBack || this.routedTo !== void 0 || this.closeOnRouteChange) && !names.has("route")) {
|
|
2748
|
+
devWarn(
|
|
2749
|
+
"[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
|
|
2750
|
+
);
|
|
2751
|
+
}
|
|
2752
|
+
if (this.persistKey && !names.has("persist")) {
|
|
2753
|
+
devWarn(
|
|
2754
|
+
"[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
|
|
2755
|
+
);
|
|
2964
2756
|
}
|
|
2965
2757
|
}
|
|
2966
2758
|
get state() {
|
|
@@ -3503,18 +3295,7 @@ var BottomSheetEngine = class {
|
|
|
3503
3295
|
}
|
|
3504
3296
|
}
|
|
3505
3297
|
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
|
-
}
|
|
3298
|
+
this.runFeatureStage("attach");
|
|
3518
3299
|
if (typeof window !== "undefined") {
|
|
3519
3300
|
this.teardowns.add(installResizeObserver({
|
|
3520
3301
|
element: this.element,
|
|
@@ -3554,31 +3335,6 @@ var BottomSheetEngine = class {
|
|
|
3554
3335
|
() => document.removeEventListener("keydown", onKey)
|
|
3555
3336
|
);
|
|
3556
3337
|
}
|
|
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
3338
|
}
|
|
3583
3339
|
this.teardowns.add(installSliderKeyboard({
|
|
3584
3340
|
handle: this.handle,
|
|
@@ -3655,13 +3411,13 @@ var BottomSheetEngine = class {
|
|
|
3655
3411
|
}
|
|
3656
3412
|
}
|
|
3657
3413
|
}
|
|
3658
|
-
applySize(size) {
|
|
3414
|
+
applySize(size, skipTransform = false) {
|
|
3659
3415
|
const cap = this.snaps.getMaxAxisSize();
|
|
3660
3416
|
const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
|
|
3661
3417
|
this.size = clamped;
|
|
3662
3418
|
const offset = cap - clamped;
|
|
3663
3419
|
const style = this.element.style;
|
|
3664
|
-
style.transform = this.transformTemplate(offset);
|
|
3420
|
+
if (!skipTransform) style.transform = this.transformTemplate(offset);
|
|
3665
3421
|
if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
|
|
3666
3422
|
style.setProperty("--bs-size", `${clamped}px`);
|
|
3667
3423
|
if (this.scrimParent) {
|
|
@@ -3739,6 +3495,514 @@ var BottomSheetEngine = class {
|
|
|
3739
3495
|
}
|
|
3740
3496
|
};
|
|
3741
3497
|
|
|
3498
|
+
// src/core/features/history-coordinator.ts
|
|
3499
|
+
var entries = [];
|
|
3500
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3501
|
+
var suppress = 0;
|
|
3502
|
+
var internalDepth = 0;
|
|
3503
|
+
var pendingRebrands = [];
|
|
3504
|
+
var listenerInstalled = false;
|
|
3505
|
+
var patchInstalled = false;
|
|
3506
|
+
var origPushState = null;
|
|
3507
|
+
var origReplaceState = null;
|
|
3508
|
+
var patchedPushState = null;
|
|
3509
|
+
var patchedReplaceState = null;
|
|
3510
|
+
var hasWindow = () => typeof window !== "undefined";
|
|
3511
|
+
var hasHistory = () => typeof history !== "undefined";
|
|
3512
|
+
var brandMarker = (surface) => ({
|
|
3513
|
+
...surface.markerState(),
|
|
3514
|
+
__bs: true
|
|
3515
|
+
});
|
|
3516
|
+
var runInternal = (fn) => {
|
|
3517
|
+
internalDepth += 1;
|
|
3518
|
+
try {
|
|
3519
|
+
fn();
|
|
3520
|
+
} finally {
|
|
3521
|
+
internalDepth -= 1;
|
|
3522
|
+
}
|
|
3523
|
+
};
|
|
3524
|
+
var notifyRouteChange = () => {
|
|
3525
|
+
const snapshot = Array.from(subscribers);
|
|
3526
|
+
for (const fn of snapshot) fn();
|
|
3527
|
+
};
|
|
3528
|
+
var ensureListener = () => {
|
|
3529
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
3530
|
+
window.addEventListener("popstate", onPopState);
|
|
3531
|
+
listenerInstalled = true;
|
|
3532
|
+
};
|
|
3533
|
+
var maybeTeardownListener = () => {
|
|
3534
|
+
if (!listenerInstalled) return;
|
|
3535
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
3536
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
3537
|
+
listenerInstalled = false;
|
|
3538
|
+
};
|
|
3539
|
+
var installPatch = () => {
|
|
3540
|
+
if (patchInstalled || !hasHistory()) return;
|
|
3541
|
+
origPushState = history.pushState;
|
|
3542
|
+
origReplaceState = history.replaceState;
|
|
3543
|
+
patchedPushState = function(...args) {
|
|
3544
|
+
origPushState.apply(this, args);
|
|
3545
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3546
|
+
};
|
|
3547
|
+
patchedReplaceState = function(...args) {
|
|
3548
|
+
origReplaceState.apply(this, args);
|
|
3549
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3550
|
+
};
|
|
3551
|
+
history.pushState = patchedPushState;
|
|
3552
|
+
history.replaceState = patchedReplaceState;
|
|
3553
|
+
patchInstalled = true;
|
|
3554
|
+
};
|
|
3555
|
+
var removePatch = () => {
|
|
3556
|
+
if (!patchInstalled) return;
|
|
3557
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
3558
|
+
history.pushState = origPushState;
|
|
3559
|
+
}
|
|
3560
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
3561
|
+
history.replaceState = origReplaceState;
|
|
3562
|
+
}
|
|
3563
|
+
origPushState = null;
|
|
3564
|
+
origReplaceState = null;
|
|
3565
|
+
patchedPushState = null;
|
|
3566
|
+
patchedReplaceState = null;
|
|
3567
|
+
patchInstalled = false;
|
|
3568
|
+
};
|
|
3569
|
+
function onPopState() {
|
|
3570
|
+
if (suppress > 0) {
|
|
3571
|
+
suppress -= 1;
|
|
3572
|
+
const rebrand = pendingRebrands.shift();
|
|
3573
|
+
if (rebrand) rebrand();
|
|
3574
|
+
maybeTeardownListener();
|
|
3575
|
+
return;
|
|
3576
|
+
}
|
|
3577
|
+
if (entries.length === 0) {
|
|
3578
|
+
notifyRouteChange();
|
|
3579
|
+
maybeTeardownListener();
|
|
3580
|
+
return;
|
|
3581
|
+
}
|
|
3582
|
+
let target = null;
|
|
3583
|
+
let targetIdx = -1;
|
|
3584
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3585
|
+
const entry = entries[i];
|
|
3586
|
+
if (!entry.surface.isOpen()) continue;
|
|
3587
|
+
if (!target) {
|
|
3588
|
+
target = entry;
|
|
3589
|
+
targetIdx = i;
|
|
3590
|
+
}
|
|
3591
|
+
if (entry.surface.isTop()) {
|
|
3592
|
+
target = entry;
|
|
3593
|
+
targetIdx = i;
|
|
3594
|
+
break;
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
if (!target) {
|
|
3598
|
+
const removed = entries.pop();
|
|
3599
|
+
if (removed) removed.live = false;
|
|
3600
|
+
maybeTeardownListener();
|
|
3601
|
+
return;
|
|
3602
|
+
}
|
|
3603
|
+
target.live = false;
|
|
3604
|
+
entries.splice(targetIdx, 1);
|
|
3605
|
+
const settled = target;
|
|
3606
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
3607
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
3608
|
+
});
|
|
3609
|
+
maybeTeardownListener();
|
|
3610
|
+
}
|
|
3611
|
+
function restore(entry) {
|
|
3612
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3613
|
+
entry.live = true;
|
|
3614
|
+
runInternal(() => {
|
|
3615
|
+
try {
|
|
3616
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
3617
|
+
} catch {
|
|
3618
|
+
entry.live = false;
|
|
3619
|
+
}
|
|
3620
|
+
});
|
|
3621
|
+
if (entry.live) {
|
|
3622
|
+
entries.push(entry);
|
|
3623
|
+
ensureListener();
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
function pushBackMarker(surface) {
|
|
3627
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
3628
|
+
if (!hasWindow() || !hasHistory()) {
|
|
3629
|
+
return entry;
|
|
3630
|
+
}
|
|
3631
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
3632
|
+
runInternal(() => {
|
|
3633
|
+
try {
|
|
3634
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
3635
|
+
entry.live = true;
|
|
3636
|
+
} catch {
|
|
3637
|
+
entry.live = false;
|
|
3638
|
+
}
|
|
3639
|
+
});
|
|
3640
|
+
if (entry.live) {
|
|
3641
|
+
entries.push(entry);
|
|
3642
|
+
ensureListener();
|
|
3643
|
+
}
|
|
3644
|
+
return entry;
|
|
3645
|
+
}
|
|
3646
|
+
function popBackMarker(handle) {
|
|
3647
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3648
|
+
const entry = handle;
|
|
3649
|
+
const idx = entries.indexOf(entry);
|
|
3650
|
+
if (idx === -1 || !entry.live) return;
|
|
3651
|
+
const last = entries.length - 1;
|
|
3652
|
+
entry.live = false;
|
|
3653
|
+
entries.splice(idx, 1);
|
|
3654
|
+
let rebrand = null;
|
|
3655
|
+
if (idx !== last) {
|
|
3656
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
3657
|
+
const rebrandUrl = entry.priorUrl;
|
|
3658
|
+
rebrand = () => {
|
|
3659
|
+
runInternal(() => {
|
|
3660
|
+
history.replaceState(
|
|
3661
|
+
brandMarker(rebrandSurface),
|
|
3662
|
+
"",
|
|
3663
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
3664
|
+
);
|
|
3665
|
+
});
|
|
3666
|
+
};
|
|
3667
|
+
}
|
|
3668
|
+
pendingRebrands.push(rebrand);
|
|
3669
|
+
suppress += 1;
|
|
3670
|
+
runInternal(() => {
|
|
3671
|
+
try {
|
|
3672
|
+
history.back();
|
|
3673
|
+
} catch {
|
|
3674
|
+
suppress = Math.max(0, suppress - 1);
|
|
3675
|
+
pendingRebrands.pop();
|
|
3676
|
+
}
|
|
3677
|
+
});
|
|
3678
|
+
maybeTeardownListener();
|
|
3679
|
+
}
|
|
3680
|
+
function subscribeRouteChange(fn) {
|
|
3681
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
3682
|
+
};
|
|
3683
|
+
subscribers.add(fn);
|
|
3684
|
+
if (subscribers.size === 1) installPatch();
|
|
3685
|
+
ensureListener();
|
|
3686
|
+
return () => {
|
|
3687
|
+
if (!subscribers.has(fn)) return;
|
|
3688
|
+
subscribers.delete(fn);
|
|
3689
|
+
if (subscribers.size === 0) removePatch();
|
|
3690
|
+
maybeTeardownListener();
|
|
3691
|
+
};
|
|
3692
|
+
}
|
|
3693
|
+
|
|
3694
|
+
// src/core/features/route.ts
|
|
3695
|
+
function installRoute(deps) {
|
|
3696
|
+
if (typeof window === "undefined") {
|
|
3697
|
+
return () => {
|
|
3698
|
+
};
|
|
3699
|
+
}
|
|
3700
|
+
if (!deps.routedTo && !deps.closeOnBack) {
|
|
3701
|
+
return () => {
|
|
3702
|
+
};
|
|
3703
|
+
}
|
|
3704
|
+
let handle = null;
|
|
3705
|
+
const onOpen = () => {
|
|
3706
|
+
if (handle) return;
|
|
3707
|
+
handle = pushBackMarker({
|
|
3708
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
3709
|
+
isTop: deps.isTopSheet,
|
|
3710
|
+
close: deps.close,
|
|
3711
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
3712
|
+
url: deps.routedTo
|
|
3713
|
+
});
|
|
3714
|
+
};
|
|
3715
|
+
const onClose = () => {
|
|
3716
|
+
if (!handle) return;
|
|
3717
|
+
popBackMarker(handle);
|
|
3718
|
+
handle = null;
|
|
3719
|
+
};
|
|
3720
|
+
const unsubscribeOpen = deps.on("open", onOpen);
|
|
3721
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
3722
|
+
if (deps.getSize() > 0) onOpen();
|
|
3723
|
+
return () => {
|
|
3724
|
+
unsubscribeOpen();
|
|
3725
|
+
unsubscribeClose();
|
|
3726
|
+
if (handle) {
|
|
3727
|
+
popBackMarker(handle);
|
|
3728
|
+
handle = null;
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3731
|
+
}
|
|
3732
|
+
function installRouteChange(deps) {
|
|
3733
|
+
return subscribeRouteChange(() => {
|
|
3734
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
3735
|
+
void deps.close();
|
|
3736
|
+
});
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
// src/core/features/persist.ts
|
|
3740
|
+
function installPersist(engine, key) {
|
|
3741
|
+
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
3742
|
+
if (typeof window === "undefined") return;
|
|
3743
|
+
if (typeof localStorage === "undefined") return;
|
|
3744
|
+
try {
|
|
3745
|
+
localStorage.setItem(key, id);
|
|
3746
|
+
} catch {
|
|
3747
|
+
}
|
|
3748
|
+
});
|
|
3749
|
+
return unsubscribe;
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
// src/core/features/auto-collapse.ts
|
|
3753
|
+
function installAutoCollapse(deps) {
|
|
3754
|
+
const { ms } = deps;
|
|
3755
|
+
if (ms === void 0 || ms <= 0) {
|
|
3756
|
+
return () => {
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
let timer = null;
|
|
3760
|
+
const clearTimer = () => {
|
|
3761
|
+
if (timer !== null) {
|
|
3762
|
+
clearTimeout(timer);
|
|
3763
|
+
timer = null;
|
|
3764
|
+
}
|
|
3765
|
+
};
|
|
3766
|
+
const fire = () => {
|
|
3767
|
+
if (deps.isDestroyed()) return;
|
|
3768
|
+
if (deps.isDragging()) return;
|
|
3769
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
3770
|
+
if (!active || active.size === 0) return;
|
|
3771
|
+
let target = null;
|
|
3772
|
+
for (const id of deps.getAllowedIds()) {
|
|
3773
|
+
const snap = deps.resolveSnap(id);
|
|
3774
|
+
if (!snap || snap.size <= 0) continue;
|
|
3775
|
+
if (!target || snap.size < target.size) target = snap;
|
|
3776
|
+
}
|
|
3777
|
+
if (!target) return;
|
|
3778
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
3779
|
+
deps.snapTo(target.id);
|
|
3780
|
+
};
|
|
3781
|
+
const reset2 = () => {
|
|
3782
|
+
clearTimer();
|
|
3783
|
+
if (deps.isDestroyed()) return;
|
|
3784
|
+
timer = setTimeout(() => {
|
|
3785
|
+
timer = null;
|
|
3786
|
+
fire();
|
|
3787
|
+
}, ms);
|
|
3788
|
+
};
|
|
3789
|
+
const unsubscribe = deps.on("snap", () => reset2());
|
|
3790
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset2();
|
|
3791
|
+
return () => {
|
|
3792
|
+
clearTimer();
|
|
3793
|
+
unsubscribe();
|
|
3794
|
+
};
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3797
|
+
// src/core/features/content-swipe.ts
|
|
3798
|
+
var CONTENT_PULL_THRESHOLD = 60;
|
|
3799
|
+
function installContentSwipe(deps) {
|
|
3800
|
+
const { container } = deps;
|
|
3801
|
+
let startY = 0;
|
|
3802
|
+
let startScrollTop = 0;
|
|
3803
|
+
let moved = false;
|
|
3804
|
+
const onTouchStart = (e) => {
|
|
3805
|
+
const t = e.touches[0];
|
|
3806
|
+
if (!t) return;
|
|
3807
|
+
startY = t.clientY;
|
|
3808
|
+
startScrollTop = container.scrollTop;
|
|
3809
|
+
moved = false;
|
|
3810
|
+
};
|
|
3811
|
+
const onTouchMove = (e) => {
|
|
3812
|
+
const t = e.touches[0];
|
|
3813
|
+
if (!t) return;
|
|
3814
|
+
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
3815
|
+
};
|
|
3816
|
+
const onTouchEnd = (e) => {
|
|
3817
|
+
if (!moved) return;
|
|
3818
|
+
if (deps.isDragging() || deps.isAnimating()) return;
|
|
3819
|
+
if (container.scrollTop !== startScrollTop) return;
|
|
3820
|
+
const t = e.changedTouches[0];
|
|
3821
|
+
if (!t) return;
|
|
3822
|
+
const deltaY = t.clientY - startY;
|
|
3823
|
+
const atTop = container.scrollTop <= 0;
|
|
3824
|
+
const allowed = deps.getAllowedIds();
|
|
3825
|
+
const idx = allowed.indexOf(deps.getActiveId());
|
|
3826
|
+
if (idx === -1) return;
|
|
3827
|
+
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
3828
|
+
deps.snapTo(allowed[idx - 1]);
|
|
3829
|
+
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
3830
|
+
deps.snapTo(allowed[idx + 1]);
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
3834
|
+
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
3835
|
+
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
3836
|
+
return () => {
|
|
3837
|
+
container.removeEventListener("touchstart", onTouchStart);
|
|
3838
|
+
container.removeEventListener("touchmove", onTouchMove);
|
|
3839
|
+
container.removeEventListener("touchend", onTouchEnd);
|
|
3840
|
+
};
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
// src/core/features/visual-viewport.ts
|
|
3844
|
+
var SAFETY_PAD = 8;
|
|
3845
|
+
function installVisualViewport(deps) {
|
|
3846
|
+
if (typeof window === "undefined" || !window.visualViewport) {
|
|
3847
|
+
return () => {
|
|
3848
|
+
};
|
|
3849
|
+
}
|
|
3850
|
+
const vv = window.visualViewport;
|
|
3851
|
+
let rafId = null;
|
|
3852
|
+
const onResize = () => {
|
|
3853
|
+
if (rafId !== null) return;
|
|
3854
|
+
rafId = requestAnimationFrame(() => {
|
|
3855
|
+
rafId = null;
|
|
3856
|
+
if (deps.isDestroyed()) return;
|
|
3857
|
+
deps.recomputeSnaps();
|
|
3858
|
+
const isVertical = deps.isVerticalAxis();
|
|
3859
|
+
const visible = isVertical ? vv.height : vv.width;
|
|
3860
|
+
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
3861
|
+
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
3862
|
+
if (clamp < deps.getMaxAxisSize()) {
|
|
3863
|
+
deps.setMaxAxisSize(clamp);
|
|
3864
|
+
}
|
|
3865
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
3866
|
+
deps.cancelInFlight();
|
|
3867
|
+
deps.newCycle();
|
|
3868
|
+
const max = deps.getMaxAxisSize();
|
|
3869
|
+
deps.setSize(Math.min(deps.getSize(), max));
|
|
3870
|
+
const current = deps.resolveActiveSnap();
|
|
3871
|
+
if (current && !deps.isDragging()) {
|
|
3872
|
+
deps.applySize(Math.min(current.size, max));
|
|
3873
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
3874
|
+
} else {
|
|
3875
|
+
deps.applySize(deps.getSize());
|
|
3876
|
+
}
|
|
3877
|
+
});
|
|
3878
|
+
};
|
|
3879
|
+
vv.addEventListener("resize", onResize);
|
|
3880
|
+
return () => {
|
|
3881
|
+
vv.removeEventListener("resize", onResize);
|
|
3882
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
3883
|
+
};
|
|
3884
|
+
}
|
|
3885
|
+
|
|
3886
|
+
// src/core/features/engine-features.ts
|
|
3887
|
+
function routeFeature() {
|
|
3888
|
+
return {
|
|
3889
|
+
name: "route",
|
|
3890
|
+
install: (ctx) => {
|
|
3891
|
+
const teardowns = new TeardownStack();
|
|
3892
|
+
if (ctx.options.closeOnRouteChange) {
|
|
3893
|
+
teardowns.add(
|
|
3894
|
+
installRouteChange({
|
|
3895
|
+
isDestroyed: ctx.isDestroyed,
|
|
3896
|
+
getSize: ctx.getSize,
|
|
3897
|
+
close: () => ctx.close()
|
|
3898
|
+
})
|
|
3899
|
+
);
|
|
3900
|
+
}
|
|
3901
|
+
teardowns.add(
|
|
3902
|
+
installRoute({
|
|
3903
|
+
routedTo: ctx.options.routedTo,
|
|
3904
|
+
closeOnBack: ctx.options.closeOnBack,
|
|
3905
|
+
isTopSheet: ctx.isTopSheet,
|
|
3906
|
+
getSize: ctx.getSize,
|
|
3907
|
+
isDestroyed: ctx.isDestroyed,
|
|
3908
|
+
close: () => ctx.close("back"),
|
|
3909
|
+
on: ctx.on,
|
|
3910
|
+
sheetId: ctx.sheetId
|
|
3911
|
+
})
|
|
3912
|
+
);
|
|
3913
|
+
return () => teardowns.drain();
|
|
3914
|
+
}
|
|
3915
|
+
};
|
|
3916
|
+
}
|
|
3917
|
+
function persistFeature() {
|
|
3918
|
+
return {
|
|
3919
|
+
name: "persist",
|
|
3920
|
+
install: (ctx) => {
|
|
3921
|
+
const key = ctx.options.persistKey;
|
|
3922
|
+
if (!key) return;
|
|
3923
|
+
return installPersist({ on: ctx.on }, key);
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3927
|
+
function autoCollapseFeature() {
|
|
3928
|
+
return {
|
|
3929
|
+
name: "auto-collapse",
|
|
3930
|
+
install: (ctx) => installAutoCollapse({
|
|
3931
|
+
ms: ctx.options.autoCollapseAfter,
|
|
3932
|
+
isDestroyed: ctx.isDestroyed,
|
|
3933
|
+
isDragging: ctx.isDragging,
|
|
3934
|
+
getAllowedIds: ctx.getAllowedIds,
|
|
3935
|
+
getActiveId: ctx.getActiveId,
|
|
3936
|
+
resolveSnap: ctx.resolveSnap,
|
|
3937
|
+
snapTo: ctx.snapTo,
|
|
3938
|
+
on: ctx.on
|
|
3939
|
+
})
|
|
3940
|
+
};
|
|
3941
|
+
}
|
|
3942
|
+
function contentSwipeFeature() {
|
|
3943
|
+
return {
|
|
3944
|
+
name: "content-swipe",
|
|
3945
|
+
stage: "attach",
|
|
3946
|
+
install: (ctx) => {
|
|
3947
|
+
if (!ctx.scrollContainer) return;
|
|
3948
|
+
return installContentSwipe({
|
|
3949
|
+
container: ctx.scrollContainer,
|
|
3950
|
+
isDragging: ctx.isDragging,
|
|
3951
|
+
isAnimating: ctx.isAnimating,
|
|
3952
|
+
getAllowedIds: ctx.allowedIdsBySize,
|
|
3953
|
+
getActiveId: ctx.getActiveId,
|
|
3954
|
+
snapTo: ctx.snapTo
|
|
3955
|
+
});
|
|
3956
|
+
}
|
|
3957
|
+
};
|
|
3958
|
+
}
|
|
3959
|
+
function visualViewportFeature() {
|
|
3960
|
+
return {
|
|
3961
|
+
name: "visual-viewport",
|
|
3962
|
+
install: (ctx) => {
|
|
3963
|
+
if (typeof window === "undefined") return;
|
|
3964
|
+
return installVisualViewport({
|
|
3965
|
+
element: ctx.element,
|
|
3966
|
+
isVerticalAxis: ctx.isVerticalAxis,
|
|
3967
|
+
isDestroyed: ctx.isDestroyed,
|
|
3968
|
+
isDragging: ctx.isDragging,
|
|
3969
|
+
recomputeSnaps: ctx.recomputeSnaps,
|
|
3970
|
+
resolveActiveSnap: ctx.resolveActiveSnap,
|
|
3971
|
+
getMaxAxisSize: ctx.getMaxAxisSize,
|
|
3972
|
+
getSize: ctx.getSize,
|
|
3973
|
+
setMaxAxisSize: ctx.setMaxAxisSize,
|
|
3974
|
+
setSize: ctx.setSize,
|
|
3975
|
+
applySize: ctx.applySize,
|
|
3976
|
+
cancelInFlight: ctx.cancelInFlight,
|
|
3977
|
+
newCycle: ctx.newCycle,
|
|
3978
|
+
isAnimating: ctx.isAnimating,
|
|
3979
|
+
resyncAfterCancel: ctx.resyncAfterResize
|
|
3980
|
+
});
|
|
3981
|
+
}
|
|
3982
|
+
};
|
|
3983
|
+
}
|
|
3984
|
+
|
|
3985
|
+
// src/core/default-features.ts
|
|
3986
|
+
function defaultEngineFeatures() {
|
|
3987
|
+
return [
|
|
3988
|
+
contentSwipeFeature(),
|
|
3989
|
+
visualViewportFeature(),
|
|
3990
|
+
persistFeature(),
|
|
3991
|
+
autoCollapseFeature(),
|
|
3992
|
+
routeFeature()
|
|
3993
|
+
];
|
|
3994
|
+
}
|
|
3995
|
+
|
|
3996
|
+
// src/core/BottomSheetEngine.ts
|
|
3997
|
+
var BottomSheetEngine = class extends BottomSheetCore {
|
|
3998
|
+
constructor(opts) {
|
|
3999
|
+
super({
|
|
4000
|
+
...opts,
|
|
4001
|
+
features: [...defaultEngineFeatures(), ...opts.features ?? []]
|
|
4002
|
+
});
|
|
4003
|
+
}
|
|
4004
|
+
};
|
|
4005
|
+
|
|
3742
4006
|
// src/core/features/teleport.ts
|
|
3743
4007
|
var resolveTeleportTarget = (target) => {
|
|
3744
4008
|
if (!target) return null;
|