@surdeddd/bottom-sheet 0.11.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 +68 -1
- package/dist/{BottomSheetEngine-DzsIwD28.d.cts → BottomSheetCore-CsIjyq7C.d.cts} +61 -5
- package/dist/{BottomSheetEngine-DRjCU73e.d.ts → BottomSheetCore-D16lsa6g.d.ts} +61 -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 +994 -697
- 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 +994 -697
- 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 +823 -542
- package/dist/index.d.cts +6 -15
- package/dist/index.d.ts +6 -15
- package/dist/index.js +817 -543
- 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 +13 -8
- package/dist/overlay.js +13 -8
- 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 +816 -542
- package/dist/qwik.d.cts +2 -2
- package/dist/qwik.d.ts +2 -2
- package/dist/qwik.js +816 -542
- package/dist/react.cjs +816 -542
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +816 -542
- package/dist/solid.cjs +816 -542
- package/dist/solid.d.cts +64 -4
- package/dist/solid.d.ts +64 -4
- package/dist/solid.js +816 -542
- package/dist/solid.source.jsx +816 -542
- package/dist/svelte-core.cjs +816 -542
- package/dist/svelte-core.js +816 -542
- package/dist/svelte.cjs +816 -542
- package/dist/svelte.js +816 -542
- package/dist/vue.cjs +927 -645
- package/dist/vue.js +927 -645
- package/package.json +63 -11
package/dist/index.cjs
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,390 +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 runInternal = (fn) => {
|
|
462
|
-
internalDepth += 1;
|
|
463
|
-
try {
|
|
464
|
-
fn();
|
|
465
|
-
} finally {
|
|
466
|
-
internalDepth -= 1;
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
var notifyRouteChange = () => {
|
|
470
|
-
const snapshot = Array.from(subscribers);
|
|
471
|
-
for (const fn of snapshot) fn();
|
|
472
|
-
};
|
|
473
|
-
var ensureListener = () => {
|
|
474
|
-
if (listenerInstalled || !hasWindow()) return;
|
|
475
|
-
window.addEventListener("popstate", onPopState);
|
|
476
|
-
listenerInstalled = true;
|
|
477
|
-
};
|
|
478
|
-
var maybeTeardownListener = () => {
|
|
479
|
-
if (!listenerInstalled) return;
|
|
480
|
-
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
481
|
-
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
482
|
-
listenerInstalled = false;
|
|
483
|
-
};
|
|
484
|
-
var installPatch = () => {
|
|
485
|
-
if (patchInstalled || !hasHistory()) return;
|
|
486
|
-
origPushState = history.pushState;
|
|
487
|
-
origReplaceState = history.replaceState;
|
|
488
|
-
patchedPushState = function(...args) {
|
|
489
|
-
origPushState.apply(this, args);
|
|
490
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
491
|
-
};
|
|
492
|
-
patchedReplaceState = function(...args) {
|
|
493
|
-
origReplaceState.apply(this, args);
|
|
494
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
495
|
-
};
|
|
496
|
-
history.pushState = patchedPushState;
|
|
497
|
-
history.replaceState = patchedReplaceState;
|
|
498
|
-
patchInstalled = true;
|
|
499
|
-
};
|
|
500
|
-
var removePatch = () => {
|
|
501
|
-
if (!patchInstalled) return;
|
|
502
|
-
if (history.pushState === patchedPushState && origPushState) {
|
|
503
|
-
history.pushState = origPushState;
|
|
504
|
-
}
|
|
505
|
-
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
506
|
-
history.replaceState = origReplaceState;
|
|
507
|
-
}
|
|
508
|
-
origPushState = null;
|
|
509
|
-
origReplaceState = null;
|
|
510
|
-
patchedPushState = null;
|
|
511
|
-
patchedReplaceState = null;
|
|
512
|
-
patchInstalled = false;
|
|
513
|
-
};
|
|
514
|
-
function onPopState() {
|
|
515
|
-
if (suppress > 0) {
|
|
516
|
-
suppress -= 1;
|
|
517
|
-
const rebrand = pendingRebrand;
|
|
518
|
-
pendingRebrand = null;
|
|
519
|
-
if (rebrand) rebrand();
|
|
520
|
-
maybeTeardownListener();
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
if (entries.length === 0) {
|
|
524
|
-
notifyRouteChange();
|
|
525
|
-
maybeTeardownListener();
|
|
526
|
-
return;
|
|
379
|
+
// src/core/features/resize-observer.ts
|
|
380
|
+
function installResizeObserver(deps) {
|
|
381
|
+
if (typeof window === "undefined") {
|
|
382
|
+
return () => {
|
|
383
|
+
};
|
|
527
384
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
if (entry.surface.isTop()) {
|
|
538
|
-
target = entry;
|
|
539
|
-
targetIdx = i;
|
|
540
|
-
break;
|
|
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);
|
|
541
394
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
void Promise.resolve(settled.surface.close()).then(() => {
|
|
553
|
-
if (settled.surface.isOpen()) restore(settled);
|
|
554
|
-
});
|
|
555
|
-
maybeTeardownListener();
|
|
556
|
-
}
|
|
557
|
-
function restore(entry) {
|
|
558
|
-
if (!hasWindow() || !hasHistory()) return;
|
|
559
|
-
entry.live = true;
|
|
560
|
-
runInternal(() => {
|
|
561
|
-
try {
|
|
562
|
-
history.pushState(entry.surface.markerState(), "", entry.surface.url);
|
|
563
|
-
} catch {
|
|
564
|
-
entry.live = false;
|
|
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?.();
|
|
565
405
|
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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);
|
|
570
413
|
}
|
|
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
|
+
};
|
|
571
426
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
entry.live = false;
|
|
584
|
-
}
|
|
585
|
-
});
|
|
586
|
-
if (entry.live) {
|
|
587
|
-
entries.push(entry);
|
|
588
|
-
ensureListener();
|
|
589
|
-
}
|
|
590
|
-
return entry;
|
|
591
|
-
}
|
|
592
|
-
function popBackMarker(handle) {
|
|
593
|
-
if (!hasWindow() || !hasHistory()) return;
|
|
594
|
-
const entry = handle;
|
|
595
|
-
const idx = entries.indexOf(entry);
|
|
596
|
-
if (idx === -1 || !entry.live) return;
|
|
597
|
-
const last = entries.length - 1;
|
|
598
|
-
entry.live = false;
|
|
599
|
-
entries.splice(idx, 1);
|
|
600
|
-
if (idx !== last) {
|
|
601
|
-
const rebrandSurface = entries[entries.length - 1].surface;
|
|
602
|
-
const rebrandUrl = entry.priorUrl;
|
|
603
|
-
pendingRebrand = () => {
|
|
604
|
-
runInternal(() => {
|
|
605
|
-
history.replaceState(
|
|
606
|
-
rebrandSurface.markerState(),
|
|
607
|
-
"",
|
|
608
|
-
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
609
|
-
);
|
|
610
|
-
});
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
suppress += 1;
|
|
614
|
-
runInternal(() => {
|
|
615
|
-
try {
|
|
616
|
-
history.back();
|
|
617
|
-
} catch {
|
|
618
|
-
suppress = Math.max(0, suppress - 1);
|
|
619
|
-
pendingRebrand = null;
|
|
620
|
-
}
|
|
621
|
-
});
|
|
622
|
-
maybeTeardownListener();
|
|
623
|
-
}
|
|
624
|
-
function subscribeRouteChange(fn) {
|
|
625
|
-
if (!hasWindow() || !hasHistory()) return () => {
|
|
626
|
-
};
|
|
627
|
-
subscribers.add(fn);
|
|
628
|
-
if (subscribers.size === 1) installPatch();
|
|
629
|
-
ensureListener();
|
|
630
|
-
return () => {
|
|
631
|
-
if (!subscribers.has(fn)) return;
|
|
632
|
-
subscribers.delete(fn);
|
|
633
|
-
if (subscribers.size === 0) removePatch();
|
|
634
|
-
maybeTeardownListener();
|
|
635
|
-
};
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// src/core/features/route.ts
|
|
639
|
-
function installRoute(deps) {
|
|
640
|
-
if (typeof window === "undefined") {
|
|
641
|
-
return () => {
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
if (!deps.routedTo && !deps.closeOnBack) {
|
|
645
|
-
return () => {
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
let handle = null;
|
|
649
|
-
const onOpen = () => {
|
|
650
|
-
if (handle) return;
|
|
651
|
-
handle = pushBackMarker({
|
|
652
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
653
|
-
isTop: deps.isTopSheet,
|
|
654
|
-
close: deps.close,
|
|
655
|
-
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
656
|
-
url: deps.routedTo
|
|
657
|
-
});
|
|
658
|
-
};
|
|
659
|
-
const onClose = () => {
|
|
660
|
-
if (!handle) return;
|
|
661
|
-
popBackMarker(handle);
|
|
662
|
-
handle = null;
|
|
663
|
-
};
|
|
664
|
-
const unsubscribeOpen = deps.on("open", onOpen);
|
|
665
|
-
const unsubscribeClose = deps.on("close", onClose);
|
|
666
|
-
if (deps.getSize() > 0) onOpen();
|
|
667
|
-
return () => {
|
|
668
|
-
unsubscribeOpen();
|
|
669
|
-
unsubscribeClose();
|
|
670
|
-
if (handle) {
|
|
671
|
-
popBackMarker(handle);
|
|
672
|
-
handle = null;
|
|
673
|
-
}
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
function installRouteChange(deps) {
|
|
677
|
-
return subscribeRouteChange(() => {
|
|
678
|
-
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
679
|
-
void deps.close();
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// src/core/features/content-swipe.ts
|
|
684
|
-
var CONTENT_PULL_THRESHOLD = 60;
|
|
685
|
-
function installContentSwipe(deps) {
|
|
686
|
-
const { container } = deps;
|
|
687
|
-
let startY = 0;
|
|
688
|
-
let startScrollTop = 0;
|
|
689
|
-
let moved = false;
|
|
690
|
-
const onTouchStart = (e) => {
|
|
691
|
-
const t = e.touches[0];
|
|
692
|
-
if (!t) return;
|
|
693
|
-
startY = t.clientY;
|
|
694
|
-
startScrollTop = container.scrollTop;
|
|
695
|
-
moved = false;
|
|
696
|
-
};
|
|
697
|
-
const onTouchMove = (e) => {
|
|
698
|
-
const t = e.touches[0];
|
|
699
|
-
if (!t) return;
|
|
700
|
-
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
701
|
-
};
|
|
702
|
-
const onTouchEnd = (e) => {
|
|
703
|
-
if (!moved) return;
|
|
704
|
-
if (deps.isDragging() || deps.isAnimating()) return;
|
|
705
|
-
if (container.scrollTop !== startScrollTop) return;
|
|
706
|
-
const t = e.changedTouches[0];
|
|
707
|
-
if (!t) return;
|
|
708
|
-
const deltaY = t.clientY - startY;
|
|
709
|
-
const atTop = container.scrollTop <= 0;
|
|
710
|
-
const allowed = deps.getAllowedIds();
|
|
711
|
-
const idx = allowed.indexOf(deps.getActiveId());
|
|
712
|
-
if (idx === -1) return;
|
|
713
|
-
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
714
|
-
deps.snapTo(allowed[idx - 1]);
|
|
715
|
-
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
716
|
-
deps.snapTo(allowed[idx + 1]);
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
720
|
-
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
721
|
-
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
722
|
-
return () => {
|
|
723
|
-
container.removeEventListener("touchstart", onTouchStart);
|
|
724
|
-
container.removeEventListener("touchmove", onTouchMove);
|
|
725
|
-
container.removeEventListener("touchend", onTouchEnd);
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// src/core/features/visual-viewport.ts
|
|
730
|
-
var SAFETY_PAD = 8;
|
|
731
|
-
function installVisualViewport(deps) {
|
|
732
|
-
if (typeof window === "undefined" || !window.visualViewport) {
|
|
733
|
-
return () => {
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
const vv = window.visualViewport;
|
|
737
|
-
let rafId = null;
|
|
738
|
-
const onResize = () => {
|
|
739
|
-
if (rafId !== null) return;
|
|
740
|
-
rafId = requestAnimationFrame(() => {
|
|
741
|
-
rafId = null;
|
|
742
|
-
if (deps.isDestroyed()) return;
|
|
743
|
-
deps.recomputeSnaps();
|
|
744
|
-
const isVertical = deps.isVerticalAxis();
|
|
745
|
-
const visible = isVertical ? vv.height : vv.width;
|
|
746
|
-
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
747
|
-
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
748
|
-
if (clamp < deps.getMaxAxisSize()) {
|
|
749
|
-
deps.setMaxAxisSize(clamp);
|
|
750
|
-
}
|
|
751
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
752
|
-
deps.cancelInFlight();
|
|
753
|
-
deps.newCycle();
|
|
754
|
-
const max = deps.getMaxAxisSize();
|
|
755
|
-
deps.setSize(Math.min(deps.getSize(), max));
|
|
756
|
-
const current = deps.resolveActiveSnap();
|
|
757
|
-
if (current && !deps.isDragging()) {
|
|
758
|
-
deps.applySize(Math.min(current.size, max));
|
|
759
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
760
|
-
} else {
|
|
761
|
-
deps.applySize(deps.getSize());
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
};
|
|
765
|
-
vv.addEventListener("resize", onResize);
|
|
766
|
-
return () => {
|
|
767
|
-
vv.removeEventListener("resize", onResize);
|
|
768
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// src/core/features/resize-observer.ts
|
|
773
|
-
function installResizeObserver(deps) {
|
|
774
|
-
if (typeof window === "undefined") {
|
|
775
|
-
return () => {
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
const onResize = () => {
|
|
779
|
-
if (deps.isDestroyed()) return;
|
|
780
|
-
deps.recomputeSnaps();
|
|
781
|
-
const mode = deps.getMode();
|
|
782
|
-
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
783
|
-
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
784
|
-
const max = deps.getMaxAxisSize();
|
|
785
|
-
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
786
|
-
deps.setMaxAxisSize(viewportSize2);
|
|
787
|
-
}
|
|
788
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
789
|
-
deps.cancelInFlight();
|
|
790
|
-
deps.newCycle();
|
|
791
|
-
const current = deps.resolveActiveSnap();
|
|
792
|
-
const newMax = deps.getMaxAxisSize();
|
|
793
|
-
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
794
|
-
deps.setSize(targetSize);
|
|
795
|
-
if (current && !deps.isDragging()) {
|
|
796
|
-
deps.applySize(targetSize);
|
|
797
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
798
|
-
}
|
|
799
|
-
};
|
|
800
|
-
let resizeObserver = null;
|
|
801
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
802
|
-
resizeObserver = new ResizeObserver(onResize);
|
|
803
|
-
resizeObserver.observe(document.documentElement);
|
|
804
|
-
} else {
|
|
805
|
-
window.addEventListener("resize", onResize);
|
|
806
|
-
}
|
|
807
|
-
window.addEventListener("orientationchange", onResize);
|
|
808
|
-
const onVisibility = () => {
|
|
809
|
-
if (deps.isDestroyed()) return;
|
|
810
|
-
if (document.hidden) deps.cancelInFlight();
|
|
811
|
-
};
|
|
812
|
-
document.addEventListener("visibilitychange", onVisibility);
|
|
813
|
-
return () => {
|
|
814
|
-
resizeObserver?.disconnect();
|
|
815
|
-
window.removeEventListener("resize", onResize);
|
|
816
|
-
window.removeEventListener("orientationchange", onResize);
|
|
817
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
818
|
-
};
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
// src/core/features/fit-observer.ts
|
|
822
|
-
var contentTargets = (scroller) => {
|
|
823
|
-
if (!scroller) return [];
|
|
824
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
825
|
-
const out = [];
|
|
826
|
-
for (const child of Array.from(scroller.children)) {
|
|
827
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
828
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
829
|
-
} else {
|
|
830
|
-
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);
|
|
831
438
|
}
|
|
832
439
|
}
|
|
833
440
|
return out;
|
|
@@ -947,11 +554,15 @@ function createMaxHeightController(deps) {
|
|
|
947
554
|
|
|
948
555
|
// src/core/features/fit-measurement.ts
|
|
949
556
|
var measureSheetNatural = (element, content, vertical) => {
|
|
950
|
-
if (!content) {
|
|
951
|
-
return vertical ? element.offsetHeight : element.offsetWidth;
|
|
952
|
-
}
|
|
953
557
|
const axis = vertical ? "height" : "width";
|
|
954
558
|
const sheetStyle = element.style;
|
|
559
|
+
if (!content) {
|
|
560
|
+
const prev = sheetStyle[axis];
|
|
561
|
+
sheetStyle[axis] = "auto";
|
|
562
|
+
const poked2 = vertical ? element.offsetHeight : element.offsetWidth;
|
|
563
|
+
sheetStyle[axis] = prev;
|
|
564
|
+
return poked2;
|
|
565
|
+
}
|
|
955
566
|
const cs = content.style;
|
|
956
567
|
const prevSheet = sheetStyle[axis];
|
|
957
568
|
const prevFlex = cs.flex;
|
|
@@ -1665,6 +1276,52 @@ function resolveAnimationPreset(animation) {
|
|
|
1665
1276
|
}
|
|
1666
1277
|
}
|
|
1667
1278
|
|
|
1279
|
+
// src/core/animation/waapi-settle.ts
|
|
1280
|
+
var SIM_HZ = 240;
|
|
1281
|
+
var SAMPLE_STRIDE = 4;
|
|
1282
|
+
var MAX_SIM_MS = 3e3;
|
|
1283
|
+
function sampleSpringSettle(from, to, velocityPxPerS, config) {
|
|
1284
|
+
const cfg = { ...DEFAULT_SPRING, ...config };
|
|
1285
|
+
const subDt = 1 / SIM_HZ;
|
|
1286
|
+
const stepMs = SAMPLE_STRIDE / SIM_HZ * 1e3;
|
|
1287
|
+
const maxSteps = Math.ceil(MAX_SIM_MS / 1e3 * SIM_HZ);
|
|
1288
|
+
const values = [from];
|
|
1289
|
+
let x = from;
|
|
1290
|
+
let v = velocityPxPerS;
|
|
1291
|
+
for (let i = 1; i <= maxSteps; i += 1) {
|
|
1292
|
+
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1293
|
+
v += force / cfg.mass * subDt;
|
|
1294
|
+
x += v * subDt;
|
|
1295
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1296
|
+
values.push(to);
|
|
1297
|
+
break;
|
|
1298
|
+
}
|
|
1299
|
+
if (i % SAMPLE_STRIDE === 0) values.push(x);
|
|
1300
|
+
const atRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1301
|
+
if (atRest) break;
|
|
1302
|
+
}
|
|
1303
|
+
if (values[values.length - 1] !== to) values.push(to);
|
|
1304
|
+
return {
|
|
1305
|
+
values,
|
|
1306
|
+
stepMs,
|
|
1307
|
+
durationMs: (values.length - 1) * stepMs
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
function sampleTweenSettle(from, to, durationMs, easing) {
|
|
1311
|
+
const count = Math.max(2, Math.min(60, Math.round(durationMs / 16)));
|
|
1312
|
+
const values = [];
|
|
1313
|
+
for (let i = 0; i <= count; i += 1) {
|
|
1314
|
+
const t = i / count;
|
|
1315
|
+
values.push(from + (to - from) * easing(t));
|
|
1316
|
+
}
|
|
1317
|
+
values[values.length - 1] = to;
|
|
1318
|
+
return {
|
|
1319
|
+
values,
|
|
1320
|
+
stepMs: durationMs / count,
|
|
1321
|
+
durationMs
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1668
1325
|
// src/core/controllers/animation-runner.ts
|
|
1669
1326
|
var DEFAULT_DURATION2 = 220;
|
|
1670
1327
|
var VELOCITY_PX_PER_S = 1e3;
|
|
@@ -1675,6 +1332,10 @@ var AnimationRunner = class {
|
|
|
1675
1332
|
__publicField(this, "applySizeFn");
|
|
1676
1333
|
__publicField(this, "getSize");
|
|
1677
1334
|
__publicField(this, "isDragging");
|
|
1335
|
+
__publicField(this, "applyAux");
|
|
1336
|
+
__publicField(this, "getTransformFor");
|
|
1337
|
+
__publicField(this, "settleWaapi");
|
|
1338
|
+
__publicField(this, "currentWaapi", null);
|
|
1678
1339
|
__publicField(this, "animationKind");
|
|
1679
1340
|
__publicField(this, "springConfig");
|
|
1680
1341
|
__publicField(this, "duration");
|
|
@@ -1690,6 +1351,9 @@ var AnimationRunner = class {
|
|
|
1690
1351
|
this.applySizeFn = deps.applySize;
|
|
1691
1352
|
this.getSize = deps.getSize;
|
|
1692
1353
|
this.isDragging = deps.isDragging;
|
|
1354
|
+
this.applyAux = deps.applyAux;
|
|
1355
|
+
this.getTransformFor = deps.getTransformFor;
|
|
1356
|
+
this.settleWaapi = opts.settleAnimation === "waapi";
|
|
1693
1357
|
const preset = resolveAnimationPreset(opts.animation);
|
|
1694
1358
|
this.animationKind = preset.kind;
|
|
1695
1359
|
this.duration = opts.duration ?? preset.duration ?? DEFAULT_DURATION2;
|
|
@@ -1714,11 +1378,20 @@ var AnimationRunner = class {
|
|
|
1714
1378
|
}
|
|
1715
1379
|
}
|
|
1716
1380
|
get isAnimating() {
|
|
1717
|
-
return this.currentTween !== null || this.currentSpring !== null;
|
|
1381
|
+
return this.currentTween !== null || this.currentSpring !== null || this.currentWaapi !== null;
|
|
1718
1382
|
}
|
|
1719
1383
|
cancel() {
|
|
1720
1384
|
this.currentTween?.cancel();
|
|
1721
1385
|
this.currentSpring?.cancel();
|
|
1386
|
+
if (this.currentWaapi) {
|
|
1387
|
+
const entry = this.currentWaapi;
|
|
1388
|
+
this.currentWaapi = null;
|
|
1389
|
+
entry.stop();
|
|
1390
|
+
try {
|
|
1391
|
+
entry.anim.cancel();
|
|
1392
|
+
} catch {
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1722
1395
|
}
|
|
1723
1396
|
async animateTo(target, velocityPxPerMs) {
|
|
1724
1397
|
if (target === this.getSize()) {
|
|
@@ -1737,7 +1410,28 @@ var AnimationRunner = class {
|
|
|
1737
1410
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1738
1411
|
return;
|
|
1739
1412
|
}
|
|
1740
|
-
if (this.
|
|
1413
|
+
if (this.settleWaapi && this.applyAux && this.getTransformFor && typeof this.element.animate === "function") {
|
|
1414
|
+
const samples = this.animationKind === "spring" ? sampleSpringSettle(
|
|
1415
|
+
this.getSize(),
|
|
1416
|
+
target,
|
|
1417
|
+
velocityPxPerMs * VELOCITY_PX_PER_S,
|
|
1418
|
+
this.springConfig
|
|
1419
|
+
) : sampleTweenSettle(
|
|
1420
|
+
this.getSize(),
|
|
1421
|
+
target,
|
|
1422
|
+
this.duration,
|
|
1423
|
+
this.easing
|
|
1424
|
+
);
|
|
1425
|
+
if (samples.values.length >= 2 && samples.durationMs > 0) {
|
|
1426
|
+
await this.runWaapiSettle(samples, target);
|
|
1427
|
+
if (!this.isAnimating) {
|
|
1428
|
+
this.getRootEl()?.removeAttribute("data-animating");
|
|
1429
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1430
|
+
}
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
if (this.animationKind === "spring") {
|
|
1741
1435
|
const spring = runSpring({
|
|
1742
1436
|
from: this.getSize(),
|
|
1743
1437
|
to: target,
|
|
@@ -1765,11 +1459,66 @@ var AnimationRunner = class {
|
|
|
1765
1459
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1766
1460
|
}
|
|
1767
1461
|
}
|
|
1462
|
+
async runWaapiSettle(samples, target) {
|
|
1463
|
+
const applyAux = this.applyAux;
|
|
1464
|
+
const getTransformFor = this.getTransformFor;
|
|
1465
|
+
const frames = samples.values.map((v) => ({
|
|
1466
|
+
transform: getTransformFor(v)
|
|
1467
|
+
}));
|
|
1468
|
+
const anim = this.element.animate(frames, {
|
|
1469
|
+
duration: samples.durationMs,
|
|
1470
|
+
easing: "linear",
|
|
1471
|
+
fill: "forwards"
|
|
1472
|
+
});
|
|
1473
|
+
let stopped = false;
|
|
1474
|
+
let auxRaf = 0;
|
|
1475
|
+
const start = performance.now();
|
|
1476
|
+
const lastIdx = samples.values.length - 1;
|
|
1477
|
+
const auxTick = () => {
|
|
1478
|
+
if (stopped) return;
|
|
1479
|
+
const elapsed = performance.now() - start;
|
|
1480
|
+
const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
|
|
1481
|
+
applyAux(samples.values[idx]);
|
|
1482
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1483
|
+
};
|
|
1484
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1485
|
+
const entry = {
|
|
1486
|
+
anim,
|
|
1487
|
+
stop: () => {
|
|
1488
|
+
stopped = true;
|
|
1489
|
+
cancelAnimationFrame(auxRaf);
|
|
1490
|
+
}
|
|
1491
|
+
};
|
|
1492
|
+
this.currentWaapi = entry;
|
|
1493
|
+
try {
|
|
1494
|
+
await anim.finished;
|
|
1495
|
+
} catch {
|
|
1496
|
+
}
|
|
1497
|
+
entry.stop();
|
|
1498
|
+
const wasCurrent = this.currentWaapi === entry;
|
|
1499
|
+
if (wasCurrent) this.currentWaapi = null;
|
|
1500
|
+
if (wasCurrent && anim.playState === "finished") {
|
|
1501
|
+
this.applySizeFn(target);
|
|
1502
|
+
try {
|
|
1503
|
+
anim.cancel();
|
|
1504
|
+
} catch {
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1768
1508
|
destroy() {
|
|
1769
1509
|
this.detachReducedMotion?.();
|
|
1770
1510
|
this.detachReducedMotion = null;
|
|
1771
1511
|
this.currentTween = null;
|
|
1772
1512
|
this.currentSpring = null;
|
|
1513
|
+
if (this.currentWaapi) {
|
|
1514
|
+
const entry = this.currentWaapi;
|
|
1515
|
+
this.currentWaapi = null;
|
|
1516
|
+
entry.stop();
|
|
1517
|
+
try {
|
|
1518
|
+
entry.anim.cancel();
|
|
1519
|
+
} catch {
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1773
1522
|
}
|
|
1774
1523
|
};
|
|
1775
1524
|
|
|
@@ -2627,7 +2376,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2627
2376
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2628
2377
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2629
2378
|
if (opts.persistKey) {
|
|
2630
|
-
const restored =
|
|
2379
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2631
2380
|
if (restored && initialAllowed.includes(restored)) {
|
|
2632
2381
|
initialId = restored;
|
|
2633
2382
|
}
|
|
@@ -2658,6 +2407,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2658
2407
|
},
|
|
2659
2408
|
animation: {
|
|
2660
2409
|
animation: opts.animation,
|
|
2410
|
+
settleAnimation: opts.settleAnimation,
|
|
2661
2411
|
duration: opts.duration,
|
|
2662
2412
|
easing: opts.easing,
|
|
2663
2413
|
spring: opts.spring,
|
|
@@ -2675,6 +2425,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2675
2425
|
}
|
|
2676
2426
|
};
|
|
2677
2427
|
}
|
|
2428
|
+
var readPersistedIdSafe = (key) => {
|
|
2429
|
+
if (typeof window === "undefined") return null;
|
|
2430
|
+
if (typeof localStorage === "undefined") return null;
|
|
2431
|
+
try {
|
|
2432
|
+
return localStorage.getItem(key);
|
|
2433
|
+
} catch {
|
|
2434
|
+
return null;
|
|
2435
|
+
}
|
|
2436
|
+
};
|
|
2678
2437
|
|
|
2679
2438
|
// src/core/primitives/teardown-stack.ts
|
|
2680
2439
|
var TeardownStack = class {
|
|
@@ -2697,9 +2456,9 @@ var TeardownStack = class {
|
|
|
2697
2456
|
}
|
|
2698
2457
|
};
|
|
2699
2458
|
|
|
2700
|
-
// src/core/
|
|
2459
|
+
// src/core/BottomSheetCore.ts
|
|
2701
2460
|
var HAPTIC_DURATION_MS = 8;
|
|
2702
|
-
var
|
|
2461
|
+
var BottomSheetCore = class {
|
|
2703
2462
|
constructor(opts) {
|
|
2704
2463
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
2705
2464
|
__publicField(this, "element");
|
|
@@ -2760,6 +2519,8 @@ var BottomSheetEngine = class {
|
|
|
2760
2519
|
__publicField(this, "stackEffectPrimed", false);
|
|
2761
2520
|
__publicField(this, "fitDeps");
|
|
2762
2521
|
__publicField(this, "transformTemplate");
|
|
2522
|
+
__publicField(this, "featureList", []);
|
|
2523
|
+
__publicField(this, "featureCtx");
|
|
2763
2524
|
const resolved = resolveEngineOptions(opts, {
|
|
2764
2525
|
shouldApplyInertSiblings: () => {
|
|
2765
2526
|
if (typeof document === "undefined") return false;
|
|
@@ -2806,7 +2567,9 @@ var BottomSheetEngine = class {
|
|
|
2806
2567
|
getRootEl: () => this.rootEl,
|
|
2807
2568
|
applySize: (size) => this.applySize(size),
|
|
2808
2569
|
getSize: () => this.size,
|
|
2809
|
-
isDragging: () => this.gesture?.isDragging ?? false
|
|
2570
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2571
|
+
applyAux: (size) => this.applySize(size, true),
|
|
2572
|
+
getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
|
|
2810
2573
|
},
|
|
2811
2574
|
resolved.animation
|
|
2812
2575
|
);
|
|
@@ -2829,6 +2592,11 @@ var BottomSheetEngine = class {
|
|
|
2829
2592
|
if (opts.linkedSheets) {
|
|
2830
2593
|
this.linkedSheets = opts.linkedSheets;
|
|
2831
2594
|
}
|
|
2595
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2596
|
+
for (const feature of opts.features ?? []) {
|
|
2597
|
+
byName.set(feature.name, feature);
|
|
2598
|
+
}
|
|
2599
|
+
this.featureList = Array.from(byName.values());
|
|
2832
2600
|
this.activeId = resolved.initialId;
|
|
2833
2601
|
auditVhUsage(this.snapPointsRaw);
|
|
2834
2602
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
@@ -2865,6 +2633,7 @@ var BottomSheetEngine = class {
|
|
|
2865
2633
|
scrollContainer: this.scrollContainer,
|
|
2866
2634
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize()
|
|
2867
2635
|
});
|
|
2636
|
+
this.featureCtx = this.buildFeatureContext(opts.autoCollapseAfter);
|
|
2868
2637
|
this.attach();
|
|
2869
2638
|
this.registerInStack();
|
|
2870
2639
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
@@ -2873,12 +2642,7 @@ var BottomSheetEngine = class {
|
|
|
2873
2642
|
if (!entry.isIntersecting) continue;
|
|
2874
2643
|
if (this.destroyed) return;
|
|
2875
2644
|
this.snaps.recompute();
|
|
2876
|
-
|
|
2877
|
-
if (current) {
|
|
2878
|
-
this.size = current.size;
|
|
2879
|
-
this.applySize(this.size);
|
|
2880
|
-
this.updateAriaSlider();
|
|
2881
|
-
}
|
|
2645
|
+
this.healActiveSnap();
|
|
2882
2646
|
io.disconnect();
|
|
2883
2647
|
return;
|
|
2884
2648
|
}
|
|
@@ -2901,46 +2665,77 @@ var BottomSheetEngine = class {
|
|
|
2901
2665
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2902
2666
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2903
2667
|
this.applyAutoAriaLabelledBy();
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
getSize: () => this.size,
|
|
2909
|
-
close: () => this.close()
|
|
2910
|
-
})
|
|
2911
|
-
);
|
|
2912
|
-
}
|
|
2913
|
-
if (this.persistKey) {
|
|
2914
|
-
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2668
|
+
this.runFeatureStage("post");
|
|
2669
|
+
this.warnOrphanFeatureOptions();
|
|
2670
|
+
if (this.size > 0) {
|
|
2671
|
+
this.handleOpen();
|
|
2915
2672
|
}
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
resolveSnap: (id) => this.snaps.findById(id),
|
|
2924
|
-
snapTo: (id) => {
|
|
2925
|
-
void this.snapTo(id);
|
|
2926
|
-
},
|
|
2927
|
-
on: (event, fn) => this.on(event, fn)
|
|
2928
|
-
})
|
|
2929
|
-
);
|
|
2930
|
-
this.teardowns.add(
|
|
2931
|
-
installRoute({
|
|
2673
|
+
}
|
|
2674
|
+
buildFeatureContext(autoCollapseAfter) {
|
|
2675
|
+
return {
|
|
2676
|
+
element: this.element,
|
|
2677
|
+
scrollContainer: this.scrollContainer,
|
|
2678
|
+
sheetId: this.id,
|
|
2679
|
+
options: {
|
|
2932
2680
|
routedTo: this.routedTo,
|
|
2933
2681
|
closeOnBack: this.closeOnBack,
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
this.
|
|
2682
|
+
closeOnRouteChange: this.closeOnRouteChange,
|
|
2683
|
+
persistKey: this.persistKey,
|
|
2684
|
+
autoCollapseAfter
|
|
2685
|
+
},
|
|
2686
|
+
isDestroyed: () => this.destroyed,
|
|
2687
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2688
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2689
|
+
isTopSheet: () => this.isTopSheet,
|
|
2690
|
+
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
2691
|
+
getSize: () => this.size,
|
|
2692
|
+
getActiveId: () => this.activeId,
|
|
2693
|
+
getAllowedIds: () => this.snaps.getAllowedIds().slice(),
|
|
2694
|
+
allowedIdsBySize: () => this.allowedIdsBySize(),
|
|
2695
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2696
|
+
resolveSnap: (id) => this.snaps.findById(id),
|
|
2697
|
+
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
2698
|
+
setSize: (size) => {
|
|
2699
|
+
this.size = size;
|
|
2700
|
+
},
|
|
2701
|
+
setMaxAxisSize: (size) => {
|
|
2702
|
+
this.snaps.setMaxAxisSize(size);
|
|
2703
|
+
},
|
|
2704
|
+
applySize: (size) => this.applySize(size),
|
|
2705
|
+
recomputeSnaps: () => this.recomputeSnaps(),
|
|
2706
|
+
newCycle: () => {
|
|
2707
|
+
this.newCycle();
|
|
2708
|
+
},
|
|
2709
|
+
cancelInFlight: () => {
|
|
2710
|
+
this.animation.cancel();
|
|
2711
|
+
},
|
|
2712
|
+
resyncAfterResize: () => this.resyncAfterResize(),
|
|
2713
|
+
snapTo: (id) => {
|
|
2714
|
+
void this.snapTo(id);
|
|
2715
|
+
},
|
|
2716
|
+
close: (reason) => this.close(reason),
|
|
2717
|
+
on: (event, fn) => this.on(event, fn),
|
|
2718
|
+
addTeardown: (fn) => this.teardowns.add(fn)
|
|
2719
|
+
};
|
|
2720
|
+
}
|
|
2721
|
+
runFeatureStage(stage) {
|
|
2722
|
+
for (const feature of this.featureList) {
|
|
2723
|
+
if ((feature.stage ?? "post") !== stage) continue;
|
|
2724
|
+
const teardown = feature.install(this.featureCtx);
|
|
2725
|
+
if (teardown) this.teardowns.add(teardown);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
warnOrphanFeatureOptions() {
|
|
2729
|
+
const names = new Set(this.featureList.map((f) => f.name));
|
|
2730
|
+
if ((this.closeOnBack || this.routedTo !== void 0 || this.closeOnRouteChange) && !names.has("route")) {
|
|
2731
|
+
devWarn(
|
|
2732
|
+
"[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
|
|
2733
|
+
);
|
|
2734
|
+
}
|
|
2735
|
+
if (this.persistKey && !names.has("persist")) {
|
|
2736
|
+
devWarn(
|
|
2737
|
+
"[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
|
|
2738
|
+
);
|
|
2944
2739
|
}
|
|
2945
2740
|
}
|
|
2946
2741
|
get state() {
|
|
@@ -3042,6 +2837,8 @@ var BottomSheetEngine = class {
|
|
|
3042
2837
|
const vt = document.startViewTransition(() => {
|
|
3043
2838
|
this.applySize(target.size);
|
|
3044
2839
|
});
|
|
2840
|
+
vt.ready?.catch(() => {
|
|
2841
|
+
});
|
|
3045
2842
|
this.currentViewTransition = vt;
|
|
3046
2843
|
try {
|
|
3047
2844
|
await vt.finished;
|
|
@@ -3293,11 +3090,16 @@ var BottomSheetEngine = class {
|
|
|
3293
3090
|
this.maxHeight.clampTo();
|
|
3294
3091
|
this.scrim.invalidateOpacityCache();
|
|
3295
3092
|
if (this.gesture?.isDragging) return;
|
|
3093
|
+
this.healActiveSnap();
|
|
3094
|
+
}
|
|
3095
|
+
healActiveSnap() {
|
|
3296
3096
|
const current = this.snaps.findById(this.activeId);
|
|
3297
|
-
if (current)
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3097
|
+
if (!current) return;
|
|
3098
|
+
this.size = current.size;
|
|
3099
|
+
this.applySize(this.size);
|
|
3100
|
+
this.updateAriaSlider();
|
|
3101
|
+
if (this.size > 0 && !this.lifecycle.isInstalled && !this.opening && !this.animation.isAnimating) {
|
|
3102
|
+
this.emitOpenSequence(this.activeId);
|
|
3301
3103
|
}
|
|
3302
3104
|
}
|
|
3303
3105
|
destroy() {
|
|
@@ -3476,18 +3278,7 @@ var BottomSheetEngine = class {
|
|
|
3476
3278
|
}
|
|
3477
3279
|
}
|
|
3478
3280
|
attachFeatures() {
|
|
3479
|
-
|
|
3480
|
-
this.teardowns.add(installContentSwipe({
|
|
3481
|
-
container: this.scrollContainer,
|
|
3482
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3483
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3484
|
-
getAllowedIds: () => this.allowedIdsBySize(),
|
|
3485
|
-
getActiveId: () => this.activeId,
|
|
3486
|
-
snapTo: (id) => {
|
|
3487
|
-
void this.snapTo(id);
|
|
3488
|
-
}
|
|
3489
|
-
}));
|
|
3490
|
-
}
|
|
3281
|
+
this.runFeatureStage("attach");
|
|
3491
3282
|
if (typeof window !== "undefined") {
|
|
3492
3283
|
this.teardowns.add(installResizeObserver({
|
|
3493
3284
|
element: this.element,
|
|
@@ -3527,31 +3318,6 @@ var BottomSheetEngine = class {
|
|
|
3527
3318
|
() => document.removeEventListener("keydown", onKey)
|
|
3528
3319
|
);
|
|
3529
3320
|
}
|
|
3530
|
-
this.teardowns.add(installVisualViewport({
|
|
3531
|
-
element: this.element,
|
|
3532
|
-
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
3533
|
-
isDestroyed: () => this.destroyed,
|
|
3534
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3535
|
-
recomputeSnaps: () => this.recomputeSnaps(),
|
|
3536
|
-
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3537
|
-
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3538
|
-
getSize: () => this.size,
|
|
3539
|
-
setMaxAxisSize: (size) => {
|
|
3540
|
-
this.snaps.setMaxAxisSize(size);
|
|
3541
|
-
},
|
|
3542
|
-
setSize: (size) => {
|
|
3543
|
-
this.size = size;
|
|
3544
|
-
},
|
|
3545
|
-
applySize: (size) => this.applySize(size),
|
|
3546
|
-
cancelInFlight: () => {
|
|
3547
|
-
this.animation.cancel();
|
|
3548
|
-
},
|
|
3549
|
-
newCycle: () => {
|
|
3550
|
-
this.newCycle();
|
|
3551
|
-
},
|
|
3552
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3553
|
-
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3554
|
-
}));
|
|
3555
3321
|
}
|
|
3556
3322
|
this.teardowns.add(installSliderKeyboard({
|
|
3557
3323
|
handle: this.handle,
|
|
@@ -3628,13 +3394,13 @@ var BottomSheetEngine = class {
|
|
|
3628
3394
|
}
|
|
3629
3395
|
}
|
|
3630
3396
|
}
|
|
3631
|
-
applySize(size) {
|
|
3397
|
+
applySize(size, skipTransform = false) {
|
|
3632
3398
|
const cap = this.snaps.getMaxAxisSize();
|
|
3633
3399
|
const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
|
|
3634
3400
|
this.size = clamped;
|
|
3635
3401
|
const offset = cap - clamped;
|
|
3636
3402
|
const style = this.element.style;
|
|
3637
|
-
style.transform = this.transformTemplate(offset);
|
|
3403
|
+
if (!skipTransform) style.transform = this.transformTemplate(offset);
|
|
3638
3404
|
if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
|
|
3639
3405
|
style.setProperty("--bs-size", `${clamped}px`);
|
|
3640
3406
|
if (this.scrimParent) {
|
|
@@ -3712,6 +3478,514 @@ var BottomSheetEngine = class {
|
|
|
3712
3478
|
}
|
|
3713
3479
|
};
|
|
3714
3480
|
|
|
3481
|
+
// src/core/features/history-coordinator.ts
|
|
3482
|
+
var entries = [];
|
|
3483
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3484
|
+
var suppress = 0;
|
|
3485
|
+
var internalDepth = 0;
|
|
3486
|
+
var pendingRebrands = [];
|
|
3487
|
+
var listenerInstalled = false;
|
|
3488
|
+
var patchInstalled = false;
|
|
3489
|
+
var origPushState = null;
|
|
3490
|
+
var origReplaceState = null;
|
|
3491
|
+
var patchedPushState = null;
|
|
3492
|
+
var patchedReplaceState = null;
|
|
3493
|
+
var hasWindow = () => typeof window !== "undefined";
|
|
3494
|
+
var hasHistory = () => typeof history !== "undefined";
|
|
3495
|
+
var brandMarker = (surface) => ({
|
|
3496
|
+
...surface.markerState(),
|
|
3497
|
+
__bs: true
|
|
3498
|
+
});
|
|
3499
|
+
var runInternal = (fn) => {
|
|
3500
|
+
internalDepth += 1;
|
|
3501
|
+
try {
|
|
3502
|
+
fn();
|
|
3503
|
+
} finally {
|
|
3504
|
+
internalDepth -= 1;
|
|
3505
|
+
}
|
|
3506
|
+
};
|
|
3507
|
+
var notifyRouteChange = () => {
|
|
3508
|
+
const snapshot = Array.from(subscribers);
|
|
3509
|
+
for (const fn of snapshot) fn();
|
|
3510
|
+
};
|
|
3511
|
+
var ensureListener = () => {
|
|
3512
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
3513
|
+
window.addEventListener("popstate", onPopState);
|
|
3514
|
+
listenerInstalled = true;
|
|
3515
|
+
};
|
|
3516
|
+
var maybeTeardownListener = () => {
|
|
3517
|
+
if (!listenerInstalled) return;
|
|
3518
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
3519
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
3520
|
+
listenerInstalled = false;
|
|
3521
|
+
};
|
|
3522
|
+
var installPatch = () => {
|
|
3523
|
+
if (patchInstalled || !hasHistory()) return;
|
|
3524
|
+
origPushState = history.pushState;
|
|
3525
|
+
origReplaceState = history.replaceState;
|
|
3526
|
+
patchedPushState = function(...args) {
|
|
3527
|
+
origPushState.apply(this, args);
|
|
3528
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3529
|
+
};
|
|
3530
|
+
patchedReplaceState = function(...args) {
|
|
3531
|
+
origReplaceState.apply(this, args);
|
|
3532
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3533
|
+
};
|
|
3534
|
+
history.pushState = patchedPushState;
|
|
3535
|
+
history.replaceState = patchedReplaceState;
|
|
3536
|
+
patchInstalled = true;
|
|
3537
|
+
};
|
|
3538
|
+
var removePatch = () => {
|
|
3539
|
+
if (!patchInstalled) return;
|
|
3540
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
3541
|
+
history.pushState = origPushState;
|
|
3542
|
+
}
|
|
3543
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
3544
|
+
history.replaceState = origReplaceState;
|
|
3545
|
+
}
|
|
3546
|
+
origPushState = null;
|
|
3547
|
+
origReplaceState = null;
|
|
3548
|
+
patchedPushState = null;
|
|
3549
|
+
patchedReplaceState = null;
|
|
3550
|
+
patchInstalled = false;
|
|
3551
|
+
};
|
|
3552
|
+
function onPopState() {
|
|
3553
|
+
if (suppress > 0) {
|
|
3554
|
+
suppress -= 1;
|
|
3555
|
+
const rebrand = pendingRebrands.shift();
|
|
3556
|
+
if (rebrand) rebrand();
|
|
3557
|
+
maybeTeardownListener();
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3560
|
+
if (entries.length === 0) {
|
|
3561
|
+
notifyRouteChange();
|
|
3562
|
+
maybeTeardownListener();
|
|
3563
|
+
return;
|
|
3564
|
+
}
|
|
3565
|
+
let target = null;
|
|
3566
|
+
let targetIdx = -1;
|
|
3567
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3568
|
+
const entry = entries[i];
|
|
3569
|
+
if (!entry.surface.isOpen()) continue;
|
|
3570
|
+
if (!target) {
|
|
3571
|
+
target = entry;
|
|
3572
|
+
targetIdx = i;
|
|
3573
|
+
}
|
|
3574
|
+
if (entry.surface.isTop()) {
|
|
3575
|
+
target = entry;
|
|
3576
|
+
targetIdx = i;
|
|
3577
|
+
break;
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
if (!target) {
|
|
3581
|
+
const removed = entries.pop();
|
|
3582
|
+
if (removed) removed.live = false;
|
|
3583
|
+
maybeTeardownListener();
|
|
3584
|
+
return;
|
|
3585
|
+
}
|
|
3586
|
+
target.live = false;
|
|
3587
|
+
entries.splice(targetIdx, 1);
|
|
3588
|
+
const settled = target;
|
|
3589
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
3590
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
3591
|
+
});
|
|
3592
|
+
maybeTeardownListener();
|
|
3593
|
+
}
|
|
3594
|
+
function restore(entry) {
|
|
3595
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3596
|
+
entry.live = true;
|
|
3597
|
+
runInternal(() => {
|
|
3598
|
+
try {
|
|
3599
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
3600
|
+
} catch {
|
|
3601
|
+
entry.live = false;
|
|
3602
|
+
}
|
|
3603
|
+
});
|
|
3604
|
+
if (entry.live) {
|
|
3605
|
+
entries.push(entry);
|
|
3606
|
+
ensureListener();
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
function pushBackMarker(surface) {
|
|
3610
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
3611
|
+
if (!hasWindow() || !hasHistory()) {
|
|
3612
|
+
return entry;
|
|
3613
|
+
}
|
|
3614
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
3615
|
+
runInternal(() => {
|
|
3616
|
+
try {
|
|
3617
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
3618
|
+
entry.live = true;
|
|
3619
|
+
} catch {
|
|
3620
|
+
entry.live = false;
|
|
3621
|
+
}
|
|
3622
|
+
});
|
|
3623
|
+
if (entry.live) {
|
|
3624
|
+
entries.push(entry);
|
|
3625
|
+
ensureListener();
|
|
3626
|
+
}
|
|
3627
|
+
return entry;
|
|
3628
|
+
}
|
|
3629
|
+
function popBackMarker(handle) {
|
|
3630
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3631
|
+
const entry = handle;
|
|
3632
|
+
const idx = entries.indexOf(entry);
|
|
3633
|
+
if (idx === -1 || !entry.live) return;
|
|
3634
|
+
const last = entries.length - 1;
|
|
3635
|
+
entry.live = false;
|
|
3636
|
+
entries.splice(idx, 1);
|
|
3637
|
+
let rebrand = null;
|
|
3638
|
+
if (idx !== last) {
|
|
3639
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
3640
|
+
const rebrandUrl = entry.priorUrl;
|
|
3641
|
+
rebrand = () => {
|
|
3642
|
+
runInternal(() => {
|
|
3643
|
+
history.replaceState(
|
|
3644
|
+
brandMarker(rebrandSurface),
|
|
3645
|
+
"",
|
|
3646
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
3647
|
+
);
|
|
3648
|
+
});
|
|
3649
|
+
};
|
|
3650
|
+
}
|
|
3651
|
+
pendingRebrands.push(rebrand);
|
|
3652
|
+
suppress += 1;
|
|
3653
|
+
runInternal(() => {
|
|
3654
|
+
try {
|
|
3655
|
+
history.back();
|
|
3656
|
+
} catch {
|
|
3657
|
+
suppress = Math.max(0, suppress - 1);
|
|
3658
|
+
pendingRebrands.pop();
|
|
3659
|
+
}
|
|
3660
|
+
});
|
|
3661
|
+
maybeTeardownListener();
|
|
3662
|
+
}
|
|
3663
|
+
function subscribeRouteChange(fn) {
|
|
3664
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
3665
|
+
};
|
|
3666
|
+
subscribers.add(fn);
|
|
3667
|
+
if (subscribers.size === 1) installPatch();
|
|
3668
|
+
ensureListener();
|
|
3669
|
+
return () => {
|
|
3670
|
+
if (!subscribers.has(fn)) return;
|
|
3671
|
+
subscribers.delete(fn);
|
|
3672
|
+
if (subscribers.size === 0) removePatch();
|
|
3673
|
+
maybeTeardownListener();
|
|
3674
|
+
};
|
|
3675
|
+
}
|
|
3676
|
+
|
|
3677
|
+
// src/core/features/route.ts
|
|
3678
|
+
function installRoute(deps) {
|
|
3679
|
+
if (typeof window === "undefined") {
|
|
3680
|
+
return () => {
|
|
3681
|
+
};
|
|
3682
|
+
}
|
|
3683
|
+
if (!deps.routedTo && !deps.closeOnBack) {
|
|
3684
|
+
return () => {
|
|
3685
|
+
};
|
|
3686
|
+
}
|
|
3687
|
+
let handle = null;
|
|
3688
|
+
const onOpen = () => {
|
|
3689
|
+
if (handle) return;
|
|
3690
|
+
handle = pushBackMarker({
|
|
3691
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
3692
|
+
isTop: deps.isTopSheet,
|
|
3693
|
+
close: deps.close,
|
|
3694
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
3695
|
+
url: deps.routedTo
|
|
3696
|
+
});
|
|
3697
|
+
};
|
|
3698
|
+
const onClose = () => {
|
|
3699
|
+
if (!handle) return;
|
|
3700
|
+
popBackMarker(handle);
|
|
3701
|
+
handle = null;
|
|
3702
|
+
};
|
|
3703
|
+
const unsubscribeOpen = deps.on("open", onOpen);
|
|
3704
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
3705
|
+
if (deps.getSize() > 0) onOpen();
|
|
3706
|
+
return () => {
|
|
3707
|
+
unsubscribeOpen();
|
|
3708
|
+
unsubscribeClose();
|
|
3709
|
+
if (handle) {
|
|
3710
|
+
popBackMarker(handle);
|
|
3711
|
+
handle = null;
|
|
3712
|
+
}
|
|
3713
|
+
};
|
|
3714
|
+
}
|
|
3715
|
+
function installRouteChange(deps) {
|
|
3716
|
+
return subscribeRouteChange(() => {
|
|
3717
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
3718
|
+
void deps.close();
|
|
3719
|
+
});
|
|
3720
|
+
}
|
|
3721
|
+
|
|
3722
|
+
// src/core/features/persist.ts
|
|
3723
|
+
function installPersist(engine, key) {
|
|
3724
|
+
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
3725
|
+
if (typeof window === "undefined") return;
|
|
3726
|
+
if (typeof localStorage === "undefined") return;
|
|
3727
|
+
try {
|
|
3728
|
+
localStorage.setItem(key, id);
|
|
3729
|
+
} catch {
|
|
3730
|
+
}
|
|
3731
|
+
});
|
|
3732
|
+
return unsubscribe;
|
|
3733
|
+
}
|
|
3734
|
+
|
|
3735
|
+
// src/core/features/auto-collapse.ts
|
|
3736
|
+
function installAutoCollapse(deps) {
|
|
3737
|
+
const { ms } = deps;
|
|
3738
|
+
if (ms === void 0 || ms <= 0) {
|
|
3739
|
+
return () => {
|
|
3740
|
+
};
|
|
3741
|
+
}
|
|
3742
|
+
let timer = null;
|
|
3743
|
+
const clearTimer = () => {
|
|
3744
|
+
if (timer !== null) {
|
|
3745
|
+
clearTimeout(timer);
|
|
3746
|
+
timer = null;
|
|
3747
|
+
}
|
|
3748
|
+
};
|
|
3749
|
+
const fire = () => {
|
|
3750
|
+
if (deps.isDestroyed()) return;
|
|
3751
|
+
if (deps.isDragging()) return;
|
|
3752
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
3753
|
+
if (!active || active.size === 0) return;
|
|
3754
|
+
let target = null;
|
|
3755
|
+
for (const id of deps.getAllowedIds()) {
|
|
3756
|
+
const snap = deps.resolveSnap(id);
|
|
3757
|
+
if (!snap || snap.size <= 0) continue;
|
|
3758
|
+
if (!target || snap.size < target.size) target = snap;
|
|
3759
|
+
}
|
|
3760
|
+
if (!target) return;
|
|
3761
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
3762
|
+
deps.snapTo(target.id);
|
|
3763
|
+
};
|
|
3764
|
+
const reset = () => {
|
|
3765
|
+
clearTimer();
|
|
3766
|
+
if (deps.isDestroyed()) return;
|
|
3767
|
+
timer = setTimeout(() => {
|
|
3768
|
+
timer = null;
|
|
3769
|
+
fire();
|
|
3770
|
+
}, ms);
|
|
3771
|
+
};
|
|
3772
|
+
const unsubscribe = deps.on("snap", () => reset());
|
|
3773
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
3774
|
+
return () => {
|
|
3775
|
+
clearTimer();
|
|
3776
|
+
unsubscribe();
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3780
|
+
// src/core/features/content-swipe.ts
|
|
3781
|
+
var CONTENT_PULL_THRESHOLD = 60;
|
|
3782
|
+
function installContentSwipe(deps) {
|
|
3783
|
+
const { container } = deps;
|
|
3784
|
+
let startY = 0;
|
|
3785
|
+
let startScrollTop = 0;
|
|
3786
|
+
let moved = false;
|
|
3787
|
+
const onTouchStart = (e) => {
|
|
3788
|
+
const t = e.touches[0];
|
|
3789
|
+
if (!t) return;
|
|
3790
|
+
startY = t.clientY;
|
|
3791
|
+
startScrollTop = container.scrollTop;
|
|
3792
|
+
moved = false;
|
|
3793
|
+
};
|
|
3794
|
+
const onTouchMove = (e) => {
|
|
3795
|
+
const t = e.touches[0];
|
|
3796
|
+
if (!t) return;
|
|
3797
|
+
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
3798
|
+
};
|
|
3799
|
+
const onTouchEnd = (e) => {
|
|
3800
|
+
if (!moved) return;
|
|
3801
|
+
if (deps.isDragging() || deps.isAnimating()) return;
|
|
3802
|
+
if (container.scrollTop !== startScrollTop) return;
|
|
3803
|
+
const t = e.changedTouches[0];
|
|
3804
|
+
if (!t) return;
|
|
3805
|
+
const deltaY = t.clientY - startY;
|
|
3806
|
+
const atTop = container.scrollTop <= 0;
|
|
3807
|
+
const allowed = deps.getAllowedIds();
|
|
3808
|
+
const idx = allowed.indexOf(deps.getActiveId());
|
|
3809
|
+
if (idx === -1) return;
|
|
3810
|
+
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
3811
|
+
deps.snapTo(allowed[idx - 1]);
|
|
3812
|
+
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
3813
|
+
deps.snapTo(allowed[idx + 1]);
|
|
3814
|
+
}
|
|
3815
|
+
};
|
|
3816
|
+
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
3817
|
+
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
3818
|
+
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
3819
|
+
return () => {
|
|
3820
|
+
container.removeEventListener("touchstart", onTouchStart);
|
|
3821
|
+
container.removeEventListener("touchmove", onTouchMove);
|
|
3822
|
+
container.removeEventListener("touchend", onTouchEnd);
|
|
3823
|
+
};
|
|
3824
|
+
}
|
|
3825
|
+
|
|
3826
|
+
// src/core/features/visual-viewport.ts
|
|
3827
|
+
var SAFETY_PAD = 8;
|
|
3828
|
+
function installVisualViewport(deps) {
|
|
3829
|
+
if (typeof window === "undefined" || !window.visualViewport) {
|
|
3830
|
+
return () => {
|
|
3831
|
+
};
|
|
3832
|
+
}
|
|
3833
|
+
const vv = window.visualViewport;
|
|
3834
|
+
let rafId = null;
|
|
3835
|
+
const onResize = () => {
|
|
3836
|
+
if (rafId !== null) return;
|
|
3837
|
+
rafId = requestAnimationFrame(() => {
|
|
3838
|
+
rafId = null;
|
|
3839
|
+
if (deps.isDestroyed()) return;
|
|
3840
|
+
deps.recomputeSnaps();
|
|
3841
|
+
const isVertical = deps.isVerticalAxis();
|
|
3842
|
+
const visible = isVertical ? vv.height : vv.width;
|
|
3843
|
+
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
3844
|
+
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
3845
|
+
if (clamp < deps.getMaxAxisSize()) {
|
|
3846
|
+
deps.setMaxAxisSize(clamp);
|
|
3847
|
+
}
|
|
3848
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
3849
|
+
deps.cancelInFlight();
|
|
3850
|
+
deps.newCycle();
|
|
3851
|
+
const max = deps.getMaxAxisSize();
|
|
3852
|
+
deps.setSize(Math.min(deps.getSize(), max));
|
|
3853
|
+
const current = deps.resolveActiveSnap();
|
|
3854
|
+
if (current && !deps.isDragging()) {
|
|
3855
|
+
deps.applySize(Math.min(current.size, max));
|
|
3856
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
3857
|
+
} else {
|
|
3858
|
+
deps.applySize(deps.getSize());
|
|
3859
|
+
}
|
|
3860
|
+
});
|
|
3861
|
+
};
|
|
3862
|
+
vv.addEventListener("resize", onResize);
|
|
3863
|
+
return () => {
|
|
3864
|
+
vv.removeEventListener("resize", onResize);
|
|
3865
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
3866
|
+
};
|
|
3867
|
+
}
|
|
3868
|
+
|
|
3869
|
+
// src/core/features/engine-features.ts
|
|
3870
|
+
function routeFeature() {
|
|
3871
|
+
return {
|
|
3872
|
+
name: "route",
|
|
3873
|
+
install: (ctx) => {
|
|
3874
|
+
const teardowns = new TeardownStack();
|
|
3875
|
+
if (ctx.options.closeOnRouteChange) {
|
|
3876
|
+
teardowns.add(
|
|
3877
|
+
installRouteChange({
|
|
3878
|
+
isDestroyed: ctx.isDestroyed,
|
|
3879
|
+
getSize: ctx.getSize,
|
|
3880
|
+
close: () => ctx.close()
|
|
3881
|
+
})
|
|
3882
|
+
);
|
|
3883
|
+
}
|
|
3884
|
+
teardowns.add(
|
|
3885
|
+
installRoute({
|
|
3886
|
+
routedTo: ctx.options.routedTo,
|
|
3887
|
+
closeOnBack: ctx.options.closeOnBack,
|
|
3888
|
+
isTopSheet: ctx.isTopSheet,
|
|
3889
|
+
getSize: ctx.getSize,
|
|
3890
|
+
isDestroyed: ctx.isDestroyed,
|
|
3891
|
+
close: () => ctx.close("back"),
|
|
3892
|
+
on: ctx.on,
|
|
3893
|
+
sheetId: ctx.sheetId
|
|
3894
|
+
})
|
|
3895
|
+
);
|
|
3896
|
+
return () => teardowns.drain();
|
|
3897
|
+
}
|
|
3898
|
+
};
|
|
3899
|
+
}
|
|
3900
|
+
function persistFeature() {
|
|
3901
|
+
return {
|
|
3902
|
+
name: "persist",
|
|
3903
|
+
install: (ctx) => {
|
|
3904
|
+
const key = ctx.options.persistKey;
|
|
3905
|
+
if (!key) return;
|
|
3906
|
+
return installPersist({ on: ctx.on }, key);
|
|
3907
|
+
}
|
|
3908
|
+
};
|
|
3909
|
+
}
|
|
3910
|
+
function autoCollapseFeature() {
|
|
3911
|
+
return {
|
|
3912
|
+
name: "auto-collapse",
|
|
3913
|
+
install: (ctx) => installAutoCollapse({
|
|
3914
|
+
ms: ctx.options.autoCollapseAfter,
|
|
3915
|
+
isDestroyed: ctx.isDestroyed,
|
|
3916
|
+
isDragging: ctx.isDragging,
|
|
3917
|
+
getAllowedIds: ctx.getAllowedIds,
|
|
3918
|
+
getActiveId: ctx.getActiveId,
|
|
3919
|
+
resolveSnap: ctx.resolveSnap,
|
|
3920
|
+
snapTo: ctx.snapTo,
|
|
3921
|
+
on: ctx.on
|
|
3922
|
+
})
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
function contentSwipeFeature() {
|
|
3926
|
+
return {
|
|
3927
|
+
name: "content-swipe",
|
|
3928
|
+
stage: "attach",
|
|
3929
|
+
install: (ctx) => {
|
|
3930
|
+
if (!ctx.scrollContainer) return;
|
|
3931
|
+
return installContentSwipe({
|
|
3932
|
+
container: ctx.scrollContainer,
|
|
3933
|
+
isDragging: ctx.isDragging,
|
|
3934
|
+
isAnimating: ctx.isAnimating,
|
|
3935
|
+
getAllowedIds: ctx.allowedIdsBySize,
|
|
3936
|
+
getActiveId: ctx.getActiveId,
|
|
3937
|
+
snapTo: ctx.snapTo
|
|
3938
|
+
});
|
|
3939
|
+
}
|
|
3940
|
+
};
|
|
3941
|
+
}
|
|
3942
|
+
function visualViewportFeature() {
|
|
3943
|
+
return {
|
|
3944
|
+
name: "visual-viewport",
|
|
3945
|
+
install: (ctx) => {
|
|
3946
|
+
if (typeof window === "undefined") return;
|
|
3947
|
+
return installVisualViewport({
|
|
3948
|
+
element: ctx.element,
|
|
3949
|
+
isVerticalAxis: ctx.isVerticalAxis,
|
|
3950
|
+
isDestroyed: ctx.isDestroyed,
|
|
3951
|
+
isDragging: ctx.isDragging,
|
|
3952
|
+
recomputeSnaps: ctx.recomputeSnaps,
|
|
3953
|
+
resolveActiveSnap: ctx.resolveActiveSnap,
|
|
3954
|
+
getMaxAxisSize: ctx.getMaxAxisSize,
|
|
3955
|
+
getSize: ctx.getSize,
|
|
3956
|
+
setMaxAxisSize: ctx.setMaxAxisSize,
|
|
3957
|
+
setSize: ctx.setSize,
|
|
3958
|
+
applySize: ctx.applySize,
|
|
3959
|
+
cancelInFlight: ctx.cancelInFlight,
|
|
3960
|
+
newCycle: ctx.newCycle,
|
|
3961
|
+
isAnimating: ctx.isAnimating,
|
|
3962
|
+
resyncAfterCancel: ctx.resyncAfterResize
|
|
3963
|
+
});
|
|
3964
|
+
}
|
|
3965
|
+
};
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
// src/core/default-features.ts
|
|
3969
|
+
function defaultEngineFeatures() {
|
|
3970
|
+
return [
|
|
3971
|
+
contentSwipeFeature(),
|
|
3972
|
+
visualViewportFeature(),
|
|
3973
|
+
persistFeature(),
|
|
3974
|
+
autoCollapseFeature(),
|
|
3975
|
+
routeFeature()
|
|
3976
|
+
];
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3979
|
+
// src/core/BottomSheetEngine.ts
|
|
3980
|
+
var BottomSheetEngine = class extends BottomSheetCore {
|
|
3981
|
+
constructor(opts) {
|
|
3982
|
+
super({
|
|
3983
|
+
...opts,
|
|
3984
|
+
features: [...defaultEngineFeatures(), ...opts.features ?? []]
|
|
3985
|
+
});
|
|
3986
|
+
}
|
|
3987
|
+
};
|
|
3988
|
+
|
|
3715
3989
|
// src/core/lifecycle/sheetManager.ts
|
|
3716
3990
|
var createSheetManager = (initial = {}) => {
|
|
3717
3991
|
const registry = /* @__PURE__ */ new Map();
|
|
@@ -4462,6 +4736,7 @@ var OverlayEngine = class {
|
|
|
4462
4736
|
};
|
|
4463
4737
|
var createOverlay = (opts) => new OverlayEngine(opts);
|
|
4464
4738
|
|
|
4739
|
+
exports.BottomSheetCore = BottomSheetCore;
|
|
4465
4740
|
exports.BottomSheetEngine = BottomSheetEngine;
|
|
4466
4741
|
exports.DEFAULT_SPRING = DEFAULT_SPRING;
|
|
4467
4742
|
exports.OVERLAY_PRESETS = OVERLAY_PRESETS;
|
|
@@ -4471,8 +4746,11 @@ exports.SCRIM_PRESETS = SCRIM_PRESETS;
|
|
|
4471
4746
|
exports.allowedRange = allowedRange;
|
|
4472
4747
|
exports.applyOverlayPosition = applyOverlayPosition;
|
|
4473
4748
|
exports.attachGestures = attachGestures;
|
|
4749
|
+
exports.autoCollapseFeature = autoCollapseFeature;
|
|
4750
|
+
exports.contentSwipeFeature = contentSwipeFeature;
|
|
4474
4751
|
exports.createOverlay = createOverlay;
|
|
4475
4752
|
exports.createSheetManager = createSheetManager;
|
|
4753
|
+
exports.defaultEngineFeatures = defaultEngineFeatures;
|
|
4476
4754
|
exports.easeOutBack = easeOutBack;
|
|
4477
4755
|
exports.easeOutCubic = easeOutCubic;
|
|
4478
4756
|
exports.findById = findById;
|
|
@@ -4480,13 +4758,16 @@ exports.findNearest = findNearest;
|
|
|
4480
4758
|
exports.installFocusTrap = installFocusTrap;
|
|
4481
4759
|
exports.installGestures = installGestures;
|
|
4482
4760
|
exports.lockBodyScroll = lockBodyScroll;
|
|
4761
|
+
exports.persistFeature = persistFeature;
|
|
4483
4762
|
exports.prefersReducedMotion = prefersReducedMotion;
|
|
4484
4763
|
exports.resolveSheetAnchoredStyle = resolveSheetAnchoredStyle;
|
|
4485
4764
|
exports.resolveSnap = resolveSnap;
|
|
4486
4765
|
exports.resolveSnapList = resolveSnapList;
|
|
4766
|
+
exports.routeFeature = routeFeature;
|
|
4487
4767
|
exports.runAnchorTransition = runAnchorTransition;
|
|
4488
4768
|
exports.runSpring = runSpring;
|
|
4489
4769
|
exports.sheetStack = sheetStack;
|
|
4490
4770
|
exports.tween = tween;
|
|
4771
|
+
exports.visualViewportFeature = visualViewportFeature;
|
|
4491
4772
|
//# sourceMappingURL=index.cjs.map
|
|
4492
4773
|
//# sourceMappingURL=index.cjs.map
|