@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/solid.source.jsx
CHANGED
|
@@ -354,74 +354,6 @@ var SnapResolver = class {
|
|
|
354
354
|
}
|
|
355
355
|
};
|
|
356
356
|
|
|
357
|
-
// src/core/features/persist.ts
|
|
358
|
-
function readPersistedId(key) {
|
|
359
|
-
if (!key) return null;
|
|
360
|
-
if (typeof window === "undefined") return null;
|
|
361
|
-
if (typeof localStorage === "undefined") return null;
|
|
362
|
-
try {
|
|
363
|
-
return localStorage.getItem(key);
|
|
364
|
-
} catch {
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
function installPersist(engine, key) {
|
|
369
|
-
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
370
|
-
if (typeof window === "undefined") return;
|
|
371
|
-
if (typeof localStorage === "undefined") return;
|
|
372
|
-
try {
|
|
373
|
-
localStorage.setItem(key, id);
|
|
374
|
-
} catch {
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
return unsubscribe;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// src/core/features/auto-collapse.ts
|
|
381
|
-
function installAutoCollapse(deps) {
|
|
382
|
-
const { ms } = deps;
|
|
383
|
-
if (ms === void 0 || ms <= 0) {
|
|
384
|
-
return () => {
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
let timer = null;
|
|
388
|
-
const clearTimer = () => {
|
|
389
|
-
if (timer !== null) {
|
|
390
|
-
clearTimeout(timer);
|
|
391
|
-
timer = null;
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
const fire = () => {
|
|
395
|
-
if (deps.isDestroyed()) return;
|
|
396
|
-
if (deps.isDragging()) return;
|
|
397
|
-
const active = deps.resolveSnap(deps.getActiveId());
|
|
398
|
-
if (!active || active.size === 0) return;
|
|
399
|
-
let target = null;
|
|
400
|
-
for (const id of deps.getAllowedIds()) {
|
|
401
|
-
const snap = deps.resolveSnap(id);
|
|
402
|
-
if (!snap || snap.size <= 0) continue;
|
|
403
|
-
if (!target || snap.size < target.size) target = snap;
|
|
404
|
-
}
|
|
405
|
-
if (!target) return;
|
|
406
|
-
if (target.id === active.id || target.size >= active.size) return;
|
|
407
|
-
deps.snapTo(target.id);
|
|
408
|
-
};
|
|
409
|
-
const reset = () => {
|
|
410
|
-
clearTimer();
|
|
411
|
-
if (deps.isDestroyed()) return;
|
|
412
|
-
timer = setTimeout(() => {
|
|
413
|
-
timer = null;
|
|
414
|
-
fire();
|
|
415
|
-
}, ms);
|
|
416
|
-
};
|
|
417
|
-
const unsubscribe = deps.on("snap", () => reset());
|
|
418
|
-
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
419
|
-
return () => {
|
|
420
|
-
clearTimer();
|
|
421
|
-
unsubscribe();
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
|
|
425
357
|
// src/core/features/linked-sheets.ts
|
|
426
358
|
function notifyLinkedSheets(sheets, self) {
|
|
427
359
|
if (sheets.length === 0) return;
|
|
@@ -444,394 +376,65 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
444
376
|
}
|
|
445
377
|
}
|
|
446
378
|
|
|
447
|
-
// src/core/features/
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
var pendingRebrand = null;
|
|
453
|
-
var listenerInstalled = false;
|
|
454
|
-
var patchInstalled = false;
|
|
455
|
-
var origPushState = null;
|
|
456
|
-
var origReplaceState = null;
|
|
457
|
-
var patchedPushState = null;
|
|
458
|
-
var patchedReplaceState = null;
|
|
459
|
-
var hasWindow = () => typeof window !== "undefined";
|
|
460
|
-
var hasHistory = () => typeof history !== "undefined";
|
|
461
|
-
var brandMarker = (surface) => ({
|
|
462
|
-
...surface.markerState(),
|
|
463
|
-
__bs: true
|
|
464
|
-
});
|
|
465
|
-
var runInternal = (fn) => {
|
|
466
|
-
internalDepth += 1;
|
|
467
|
-
try {
|
|
468
|
-
fn();
|
|
469
|
-
} finally {
|
|
470
|
-
internalDepth -= 1;
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
var notifyRouteChange = () => {
|
|
474
|
-
const snapshot = Array.from(subscribers);
|
|
475
|
-
for (const fn of snapshot) fn();
|
|
476
|
-
};
|
|
477
|
-
var ensureListener = () => {
|
|
478
|
-
if (listenerInstalled || !hasWindow()) return;
|
|
479
|
-
window.addEventListener("popstate", onPopState);
|
|
480
|
-
listenerInstalled = true;
|
|
481
|
-
};
|
|
482
|
-
var maybeTeardownListener = () => {
|
|
483
|
-
if (!listenerInstalled) return;
|
|
484
|
-
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
485
|
-
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
486
|
-
listenerInstalled = false;
|
|
487
|
-
};
|
|
488
|
-
var installPatch = () => {
|
|
489
|
-
if (patchInstalled || !hasHistory()) return;
|
|
490
|
-
origPushState = history.pushState;
|
|
491
|
-
origReplaceState = history.replaceState;
|
|
492
|
-
patchedPushState = function(...args) {
|
|
493
|
-
origPushState.apply(this, args);
|
|
494
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
495
|
-
};
|
|
496
|
-
patchedReplaceState = function(...args) {
|
|
497
|
-
origReplaceState.apply(this, args);
|
|
498
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
499
|
-
};
|
|
500
|
-
history.pushState = patchedPushState;
|
|
501
|
-
history.replaceState = patchedReplaceState;
|
|
502
|
-
patchInstalled = true;
|
|
503
|
-
};
|
|
504
|
-
var removePatch = () => {
|
|
505
|
-
if (!patchInstalled) return;
|
|
506
|
-
if (history.pushState === patchedPushState && origPushState) {
|
|
507
|
-
history.pushState = origPushState;
|
|
508
|
-
}
|
|
509
|
-
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
510
|
-
history.replaceState = origReplaceState;
|
|
511
|
-
}
|
|
512
|
-
origPushState = null;
|
|
513
|
-
origReplaceState = null;
|
|
514
|
-
patchedPushState = null;
|
|
515
|
-
patchedReplaceState = null;
|
|
516
|
-
patchInstalled = false;
|
|
517
|
-
};
|
|
518
|
-
function onPopState() {
|
|
519
|
-
if (suppress > 0) {
|
|
520
|
-
suppress -= 1;
|
|
521
|
-
const rebrand = pendingRebrand;
|
|
522
|
-
pendingRebrand = null;
|
|
523
|
-
if (rebrand) rebrand();
|
|
524
|
-
maybeTeardownListener();
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
if (entries.length === 0) {
|
|
528
|
-
notifyRouteChange();
|
|
529
|
-
maybeTeardownListener();
|
|
530
|
-
return;
|
|
379
|
+
// src/core/features/resize-observer.ts
|
|
380
|
+
function installResizeObserver(deps) {
|
|
381
|
+
if (typeof window === "undefined") {
|
|
382
|
+
return () => {
|
|
383
|
+
};
|
|
531
384
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
385
|
+
const onResize = () => {
|
|
386
|
+
if (deps.isDestroyed()) return;
|
|
387
|
+
deps.recomputeSnaps();
|
|
388
|
+
const mode = deps.getMode();
|
|
389
|
+
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
390
|
+
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
391
|
+
const max = deps.getMaxAxisSize();
|
|
392
|
+
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
393
|
+
deps.setMaxAxisSize(viewportSize2);
|
|
540
394
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
395
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
396
|
+
deps.cancelInFlight();
|
|
397
|
+
deps.newCycle();
|
|
398
|
+
const current = deps.resolveActiveSnap();
|
|
399
|
+
const newMax = deps.getMaxAxisSize();
|
|
400
|
+
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
401
|
+
deps.setSize(targetSize);
|
|
402
|
+
if (current && !deps.isDragging()) {
|
|
403
|
+
deps.applySize(targetSize);
|
|
404
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
545
405
|
}
|
|
406
|
+
};
|
|
407
|
+
let resizeObserver = null;
|
|
408
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
409
|
+
resizeObserver = new ResizeObserver(onResize);
|
|
410
|
+
resizeObserver.observe(document.documentElement);
|
|
411
|
+
} else {
|
|
412
|
+
window.addEventListener("resize", onResize);
|
|
546
413
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
maybeTeardownListener();
|
|
414
|
+
window.addEventListener("orientationchange", onResize);
|
|
415
|
+
const onVisibility = () => {
|
|
416
|
+
if (deps.isDestroyed()) return;
|
|
417
|
+
if (document.hidden) deps.cancelInFlight();
|
|
418
|
+
};
|
|
419
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
420
|
+
return () => {
|
|
421
|
+
resizeObserver?.disconnect();
|
|
422
|
+
window.removeEventListener("resize", onResize);
|
|
423
|
+
window.removeEventListener("orientationchange", onResize);
|
|
424
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
425
|
+
};
|
|
560
426
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
entries.push(entry);
|
|
573
|
-
ensureListener();
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
function pushBackMarker(surface) {
|
|
577
|
-
const entry = { surface, priorUrl: void 0, live: false };
|
|
578
|
-
if (!hasWindow() || !hasHistory()) {
|
|
579
|
-
return entry;
|
|
580
|
-
}
|
|
581
|
-
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
582
|
-
runInternal(() => {
|
|
583
|
-
try {
|
|
584
|
-
history.pushState(brandMarker(surface), "", surface.url);
|
|
585
|
-
entry.live = true;
|
|
586
|
-
} catch {
|
|
587
|
-
entry.live = false;
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
if (entry.live) {
|
|
591
|
-
entries.push(entry);
|
|
592
|
-
ensureListener();
|
|
593
|
-
}
|
|
594
|
-
return entry;
|
|
595
|
-
}
|
|
596
|
-
function popBackMarker(handle) {
|
|
597
|
-
if (!hasWindow() || !hasHistory()) return;
|
|
598
|
-
const entry = handle;
|
|
599
|
-
const idx = entries.indexOf(entry);
|
|
600
|
-
if (idx === -1 || !entry.live) return;
|
|
601
|
-
const last = entries.length - 1;
|
|
602
|
-
entry.live = false;
|
|
603
|
-
entries.splice(idx, 1);
|
|
604
|
-
if (idx !== last) {
|
|
605
|
-
const rebrandSurface = entries[entries.length - 1].surface;
|
|
606
|
-
const rebrandUrl = entry.priorUrl;
|
|
607
|
-
pendingRebrand = () => {
|
|
608
|
-
runInternal(() => {
|
|
609
|
-
history.replaceState(
|
|
610
|
-
brandMarker(rebrandSurface),
|
|
611
|
-
"",
|
|
612
|
-
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
613
|
-
);
|
|
614
|
-
});
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
suppress += 1;
|
|
618
|
-
runInternal(() => {
|
|
619
|
-
try {
|
|
620
|
-
history.back();
|
|
621
|
-
} catch {
|
|
622
|
-
suppress = Math.max(0, suppress - 1);
|
|
623
|
-
pendingRebrand = null;
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
maybeTeardownListener();
|
|
627
|
-
}
|
|
628
|
-
function subscribeRouteChange(fn) {
|
|
629
|
-
if (!hasWindow() || !hasHistory()) return () => {
|
|
630
|
-
};
|
|
631
|
-
subscribers.add(fn);
|
|
632
|
-
if (subscribers.size === 1) installPatch();
|
|
633
|
-
ensureListener();
|
|
634
|
-
return () => {
|
|
635
|
-
if (!subscribers.has(fn)) return;
|
|
636
|
-
subscribers.delete(fn);
|
|
637
|
-
if (subscribers.size === 0) removePatch();
|
|
638
|
-
maybeTeardownListener();
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// src/core/features/route.ts
|
|
643
|
-
function installRoute(deps) {
|
|
644
|
-
if (typeof window === "undefined") {
|
|
645
|
-
return () => {
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
if (!deps.routedTo && !deps.closeOnBack) {
|
|
649
|
-
return () => {
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
let handle = null;
|
|
653
|
-
const onOpen = () => {
|
|
654
|
-
if (handle) return;
|
|
655
|
-
handle = pushBackMarker({
|
|
656
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
657
|
-
isTop: deps.isTopSheet,
|
|
658
|
-
close: deps.close,
|
|
659
|
-
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
660
|
-
url: deps.routedTo
|
|
661
|
-
});
|
|
662
|
-
};
|
|
663
|
-
const onClose = () => {
|
|
664
|
-
if (!handle) return;
|
|
665
|
-
popBackMarker(handle);
|
|
666
|
-
handle = null;
|
|
667
|
-
};
|
|
668
|
-
const unsubscribeOpen = deps.on("open", onOpen);
|
|
669
|
-
const unsubscribeClose = deps.on("close", onClose);
|
|
670
|
-
if (deps.getSize() > 0) onOpen();
|
|
671
|
-
return () => {
|
|
672
|
-
unsubscribeOpen();
|
|
673
|
-
unsubscribeClose();
|
|
674
|
-
if (handle) {
|
|
675
|
-
popBackMarker(handle);
|
|
676
|
-
handle = null;
|
|
677
|
-
}
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
function installRouteChange(deps) {
|
|
681
|
-
return subscribeRouteChange(() => {
|
|
682
|
-
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
683
|
-
void deps.close();
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// src/core/features/content-swipe.ts
|
|
688
|
-
var CONTENT_PULL_THRESHOLD = 60;
|
|
689
|
-
function installContentSwipe(deps) {
|
|
690
|
-
const { container } = deps;
|
|
691
|
-
let startY = 0;
|
|
692
|
-
let startScrollTop = 0;
|
|
693
|
-
let moved = false;
|
|
694
|
-
const onTouchStart = (e) => {
|
|
695
|
-
const t = e.touches[0];
|
|
696
|
-
if (!t) return;
|
|
697
|
-
startY = t.clientY;
|
|
698
|
-
startScrollTop = container.scrollTop;
|
|
699
|
-
moved = false;
|
|
700
|
-
};
|
|
701
|
-
const onTouchMove = (e) => {
|
|
702
|
-
const t = e.touches[0];
|
|
703
|
-
if (!t) return;
|
|
704
|
-
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
705
|
-
};
|
|
706
|
-
const onTouchEnd = (e) => {
|
|
707
|
-
if (!moved) return;
|
|
708
|
-
if (deps.isDragging() || deps.isAnimating()) return;
|
|
709
|
-
if (container.scrollTop !== startScrollTop) return;
|
|
710
|
-
const t = e.changedTouches[0];
|
|
711
|
-
if (!t) return;
|
|
712
|
-
const deltaY = t.clientY - startY;
|
|
713
|
-
const atTop = container.scrollTop <= 0;
|
|
714
|
-
const allowed = deps.getAllowedIds();
|
|
715
|
-
const idx = allowed.indexOf(deps.getActiveId());
|
|
716
|
-
if (idx === -1) return;
|
|
717
|
-
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
718
|
-
deps.snapTo(allowed[idx - 1]);
|
|
719
|
-
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
720
|
-
deps.snapTo(allowed[idx + 1]);
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
|
-
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
724
|
-
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
725
|
-
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
726
|
-
return () => {
|
|
727
|
-
container.removeEventListener("touchstart", onTouchStart);
|
|
728
|
-
container.removeEventListener("touchmove", onTouchMove);
|
|
729
|
-
container.removeEventListener("touchend", onTouchEnd);
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
// src/core/features/visual-viewport.ts
|
|
734
|
-
var SAFETY_PAD = 8;
|
|
735
|
-
function installVisualViewport(deps) {
|
|
736
|
-
if (typeof window === "undefined" || !window.visualViewport) {
|
|
737
|
-
return () => {
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
const vv = window.visualViewport;
|
|
741
|
-
let rafId = null;
|
|
742
|
-
const onResize = () => {
|
|
743
|
-
if (rafId !== null) return;
|
|
744
|
-
rafId = requestAnimationFrame(() => {
|
|
745
|
-
rafId = null;
|
|
746
|
-
if (deps.isDestroyed()) return;
|
|
747
|
-
deps.recomputeSnaps();
|
|
748
|
-
const isVertical = deps.isVerticalAxis();
|
|
749
|
-
const visible = isVertical ? vv.height : vv.width;
|
|
750
|
-
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
751
|
-
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
752
|
-
if (clamp < deps.getMaxAxisSize()) {
|
|
753
|
-
deps.setMaxAxisSize(clamp);
|
|
754
|
-
}
|
|
755
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
756
|
-
deps.cancelInFlight();
|
|
757
|
-
deps.newCycle();
|
|
758
|
-
const max = deps.getMaxAxisSize();
|
|
759
|
-
deps.setSize(Math.min(deps.getSize(), max));
|
|
760
|
-
const current = deps.resolveActiveSnap();
|
|
761
|
-
if (current && !deps.isDragging()) {
|
|
762
|
-
deps.applySize(Math.min(current.size, max));
|
|
763
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
764
|
-
} else {
|
|
765
|
-
deps.applySize(deps.getSize());
|
|
766
|
-
}
|
|
767
|
-
});
|
|
768
|
-
};
|
|
769
|
-
vv.addEventListener("resize", onResize);
|
|
770
|
-
return () => {
|
|
771
|
-
vv.removeEventListener("resize", onResize);
|
|
772
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
// src/core/features/resize-observer.ts
|
|
777
|
-
function installResizeObserver(deps) {
|
|
778
|
-
if (typeof window === "undefined") {
|
|
779
|
-
return () => {
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
const onResize = () => {
|
|
783
|
-
if (deps.isDestroyed()) return;
|
|
784
|
-
deps.recomputeSnaps();
|
|
785
|
-
const mode = deps.getMode();
|
|
786
|
-
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
787
|
-
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
788
|
-
const max = deps.getMaxAxisSize();
|
|
789
|
-
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
790
|
-
deps.setMaxAxisSize(viewportSize2);
|
|
791
|
-
}
|
|
792
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
793
|
-
deps.cancelInFlight();
|
|
794
|
-
deps.newCycle();
|
|
795
|
-
const current = deps.resolveActiveSnap();
|
|
796
|
-
const newMax = deps.getMaxAxisSize();
|
|
797
|
-
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
798
|
-
deps.setSize(targetSize);
|
|
799
|
-
if (current && !deps.isDragging()) {
|
|
800
|
-
deps.applySize(targetSize);
|
|
801
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
let resizeObserver = null;
|
|
805
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
806
|
-
resizeObserver = new ResizeObserver(onResize);
|
|
807
|
-
resizeObserver.observe(document.documentElement);
|
|
808
|
-
} else {
|
|
809
|
-
window.addEventListener("resize", onResize);
|
|
810
|
-
}
|
|
811
|
-
window.addEventListener("orientationchange", onResize);
|
|
812
|
-
const onVisibility = () => {
|
|
813
|
-
if (deps.isDestroyed()) return;
|
|
814
|
-
if (document.hidden) deps.cancelInFlight();
|
|
815
|
-
};
|
|
816
|
-
document.addEventListener("visibilitychange", onVisibility);
|
|
817
|
-
return () => {
|
|
818
|
-
resizeObserver?.disconnect();
|
|
819
|
-
window.removeEventListener("resize", onResize);
|
|
820
|
-
window.removeEventListener("orientationchange", onResize);
|
|
821
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
822
|
-
};
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
// src/core/features/fit-observer.ts
|
|
826
|
-
var contentTargets = (scroller) => {
|
|
827
|
-
if (!scroller) return [];
|
|
828
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
829
|
-
const out = [];
|
|
830
|
-
for (const child of Array.from(scroller.children)) {
|
|
831
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
832
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
833
|
-
} else {
|
|
834
|
-
out.push(child);
|
|
427
|
+
|
|
428
|
+
// src/core/features/fit-observer.ts
|
|
429
|
+
var contentTargets = (scroller) => {
|
|
430
|
+
if (!scroller) return [];
|
|
431
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
432
|
+
const out = [];
|
|
433
|
+
for (const child of Array.from(scroller.children)) {
|
|
434
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
435
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
436
|
+
} else {
|
|
437
|
+
out.push(child);
|
|
835
438
|
}
|
|
836
439
|
}
|
|
837
440
|
return out;
|
|
@@ -1671,6 +1274,52 @@ function resolveAnimationPreset(animation) {
|
|
|
1671
1274
|
}
|
|
1672
1275
|
}
|
|
1673
1276
|
|
|
1277
|
+
// src/core/animation/waapi-settle.ts
|
|
1278
|
+
var SIM_HZ = 240;
|
|
1279
|
+
var SAMPLE_STRIDE = 4;
|
|
1280
|
+
var MAX_SIM_MS = 3e3;
|
|
1281
|
+
function sampleSpringSettle(from, to, velocityPxPerS, config) {
|
|
1282
|
+
const cfg = { ...DEFAULT_SPRING, ...config };
|
|
1283
|
+
const subDt = 1 / SIM_HZ;
|
|
1284
|
+
const stepMs = SAMPLE_STRIDE / SIM_HZ * 1e3;
|
|
1285
|
+
const maxSteps = Math.ceil(MAX_SIM_MS / 1e3 * SIM_HZ);
|
|
1286
|
+
const values = [from];
|
|
1287
|
+
let x = from;
|
|
1288
|
+
let v = velocityPxPerS;
|
|
1289
|
+
for (let i = 1; i <= maxSteps; i += 1) {
|
|
1290
|
+
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1291
|
+
v += force / cfg.mass * subDt;
|
|
1292
|
+
x += v * subDt;
|
|
1293
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1294
|
+
values.push(to);
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
if (i % SAMPLE_STRIDE === 0) values.push(x);
|
|
1298
|
+
const atRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1299
|
+
if (atRest) break;
|
|
1300
|
+
}
|
|
1301
|
+
if (values[values.length - 1] !== to) values.push(to);
|
|
1302
|
+
return {
|
|
1303
|
+
values,
|
|
1304
|
+
stepMs,
|
|
1305
|
+
durationMs: (values.length - 1) * stepMs
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
function sampleTweenSettle(from, to, durationMs, easing) {
|
|
1309
|
+
const count = Math.max(2, Math.min(60, Math.round(durationMs / 16)));
|
|
1310
|
+
const values = [];
|
|
1311
|
+
for (let i = 0; i <= count; i += 1) {
|
|
1312
|
+
const t = i / count;
|
|
1313
|
+
values.push(from + (to - from) * easing(t));
|
|
1314
|
+
}
|
|
1315
|
+
values[values.length - 1] = to;
|
|
1316
|
+
return {
|
|
1317
|
+
values,
|
|
1318
|
+
stepMs: durationMs / count,
|
|
1319
|
+
durationMs
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1674
1323
|
// src/core/controllers/animation-runner.ts
|
|
1675
1324
|
var DEFAULT_DURATION2 = 220;
|
|
1676
1325
|
var VELOCITY_PX_PER_S = 1e3;
|
|
@@ -1680,6 +1329,10 @@ var AnimationRunner = class {
|
|
|
1680
1329
|
applySizeFn;
|
|
1681
1330
|
getSize;
|
|
1682
1331
|
isDragging;
|
|
1332
|
+
applyAux;
|
|
1333
|
+
getTransformFor;
|
|
1334
|
+
settleWaapi;
|
|
1335
|
+
currentWaapi = null;
|
|
1683
1336
|
animationKind;
|
|
1684
1337
|
springConfig;
|
|
1685
1338
|
duration;
|
|
@@ -1696,6 +1349,9 @@ var AnimationRunner = class {
|
|
|
1696
1349
|
this.applySizeFn = deps.applySize;
|
|
1697
1350
|
this.getSize = deps.getSize;
|
|
1698
1351
|
this.isDragging = deps.isDragging;
|
|
1352
|
+
this.applyAux = deps.applyAux;
|
|
1353
|
+
this.getTransformFor = deps.getTransformFor;
|
|
1354
|
+
this.settleWaapi = opts.settleAnimation === "waapi";
|
|
1699
1355
|
const preset = resolveAnimationPreset(opts.animation);
|
|
1700
1356
|
this.animationKind = preset.kind;
|
|
1701
1357
|
this.duration = opts.duration ?? preset.duration ?? DEFAULT_DURATION2;
|
|
@@ -1720,13 +1376,22 @@ var AnimationRunner = class {
|
|
|
1720
1376
|
}
|
|
1721
1377
|
}
|
|
1722
1378
|
get isAnimating() {
|
|
1723
|
-
return this.currentTween !== null || this.currentSpring !== null;
|
|
1379
|
+
return this.currentTween !== null || this.currentSpring !== null || this.currentWaapi !== null;
|
|
1724
1380
|
}
|
|
1725
1381
|
cancel() {
|
|
1726
1382
|
this.currentTween?.cancel();
|
|
1727
1383
|
this.currentSpring?.cancel();
|
|
1728
|
-
|
|
1729
|
-
|
|
1384
|
+
if (this.currentWaapi) {
|
|
1385
|
+
const entry = this.currentWaapi;
|
|
1386
|
+
this.currentWaapi = null;
|
|
1387
|
+
entry.stop();
|
|
1388
|
+
try {
|
|
1389
|
+
entry.anim.cancel();
|
|
1390
|
+
} catch {
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
async animateTo(target, velocityPxPerMs) {
|
|
1730
1395
|
if (target === this.getSize()) {
|
|
1731
1396
|
if (!this.isAnimating && !this.isDragging()) {
|
|
1732
1397
|
this.element.style.willChange = "";
|
|
@@ -1743,6 +1408,27 @@ var AnimationRunner = class {
|
|
|
1743
1408
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1744
1409
|
return;
|
|
1745
1410
|
}
|
|
1411
|
+
if (this.settleWaapi && this.applyAux && this.getTransformFor && typeof this.element.animate === "function") {
|
|
1412
|
+
const samples = this.animationKind === "spring" ? sampleSpringSettle(
|
|
1413
|
+
this.getSize(),
|
|
1414
|
+
target,
|
|
1415
|
+
velocityPxPerMs * VELOCITY_PX_PER_S,
|
|
1416
|
+
this.springConfig
|
|
1417
|
+
) : sampleTweenSettle(
|
|
1418
|
+
this.getSize(),
|
|
1419
|
+
target,
|
|
1420
|
+
this.duration,
|
|
1421
|
+
this.easing
|
|
1422
|
+
);
|
|
1423
|
+
if (samples.values.length >= 2 && samples.durationMs > 0) {
|
|
1424
|
+
await this.runWaapiSettle(samples, target);
|
|
1425
|
+
if (!this.isAnimating) {
|
|
1426
|
+
this.getRootEl()?.removeAttribute("data-animating");
|
|
1427
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1428
|
+
}
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1746
1432
|
if (this.animationKind === "spring") {
|
|
1747
1433
|
const spring = runSpring({
|
|
1748
1434
|
from: this.getSize(),
|
|
@@ -1771,11 +1457,66 @@ var AnimationRunner = class {
|
|
|
1771
1457
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1772
1458
|
}
|
|
1773
1459
|
}
|
|
1460
|
+
async runWaapiSettle(samples, target) {
|
|
1461
|
+
const applyAux = this.applyAux;
|
|
1462
|
+
const getTransformFor = this.getTransformFor;
|
|
1463
|
+
const frames = samples.values.map((v) => ({
|
|
1464
|
+
transform: getTransformFor(v)
|
|
1465
|
+
}));
|
|
1466
|
+
const anim = this.element.animate(frames, {
|
|
1467
|
+
duration: samples.durationMs,
|
|
1468
|
+
easing: "linear",
|
|
1469
|
+
fill: "forwards"
|
|
1470
|
+
});
|
|
1471
|
+
let stopped = false;
|
|
1472
|
+
let auxRaf = 0;
|
|
1473
|
+
const start = performance.now();
|
|
1474
|
+
const lastIdx = samples.values.length - 1;
|
|
1475
|
+
const auxTick = () => {
|
|
1476
|
+
if (stopped) return;
|
|
1477
|
+
const elapsed = performance.now() - start;
|
|
1478
|
+
const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
|
|
1479
|
+
applyAux(samples.values[idx]);
|
|
1480
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1481
|
+
};
|
|
1482
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1483
|
+
const entry = {
|
|
1484
|
+
anim,
|
|
1485
|
+
stop: () => {
|
|
1486
|
+
stopped = true;
|
|
1487
|
+
cancelAnimationFrame(auxRaf);
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
this.currentWaapi = entry;
|
|
1491
|
+
try {
|
|
1492
|
+
await anim.finished;
|
|
1493
|
+
} catch {
|
|
1494
|
+
}
|
|
1495
|
+
entry.stop();
|
|
1496
|
+
const wasCurrent = this.currentWaapi === entry;
|
|
1497
|
+
if (wasCurrent) this.currentWaapi = null;
|
|
1498
|
+
if (wasCurrent && anim.playState === "finished") {
|
|
1499
|
+
this.applySizeFn(target);
|
|
1500
|
+
try {
|
|
1501
|
+
anim.cancel();
|
|
1502
|
+
} catch {
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1774
1506
|
destroy() {
|
|
1775
1507
|
this.detachReducedMotion?.();
|
|
1776
1508
|
this.detachReducedMotion = null;
|
|
1777
1509
|
this.currentTween = null;
|
|
1778
1510
|
this.currentSpring = null;
|
|
1511
|
+
if (this.currentWaapi) {
|
|
1512
|
+
const entry = this.currentWaapi;
|
|
1513
|
+
this.currentWaapi = null;
|
|
1514
|
+
entry.stop();
|
|
1515
|
+
try {
|
|
1516
|
+
entry.anim.cancel();
|
|
1517
|
+
} catch {
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1779
1520
|
}
|
|
1780
1521
|
};
|
|
1781
1522
|
|
|
@@ -2633,7 +2374,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2633
2374
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2634
2375
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2635
2376
|
if (opts.persistKey) {
|
|
2636
|
-
const restored =
|
|
2377
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2637
2378
|
if (restored && initialAllowed.includes(restored)) {
|
|
2638
2379
|
initialId = restored;
|
|
2639
2380
|
}
|
|
@@ -2664,6 +2405,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2664
2405
|
},
|
|
2665
2406
|
animation: {
|
|
2666
2407
|
animation: opts.animation,
|
|
2408
|
+
settleAnimation: opts.settleAnimation,
|
|
2667
2409
|
duration: opts.duration,
|
|
2668
2410
|
easing: opts.easing,
|
|
2669
2411
|
spring: opts.spring,
|
|
@@ -2681,6 +2423,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2681
2423
|
}
|
|
2682
2424
|
};
|
|
2683
2425
|
}
|
|
2426
|
+
var readPersistedIdSafe = (key) => {
|
|
2427
|
+
if (typeof window === "undefined") return null;
|
|
2428
|
+
if (typeof localStorage === "undefined") return null;
|
|
2429
|
+
try {
|
|
2430
|
+
return localStorage.getItem(key);
|
|
2431
|
+
} catch {
|
|
2432
|
+
return null;
|
|
2433
|
+
}
|
|
2434
|
+
};
|
|
2684
2435
|
|
|
2685
2436
|
// src/core/primitives/teardown-stack.ts
|
|
2686
2437
|
var TeardownStack = class {
|
|
@@ -2701,9 +2452,9 @@ var TeardownStack = class {
|
|
|
2701
2452
|
}
|
|
2702
2453
|
};
|
|
2703
2454
|
|
|
2704
|
-
// src/core/
|
|
2455
|
+
// src/core/BottomSheetCore.ts
|
|
2705
2456
|
var HAPTIC_DURATION_MS = 8;
|
|
2706
|
-
var
|
|
2457
|
+
var BottomSheetCore = class {
|
|
2707
2458
|
id = nextInstanceId("bs");
|
|
2708
2459
|
element;
|
|
2709
2460
|
handle;
|
|
@@ -2763,6 +2514,8 @@ var BottomSheetEngine = class {
|
|
|
2763
2514
|
stackEffectPrimed = false;
|
|
2764
2515
|
fitDeps;
|
|
2765
2516
|
transformTemplate;
|
|
2517
|
+
featureList = [];
|
|
2518
|
+
featureCtx;
|
|
2766
2519
|
constructor(opts) {
|
|
2767
2520
|
const resolved = resolveEngineOptions(opts, {
|
|
2768
2521
|
shouldApplyInertSiblings: () => {
|
|
@@ -2810,7 +2563,9 @@ var BottomSheetEngine = class {
|
|
|
2810
2563
|
getRootEl: () => this.rootEl,
|
|
2811
2564
|
applySize: (size) => this.applySize(size),
|
|
2812
2565
|
getSize: () => this.size,
|
|
2813
|
-
isDragging: () => this.gesture?.isDragging ?? false
|
|
2566
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2567
|
+
applyAux: (size) => this.applySize(size, true),
|
|
2568
|
+
getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
|
|
2814
2569
|
},
|
|
2815
2570
|
resolved.animation
|
|
2816
2571
|
);
|
|
@@ -2833,6 +2588,11 @@ var BottomSheetEngine = class {
|
|
|
2833
2588
|
if (opts.linkedSheets) {
|
|
2834
2589
|
this.linkedSheets = opts.linkedSheets;
|
|
2835
2590
|
}
|
|
2591
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2592
|
+
for (const feature of opts.features ?? []) {
|
|
2593
|
+
byName.set(feature.name, feature);
|
|
2594
|
+
}
|
|
2595
|
+
this.featureList = Array.from(byName.values());
|
|
2836
2596
|
this.activeId = resolved.initialId;
|
|
2837
2597
|
auditVhUsage(this.snapPointsRaw);
|
|
2838
2598
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
@@ -2869,6 +2629,7 @@ var BottomSheetEngine = class {
|
|
|
2869
2629
|
scrollContainer: this.scrollContainer,
|
|
2870
2630
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize()
|
|
2871
2631
|
});
|
|
2632
|
+
this.featureCtx = this.buildFeatureContext(opts.autoCollapseAfter);
|
|
2872
2633
|
this.attach();
|
|
2873
2634
|
this.registerInStack();
|
|
2874
2635
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
@@ -2900,46 +2661,77 @@ var BottomSheetEngine = class {
|
|
|
2900
2661
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2901
2662
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2902
2663
|
this.applyAutoAriaLabelledBy();
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
getSize: () => this.size,
|
|
2908
|
-
close: () => this.close()
|
|
2909
|
-
})
|
|
2910
|
-
);
|
|
2911
|
-
}
|
|
2912
|
-
if (this.persistKey) {
|
|
2913
|
-
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2664
|
+
this.runFeatureStage("post");
|
|
2665
|
+
this.warnOrphanFeatureOptions();
|
|
2666
|
+
if (this.size > 0) {
|
|
2667
|
+
this.handleOpen();
|
|
2914
2668
|
}
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
resolveSnap: (id) => this.snaps.findById(id),
|
|
2923
|
-
snapTo: (id) => {
|
|
2924
|
-
void this.snapTo(id);
|
|
2925
|
-
},
|
|
2926
|
-
on: (event, fn) => this.on(event, fn)
|
|
2927
|
-
})
|
|
2928
|
-
);
|
|
2929
|
-
this.teardowns.add(
|
|
2930
|
-
installRoute({
|
|
2669
|
+
}
|
|
2670
|
+
buildFeatureContext(autoCollapseAfter) {
|
|
2671
|
+
return {
|
|
2672
|
+
element: this.element,
|
|
2673
|
+
scrollContainer: this.scrollContainer,
|
|
2674
|
+
sheetId: this.id,
|
|
2675
|
+
options: {
|
|
2931
2676
|
routedTo: this.routedTo,
|
|
2932
2677
|
closeOnBack: this.closeOnBack,
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
this.
|
|
2678
|
+
closeOnRouteChange: this.closeOnRouteChange,
|
|
2679
|
+
persistKey: this.persistKey,
|
|
2680
|
+
autoCollapseAfter
|
|
2681
|
+
},
|
|
2682
|
+
isDestroyed: () => this.destroyed,
|
|
2683
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2684
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2685
|
+
isTopSheet: () => this.isTopSheet,
|
|
2686
|
+
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
2687
|
+
getSize: () => this.size,
|
|
2688
|
+
getActiveId: () => this.activeId,
|
|
2689
|
+
getAllowedIds: () => this.snaps.getAllowedIds().slice(),
|
|
2690
|
+
allowedIdsBySize: () => this.allowedIdsBySize(),
|
|
2691
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2692
|
+
resolveSnap: (id) => this.snaps.findById(id),
|
|
2693
|
+
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
2694
|
+
setSize: (size) => {
|
|
2695
|
+
this.size = size;
|
|
2696
|
+
},
|
|
2697
|
+
setMaxAxisSize: (size) => {
|
|
2698
|
+
this.snaps.setMaxAxisSize(size);
|
|
2699
|
+
},
|
|
2700
|
+
applySize: (size) => this.applySize(size),
|
|
2701
|
+
recomputeSnaps: () => this.recomputeSnaps(),
|
|
2702
|
+
newCycle: () => {
|
|
2703
|
+
this.newCycle();
|
|
2704
|
+
},
|
|
2705
|
+
cancelInFlight: () => {
|
|
2706
|
+
this.animation.cancel();
|
|
2707
|
+
},
|
|
2708
|
+
resyncAfterResize: () => this.resyncAfterResize(),
|
|
2709
|
+
snapTo: (id) => {
|
|
2710
|
+
void this.snapTo(id);
|
|
2711
|
+
},
|
|
2712
|
+
close: (reason) => this.close(reason),
|
|
2713
|
+
on: (event, fn) => this.on(event, fn),
|
|
2714
|
+
addTeardown: (fn) => this.teardowns.add(fn)
|
|
2715
|
+
};
|
|
2716
|
+
}
|
|
2717
|
+
runFeatureStage(stage) {
|
|
2718
|
+
for (const feature of this.featureList) {
|
|
2719
|
+
if ((feature.stage ?? "post") !== stage) continue;
|
|
2720
|
+
const teardown = feature.install(this.featureCtx);
|
|
2721
|
+
if (teardown) this.teardowns.add(teardown);
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
warnOrphanFeatureOptions() {
|
|
2725
|
+
const names = new Set(this.featureList.map((f) => f.name));
|
|
2726
|
+
if ((this.closeOnBack || this.routedTo !== void 0 || this.closeOnRouteChange) && !names.has("route")) {
|
|
2727
|
+
devWarn(
|
|
2728
|
+
"[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
|
|
2729
|
+
);
|
|
2730
|
+
}
|
|
2731
|
+
if (this.persistKey && !names.has("persist")) {
|
|
2732
|
+
devWarn(
|
|
2733
|
+
"[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
|
|
2734
|
+
);
|
|
2943
2735
|
}
|
|
2944
2736
|
}
|
|
2945
2737
|
get state() {
|
|
@@ -3482,18 +3274,7 @@ var BottomSheetEngine = class {
|
|
|
3482
3274
|
}
|
|
3483
3275
|
}
|
|
3484
3276
|
attachFeatures() {
|
|
3485
|
-
|
|
3486
|
-
this.teardowns.add(installContentSwipe({
|
|
3487
|
-
container: this.scrollContainer,
|
|
3488
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3489
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3490
|
-
getAllowedIds: () => this.allowedIdsBySize(),
|
|
3491
|
-
getActiveId: () => this.activeId,
|
|
3492
|
-
snapTo: (id) => {
|
|
3493
|
-
void this.snapTo(id);
|
|
3494
|
-
}
|
|
3495
|
-
}));
|
|
3496
|
-
}
|
|
3277
|
+
this.runFeatureStage("attach");
|
|
3497
3278
|
if (typeof window !== "undefined") {
|
|
3498
3279
|
this.teardowns.add(installResizeObserver({
|
|
3499
3280
|
element: this.element,
|
|
@@ -3533,31 +3314,6 @@ var BottomSheetEngine = class {
|
|
|
3533
3314
|
() => document.removeEventListener("keydown", onKey)
|
|
3534
3315
|
);
|
|
3535
3316
|
}
|
|
3536
|
-
this.teardowns.add(installVisualViewport({
|
|
3537
|
-
element: this.element,
|
|
3538
|
-
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
3539
|
-
isDestroyed: () => this.destroyed,
|
|
3540
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3541
|
-
recomputeSnaps: () => this.recomputeSnaps(),
|
|
3542
|
-
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3543
|
-
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3544
|
-
getSize: () => this.size,
|
|
3545
|
-
setMaxAxisSize: (size) => {
|
|
3546
|
-
this.snaps.setMaxAxisSize(size);
|
|
3547
|
-
},
|
|
3548
|
-
setSize: (size) => {
|
|
3549
|
-
this.size = size;
|
|
3550
|
-
},
|
|
3551
|
-
applySize: (size) => this.applySize(size),
|
|
3552
|
-
cancelInFlight: () => {
|
|
3553
|
-
this.animation.cancel();
|
|
3554
|
-
},
|
|
3555
|
-
newCycle: () => {
|
|
3556
|
-
this.newCycle();
|
|
3557
|
-
},
|
|
3558
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3559
|
-
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3560
|
-
}));
|
|
3561
3317
|
}
|
|
3562
3318
|
this.teardowns.add(installSliderKeyboard({
|
|
3563
3319
|
handle: this.handle,
|
|
@@ -3634,13 +3390,13 @@ var BottomSheetEngine = class {
|
|
|
3634
3390
|
}
|
|
3635
3391
|
}
|
|
3636
3392
|
}
|
|
3637
|
-
applySize(size) {
|
|
3393
|
+
applySize(size, skipTransform = false) {
|
|
3638
3394
|
const cap = this.snaps.getMaxAxisSize();
|
|
3639
3395
|
const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
|
|
3640
3396
|
this.size = clamped;
|
|
3641
3397
|
const offset = cap - clamped;
|
|
3642
3398
|
const style = this.element.style;
|
|
3643
|
-
style.transform = this.transformTemplate(offset);
|
|
3399
|
+
if (!skipTransform) style.transform = this.transformTemplate(offset);
|
|
3644
3400
|
if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
|
|
3645
3401
|
style.setProperty("--bs-size", `${clamped}px`);
|
|
3646
3402
|
if (this.scrimParent) {
|
|
@@ -3718,6 +3474,514 @@ var BottomSheetEngine = class {
|
|
|
3718
3474
|
}
|
|
3719
3475
|
};
|
|
3720
3476
|
|
|
3477
|
+
// src/core/features/history-coordinator.ts
|
|
3478
|
+
var entries = [];
|
|
3479
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3480
|
+
var suppress = 0;
|
|
3481
|
+
var internalDepth = 0;
|
|
3482
|
+
var pendingRebrands = [];
|
|
3483
|
+
var listenerInstalled = false;
|
|
3484
|
+
var patchInstalled = false;
|
|
3485
|
+
var origPushState = null;
|
|
3486
|
+
var origReplaceState = null;
|
|
3487
|
+
var patchedPushState = null;
|
|
3488
|
+
var patchedReplaceState = null;
|
|
3489
|
+
var hasWindow = () => typeof window !== "undefined";
|
|
3490
|
+
var hasHistory = () => typeof history !== "undefined";
|
|
3491
|
+
var brandMarker = (surface) => ({
|
|
3492
|
+
...surface.markerState(),
|
|
3493
|
+
__bs: true
|
|
3494
|
+
});
|
|
3495
|
+
var runInternal = (fn) => {
|
|
3496
|
+
internalDepth += 1;
|
|
3497
|
+
try {
|
|
3498
|
+
fn();
|
|
3499
|
+
} finally {
|
|
3500
|
+
internalDepth -= 1;
|
|
3501
|
+
}
|
|
3502
|
+
};
|
|
3503
|
+
var notifyRouteChange = () => {
|
|
3504
|
+
const snapshot = Array.from(subscribers);
|
|
3505
|
+
for (const fn of snapshot) fn();
|
|
3506
|
+
};
|
|
3507
|
+
var ensureListener = () => {
|
|
3508
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
3509
|
+
window.addEventListener("popstate", onPopState);
|
|
3510
|
+
listenerInstalled = true;
|
|
3511
|
+
};
|
|
3512
|
+
var maybeTeardownListener = () => {
|
|
3513
|
+
if (!listenerInstalled) return;
|
|
3514
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
3515
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
3516
|
+
listenerInstalled = false;
|
|
3517
|
+
};
|
|
3518
|
+
var installPatch = () => {
|
|
3519
|
+
if (patchInstalled || !hasHistory()) return;
|
|
3520
|
+
origPushState = history.pushState;
|
|
3521
|
+
origReplaceState = history.replaceState;
|
|
3522
|
+
patchedPushState = function(...args) {
|
|
3523
|
+
origPushState.apply(this, args);
|
|
3524
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3525
|
+
};
|
|
3526
|
+
patchedReplaceState = function(...args) {
|
|
3527
|
+
origReplaceState.apply(this, args);
|
|
3528
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3529
|
+
};
|
|
3530
|
+
history.pushState = patchedPushState;
|
|
3531
|
+
history.replaceState = patchedReplaceState;
|
|
3532
|
+
patchInstalled = true;
|
|
3533
|
+
};
|
|
3534
|
+
var removePatch = () => {
|
|
3535
|
+
if (!patchInstalled) return;
|
|
3536
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
3537
|
+
history.pushState = origPushState;
|
|
3538
|
+
}
|
|
3539
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
3540
|
+
history.replaceState = origReplaceState;
|
|
3541
|
+
}
|
|
3542
|
+
origPushState = null;
|
|
3543
|
+
origReplaceState = null;
|
|
3544
|
+
patchedPushState = null;
|
|
3545
|
+
patchedReplaceState = null;
|
|
3546
|
+
patchInstalled = false;
|
|
3547
|
+
};
|
|
3548
|
+
function onPopState() {
|
|
3549
|
+
if (suppress > 0) {
|
|
3550
|
+
suppress -= 1;
|
|
3551
|
+
const rebrand = pendingRebrands.shift();
|
|
3552
|
+
if (rebrand) rebrand();
|
|
3553
|
+
maybeTeardownListener();
|
|
3554
|
+
return;
|
|
3555
|
+
}
|
|
3556
|
+
if (entries.length === 0) {
|
|
3557
|
+
notifyRouteChange();
|
|
3558
|
+
maybeTeardownListener();
|
|
3559
|
+
return;
|
|
3560
|
+
}
|
|
3561
|
+
let target = null;
|
|
3562
|
+
let targetIdx = -1;
|
|
3563
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3564
|
+
const entry = entries[i];
|
|
3565
|
+
if (!entry.surface.isOpen()) continue;
|
|
3566
|
+
if (!target) {
|
|
3567
|
+
target = entry;
|
|
3568
|
+
targetIdx = i;
|
|
3569
|
+
}
|
|
3570
|
+
if (entry.surface.isTop()) {
|
|
3571
|
+
target = entry;
|
|
3572
|
+
targetIdx = i;
|
|
3573
|
+
break;
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
if (!target) {
|
|
3577
|
+
const removed = entries.pop();
|
|
3578
|
+
if (removed) removed.live = false;
|
|
3579
|
+
maybeTeardownListener();
|
|
3580
|
+
return;
|
|
3581
|
+
}
|
|
3582
|
+
target.live = false;
|
|
3583
|
+
entries.splice(targetIdx, 1);
|
|
3584
|
+
const settled = target;
|
|
3585
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
3586
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
3587
|
+
});
|
|
3588
|
+
maybeTeardownListener();
|
|
3589
|
+
}
|
|
3590
|
+
function restore(entry) {
|
|
3591
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3592
|
+
entry.live = true;
|
|
3593
|
+
runInternal(() => {
|
|
3594
|
+
try {
|
|
3595
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
3596
|
+
} catch {
|
|
3597
|
+
entry.live = false;
|
|
3598
|
+
}
|
|
3599
|
+
});
|
|
3600
|
+
if (entry.live) {
|
|
3601
|
+
entries.push(entry);
|
|
3602
|
+
ensureListener();
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
function pushBackMarker(surface) {
|
|
3606
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
3607
|
+
if (!hasWindow() || !hasHistory()) {
|
|
3608
|
+
return entry;
|
|
3609
|
+
}
|
|
3610
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
3611
|
+
runInternal(() => {
|
|
3612
|
+
try {
|
|
3613
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
3614
|
+
entry.live = true;
|
|
3615
|
+
} catch {
|
|
3616
|
+
entry.live = false;
|
|
3617
|
+
}
|
|
3618
|
+
});
|
|
3619
|
+
if (entry.live) {
|
|
3620
|
+
entries.push(entry);
|
|
3621
|
+
ensureListener();
|
|
3622
|
+
}
|
|
3623
|
+
return entry;
|
|
3624
|
+
}
|
|
3625
|
+
function popBackMarker(handle) {
|
|
3626
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3627
|
+
const entry = handle;
|
|
3628
|
+
const idx = entries.indexOf(entry);
|
|
3629
|
+
if (idx === -1 || !entry.live) return;
|
|
3630
|
+
const last = entries.length - 1;
|
|
3631
|
+
entry.live = false;
|
|
3632
|
+
entries.splice(idx, 1);
|
|
3633
|
+
let rebrand = null;
|
|
3634
|
+
if (idx !== last) {
|
|
3635
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
3636
|
+
const rebrandUrl = entry.priorUrl;
|
|
3637
|
+
rebrand = () => {
|
|
3638
|
+
runInternal(() => {
|
|
3639
|
+
history.replaceState(
|
|
3640
|
+
brandMarker(rebrandSurface),
|
|
3641
|
+
"",
|
|
3642
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
3643
|
+
);
|
|
3644
|
+
});
|
|
3645
|
+
};
|
|
3646
|
+
}
|
|
3647
|
+
pendingRebrands.push(rebrand);
|
|
3648
|
+
suppress += 1;
|
|
3649
|
+
runInternal(() => {
|
|
3650
|
+
try {
|
|
3651
|
+
history.back();
|
|
3652
|
+
} catch {
|
|
3653
|
+
suppress = Math.max(0, suppress - 1);
|
|
3654
|
+
pendingRebrands.pop();
|
|
3655
|
+
}
|
|
3656
|
+
});
|
|
3657
|
+
maybeTeardownListener();
|
|
3658
|
+
}
|
|
3659
|
+
function subscribeRouteChange(fn) {
|
|
3660
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
3661
|
+
};
|
|
3662
|
+
subscribers.add(fn);
|
|
3663
|
+
if (subscribers.size === 1) installPatch();
|
|
3664
|
+
ensureListener();
|
|
3665
|
+
return () => {
|
|
3666
|
+
if (!subscribers.has(fn)) return;
|
|
3667
|
+
subscribers.delete(fn);
|
|
3668
|
+
if (subscribers.size === 0) removePatch();
|
|
3669
|
+
maybeTeardownListener();
|
|
3670
|
+
};
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
// src/core/features/route.ts
|
|
3674
|
+
function installRoute(deps) {
|
|
3675
|
+
if (typeof window === "undefined") {
|
|
3676
|
+
return () => {
|
|
3677
|
+
};
|
|
3678
|
+
}
|
|
3679
|
+
if (!deps.routedTo && !deps.closeOnBack) {
|
|
3680
|
+
return () => {
|
|
3681
|
+
};
|
|
3682
|
+
}
|
|
3683
|
+
let handle = null;
|
|
3684
|
+
const onOpen = () => {
|
|
3685
|
+
if (handle) return;
|
|
3686
|
+
handle = pushBackMarker({
|
|
3687
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
3688
|
+
isTop: deps.isTopSheet,
|
|
3689
|
+
close: deps.close,
|
|
3690
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
3691
|
+
url: deps.routedTo
|
|
3692
|
+
});
|
|
3693
|
+
};
|
|
3694
|
+
const onClose = () => {
|
|
3695
|
+
if (!handle) return;
|
|
3696
|
+
popBackMarker(handle);
|
|
3697
|
+
handle = null;
|
|
3698
|
+
};
|
|
3699
|
+
const unsubscribeOpen = deps.on("open", onOpen);
|
|
3700
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
3701
|
+
if (deps.getSize() > 0) onOpen();
|
|
3702
|
+
return () => {
|
|
3703
|
+
unsubscribeOpen();
|
|
3704
|
+
unsubscribeClose();
|
|
3705
|
+
if (handle) {
|
|
3706
|
+
popBackMarker(handle);
|
|
3707
|
+
handle = null;
|
|
3708
|
+
}
|
|
3709
|
+
};
|
|
3710
|
+
}
|
|
3711
|
+
function installRouteChange(deps) {
|
|
3712
|
+
return subscribeRouteChange(() => {
|
|
3713
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
3714
|
+
void deps.close();
|
|
3715
|
+
});
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
// src/core/features/persist.ts
|
|
3719
|
+
function installPersist(engine, key) {
|
|
3720
|
+
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
3721
|
+
if (typeof window === "undefined") return;
|
|
3722
|
+
if (typeof localStorage === "undefined") return;
|
|
3723
|
+
try {
|
|
3724
|
+
localStorage.setItem(key, id);
|
|
3725
|
+
} catch {
|
|
3726
|
+
}
|
|
3727
|
+
});
|
|
3728
|
+
return unsubscribe;
|
|
3729
|
+
}
|
|
3730
|
+
|
|
3731
|
+
// src/core/features/auto-collapse.ts
|
|
3732
|
+
function installAutoCollapse(deps) {
|
|
3733
|
+
const { ms } = deps;
|
|
3734
|
+
if (ms === void 0 || ms <= 0) {
|
|
3735
|
+
return () => {
|
|
3736
|
+
};
|
|
3737
|
+
}
|
|
3738
|
+
let timer = null;
|
|
3739
|
+
const clearTimer = () => {
|
|
3740
|
+
if (timer !== null) {
|
|
3741
|
+
clearTimeout(timer);
|
|
3742
|
+
timer = null;
|
|
3743
|
+
}
|
|
3744
|
+
};
|
|
3745
|
+
const fire = () => {
|
|
3746
|
+
if (deps.isDestroyed()) return;
|
|
3747
|
+
if (deps.isDragging()) return;
|
|
3748
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
3749
|
+
if (!active || active.size === 0) return;
|
|
3750
|
+
let target = null;
|
|
3751
|
+
for (const id of deps.getAllowedIds()) {
|
|
3752
|
+
const snap = deps.resolveSnap(id);
|
|
3753
|
+
if (!snap || snap.size <= 0) continue;
|
|
3754
|
+
if (!target || snap.size < target.size) target = snap;
|
|
3755
|
+
}
|
|
3756
|
+
if (!target) return;
|
|
3757
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
3758
|
+
deps.snapTo(target.id);
|
|
3759
|
+
};
|
|
3760
|
+
const reset = () => {
|
|
3761
|
+
clearTimer();
|
|
3762
|
+
if (deps.isDestroyed()) return;
|
|
3763
|
+
timer = setTimeout(() => {
|
|
3764
|
+
timer = null;
|
|
3765
|
+
fire();
|
|
3766
|
+
}, ms);
|
|
3767
|
+
};
|
|
3768
|
+
const unsubscribe = deps.on("snap", () => reset());
|
|
3769
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
3770
|
+
return () => {
|
|
3771
|
+
clearTimer();
|
|
3772
|
+
unsubscribe();
|
|
3773
|
+
};
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
// src/core/features/content-swipe.ts
|
|
3777
|
+
var CONTENT_PULL_THRESHOLD = 60;
|
|
3778
|
+
function installContentSwipe(deps) {
|
|
3779
|
+
const { container } = deps;
|
|
3780
|
+
let startY = 0;
|
|
3781
|
+
let startScrollTop = 0;
|
|
3782
|
+
let moved = false;
|
|
3783
|
+
const onTouchStart = (e) => {
|
|
3784
|
+
const t = e.touches[0];
|
|
3785
|
+
if (!t) return;
|
|
3786
|
+
startY = t.clientY;
|
|
3787
|
+
startScrollTop = container.scrollTop;
|
|
3788
|
+
moved = false;
|
|
3789
|
+
};
|
|
3790
|
+
const onTouchMove = (e) => {
|
|
3791
|
+
const t = e.touches[0];
|
|
3792
|
+
if (!t) return;
|
|
3793
|
+
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
3794
|
+
};
|
|
3795
|
+
const onTouchEnd = (e) => {
|
|
3796
|
+
if (!moved) return;
|
|
3797
|
+
if (deps.isDragging() || deps.isAnimating()) return;
|
|
3798
|
+
if (container.scrollTop !== startScrollTop) return;
|
|
3799
|
+
const t = e.changedTouches[0];
|
|
3800
|
+
if (!t) return;
|
|
3801
|
+
const deltaY = t.clientY - startY;
|
|
3802
|
+
const atTop = container.scrollTop <= 0;
|
|
3803
|
+
const allowed = deps.getAllowedIds();
|
|
3804
|
+
const idx = allowed.indexOf(deps.getActiveId());
|
|
3805
|
+
if (idx === -1) return;
|
|
3806
|
+
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
3807
|
+
deps.snapTo(allowed[idx - 1]);
|
|
3808
|
+
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
3809
|
+
deps.snapTo(allowed[idx + 1]);
|
|
3810
|
+
}
|
|
3811
|
+
};
|
|
3812
|
+
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
3813
|
+
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
3814
|
+
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
3815
|
+
return () => {
|
|
3816
|
+
container.removeEventListener("touchstart", onTouchStart);
|
|
3817
|
+
container.removeEventListener("touchmove", onTouchMove);
|
|
3818
|
+
container.removeEventListener("touchend", onTouchEnd);
|
|
3819
|
+
};
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
// src/core/features/visual-viewport.ts
|
|
3823
|
+
var SAFETY_PAD = 8;
|
|
3824
|
+
function installVisualViewport(deps) {
|
|
3825
|
+
if (typeof window === "undefined" || !window.visualViewport) {
|
|
3826
|
+
return () => {
|
|
3827
|
+
};
|
|
3828
|
+
}
|
|
3829
|
+
const vv = window.visualViewport;
|
|
3830
|
+
let rafId = null;
|
|
3831
|
+
const onResize = () => {
|
|
3832
|
+
if (rafId !== null) return;
|
|
3833
|
+
rafId = requestAnimationFrame(() => {
|
|
3834
|
+
rafId = null;
|
|
3835
|
+
if (deps.isDestroyed()) return;
|
|
3836
|
+
deps.recomputeSnaps();
|
|
3837
|
+
const isVertical = deps.isVerticalAxis();
|
|
3838
|
+
const visible = isVertical ? vv.height : vv.width;
|
|
3839
|
+
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
3840
|
+
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
3841
|
+
if (clamp < deps.getMaxAxisSize()) {
|
|
3842
|
+
deps.setMaxAxisSize(clamp);
|
|
3843
|
+
}
|
|
3844
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
3845
|
+
deps.cancelInFlight();
|
|
3846
|
+
deps.newCycle();
|
|
3847
|
+
const max = deps.getMaxAxisSize();
|
|
3848
|
+
deps.setSize(Math.min(deps.getSize(), max));
|
|
3849
|
+
const current = deps.resolveActiveSnap();
|
|
3850
|
+
if (current && !deps.isDragging()) {
|
|
3851
|
+
deps.applySize(Math.min(current.size, max));
|
|
3852
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
3853
|
+
} else {
|
|
3854
|
+
deps.applySize(deps.getSize());
|
|
3855
|
+
}
|
|
3856
|
+
});
|
|
3857
|
+
};
|
|
3858
|
+
vv.addEventListener("resize", onResize);
|
|
3859
|
+
return () => {
|
|
3860
|
+
vv.removeEventListener("resize", onResize);
|
|
3861
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
3862
|
+
};
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
// src/core/features/engine-features.ts
|
|
3866
|
+
function routeFeature() {
|
|
3867
|
+
return {
|
|
3868
|
+
name: "route",
|
|
3869
|
+
install: (ctx) => {
|
|
3870
|
+
const teardowns = new TeardownStack();
|
|
3871
|
+
if (ctx.options.closeOnRouteChange) {
|
|
3872
|
+
teardowns.add(
|
|
3873
|
+
installRouteChange({
|
|
3874
|
+
isDestroyed: ctx.isDestroyed,
|
|
3875
|
+
getSize: ctx.getSize,
|
|
3876
|
+
close: () => ctx.close()
|
|
3877
|
+
})
|
|
3878
|
+
);
|
|
3879
|
+
}
|
|
3880
|
+
teardowns.add(
|
|
3881
|
+
installRoute({
|
|
3882
|
+
routedTo: ctx.options.routedTo,
|
|
3883
|
+
closeOnBack: ctx.options.closeOnBack,
|
|
3884
|
+
isTopSheet: ctx.isTopSheet,
|
|
3885
|
+
getSize: ctx.getSize,
|
|
3886
|
+
isDestroyed: ctx.isDestroyed,
|
|
3887
|
+
close: () => ctx.close("back"),
|
|
3888
|
+
on: ctx.on,
|
|
3889
|
+
sheetId: ctx.sheetId
|
|
3890
|
+
})
|
|
3891
|
+
);
|
|
3892
|
+
return () => teardowns.drain();
|
|
3893
|
+
}
|
|
3894
|
+
};
|
|
3895
|
+
}
|
|
3896
|
+
function persistFeature() {
|
|
3897
|
+
return {
|
|
3898
|
+
name: "persist",
|
|
3899
|
+
install: (ctx) => {
|
|
3900
|
+
const key = ctx.options.persistKey;
|
|
3901
|
+
if (!key) return;
|
|
3902
|
+
return installPersist({ on: ctx.on }, key);
|
|
3903
|
+
}
|
|
3904
|
+
};
|
|
3905
|
+
}
|
|
3906
|
+
function autoCollapseFeature() {
|
|
3907
|
+
return {
|
|
3908
|
+
name: "auto-collapse",
|
|
3909
|
+
install: (ctx) => installAutoCollapse({
|
|
3910
|
+
ms: ctx.options.autoCollapseAfter,
|
|
3911
|
+
isDestroyed: ctx.isDestroyed,
|
|
3912
|
+
isDragging: ctx.isDragging,
|
|
3913
|
+
getAllowedIds: ctx.getAllowedIds,
|
|
3914
|
+
getActiveId: ctx.getActiveId,
|
|
3915
|
+
resolveSnap: ctx.resolveSnap,
|
|
3916
|
+
snapTo: ctx.snapTo,
|
|
3917
|
+
on: ctx.on
|
|
3918
|
+
})
|
|
3919
|
+
};
|
|
3920
|
+
}
|
|
3921
|
+
function contentSwipeFeature() {
|
|
3922
|
+
return {
|
|
3923
|
+
name: "content-swipe",
|
|
3924
|
+
stage: "attach",
|
|
3925
|
+
install: (ctx) => {
|
|
3926
|
+
if (!ctx.scrollContainer) return;
|
|
3927
|
+
return installContentSwipe({
|
|
3928
|
+
container: ctx.scrollContainer,
|
|
3929
|
+
isDragging: ctx.isDragging,
|
|
3930
|
+
isAnimating: ctx.isAnimating,
|
|
3931
|
+
getAllowedIds: ctx.allowedIdsBySize,
|
|
3932
|
+
getActiveId: ctx.getActiveId,
|
|
3933
|
+
snapTo: ctx.snapTo
|
|
3934
|
+
});
|
|
3935
|
+
}
|
|
3936
|
+
};
|
|
3937
|
+
}
|
|
3938
|
+
function visualViewportFeature() {
|
|
3939
|
+
return {
|
|
3940
|
+
name: "visual-viewport",
|
|
3941
|
+
install: (ctx) => {
|
|
3942
|
+
if (typeof window === "undefined") return;
|
|
3943
|
+
return installVisualViewport({
|
|
3944
|
+
element: ctx.element,
|
|
3945
|
+
isVerticalAxis: ctx.isVerticalAxis,
|
|
3946
|
+
isDestroyed: ctx.isDestroyed,
|
|
3947
|
+
isDragging: ctx.isDragging,
|
|
3948
|
+
recomputeSnaps: ctx.recomputeSnaps,
|
|
3949
|
+
resolveActiveSnap: ctx.resolveActiveSnap,
|
|
3950
|
+
getMaxAxisSize: ctx.getMaxAxisSize,
|
|
3951
|
+
getSize: ctx.getSize,
|
|
3952
|
+
setMaxAxisSize: ctx.setMaxAxisSize,
|
|
3953
|
+
setSize: ctx.setSize,
|
|
3954
|
+
applySize: ctx.applySize,
|
|
3955
|
+
cancelInFlight: ctx.cancelInFlight,
|
|
3956
|
+
newCycle: ctx.newCycle,
|
|
3957
|
+
isAnimating: ctx.isAnimating,
|
|
3958
|
+
resyncAfterCancel: ctx.resyncAfterResize
|
|
3959
|
+
});
|
|
3960
|
+
}
|
|
3961
|
+
};
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
// src/core/default-features.ts
|
|
3965
|
+
function defaultEngineFeatures() {
|
|
3966
|
+
return [
|
|
3967
|
+
contentSwipeFeature(),
|
|
3968
|
+
visualViewportFeature(),
|
|
3969
|
+
persistFeature(),
|
|
3970
|
+
autoCollapseFeature(),
|
|
3971
|
+
routeFeature()
|
|
3972
|
+
];
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
// src/core/BottomSheetEngine.ts
|
|
3976
|
+
var BottomSheetEngine = class extends BottomSheetCore {
|
|
3977
|
+
constructor(opts) {
|
|
3978
|
+
super({
|
|
3979
|
+
...opts,
|
|
3980
|
+
features: [...defaultEngineFeatures(), ...opts.features ?? []]
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
};
|
|
3984
|
+
|
|
3721
3985
|
// src/core/features/teleport.ts
|
|
3722
3986
|
var resolveTeleportTarget = (target) => {
|
|
3723
3987
|
if (!target) return null;
|