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