@surdeddd/bottom-sheet 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -1
- package/dist/{BottomSheetEngine-D6oiEfZ4.d.cts → BottomSheetCore-CsIjyq7C.d.cts} +60 -5
- package/dist/{BottomSheetEngine-Dhy0X_e9.d.ts → BottomSheetCore-D16lsa6g.d.ts} +60 -5
- package/dist/BottomSheetEngine-BYjAVrmd.d.cts +7 -0
- package/dist/BottomSheetEngine-YuCNugZn.d.ts +7 -0
- package/dist/core.cjs +3476 -0
- package/dist/core.d.cts +3 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +3474 -0
- package/dist/debug.cjs +109 -0
- package/dist/debug.d.cts +22 -0
- package/dist/debug.d.ts +22 -0
- package/dist/debug.js +107 -0
- package/dist/element.cjs +972 -685
- package/dist/element.d.cts +2 -1
- package/dist/element.d.ts +2 -1
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +972 -685
- package/dist/features.cjs +533 -0
- package/dist/features.d.cts +13 -0
- package/dist/features.d.ts +13 -0
- package/dist/features.js +526 -0
- package/dist/index-DdYLOIIT.d.ts +15 -0
- package/dist/index-dfrzw-lI.d.cts +15 -0
- package/dist/index.cjs +805 -534
- package/dist/index.d.cts +6 -15
- package/dist/index.d.ts +6 -15
- package/dist/index.js +799 -535
- package/dist/integrations/formik.d.cts +1 -1
- package/dist/integrations/formik.d.ts +1 -1
- package/dist/integrations/react-hook-form.d.cts +1 -1
- package/dist/integrations/react-hook-form.d.ts +1 -1
- package/dist/overlay.cjs +6 -5
- package/dist/overlay.js +6 -5
- package/dist/preact.d.cts +2 -1
- package/dist/preact.d.ts +2 -1
- package/dist/qwik-lib/index.qwik.cjs +4267 -0
- package/dist/qwik-lib/index.qwik.mjs +4267 -0
- package/dist/qwik.cjs +798 -534
- package/dist/qwik.d.cts +2 -2
- package/dist/qwik.d.ts +2 -2
- package/dist/qwik.js +798 -534
- package/dist/react.cjs +798 -534
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +798 -534
- package/dist/solid.cjs +798 -534
- package/dist/solid.d.cts +63 -4
- package/dist/solid.d.ts +63 -4
- package/dist/solid.js +798 -534
- package/dist/solid.source.jsx +798 -534
- package/dist/svelte-core.cjs +798 -534
- package/dist/svelte-core.js +798 -534
- package/dist/svelte.cjs +798 -534
- package/dist/svelte.js +798 -534
- package/dist/vue.cjs +909 -637
- package/dist/vue.js +909 -637
- package/package.json +63 -11
package/dist/svelte-core.cjs
CHANGED
|
@@ -350,74 +350,6 @@ var SnapResolver = class {
|
|
|
350
350
|
}
|
|
351
351
|
};
|
|
352
352
|
|
|
353
|
-
// src/core/features/persist.ts
|
|
354
|
-
function readPersistedId(key) {
|
|
355
|
-
if (!key) return null;
|
|
356
|
-
if (typeof window === "undefined") return null;
|
|
357
|
-
if (typeof localStorage === "undefined") return null;
|
|
358
|
-
try {
|
|
359
|
-
return localStorage.getItem(key);
|
|
360
|
-
} catch {
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
function installPersist(engine, key) {
|
|
365
|
-
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
366
|
-
if (typeof window === "undefined") return;
|
|
367
|
-
if (typeof localStorage === "undefined") return;
|
|
368
|
-
try {
|
|
369
|
-
localStorage.setItem(key, id);
|
|
370
|
-
} catch {
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
return unsubscribe;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// src/core/features/auto-collapse.ts
|
|
377
|
-
function installAutoCollapse(deps) {
|
|
378
|
-
const { ms } = deps;
|
|
379
|
-
if (ms === void 0 || ms <= 0) {
|
|
380
|
-
return () => {
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
let timer = null;
|
|
384
|
-
const clearTimer = () => {
|
|
385
|
-
if (timer !== null) {
|
|
386
|
-
clearTimeout(timer);
|
|
387
|
-
timer = null;
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
const fire = () => {
|
|
391
|
-
if (deps.isDestroyed()) return;
|
|
392
|
-
if (deps.isDragging()) return;
|
|
393
|
-
const active = deps.resolveSnap(deps.getActiveId());
|
|
394
|
-
if (!active || active.size === 0) return;
|
|
395
|
-
let target = null;
|
|
396
|
-
for (const id of deps.getAllowedIds()) {
|
|
397
|
-
const snap = deps.resolveSnap(id);
|
|
398
|
-
if (!snap || snap.size <= 0) continue;
|
|
399
|
-
if (!target || snap.size < target.size) target = snap;
|
|
400
|
-
}
|
|
401
|
-
if (!target) return;
|
|
402
|
-
if (target.id === active.id || target.size >= active.size) return;
|
|
403
|
-
deps.snapTo(target.id);
|
|
404
|
-
};
|
|
405
|
-
const reset = () => {
|
|
406
|
-
clearTimer();
|
|
407
|
-
if (deps.isDestroyed()) return;
|
|
408
|
-
timer = setTimeout(() => {
|
|
409
|
-
timer = null;
|
|
410
|
-
fire();
|
|
411
|
-
}, ms);
|
|
412
|
-
};
|
|
413
|
-
const unsubscribe = deps.on("snap", () => reset());
|
|
414
|
-
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
415
|
-
return () => {
|
|
416
|
-
clearTimer();
|
|
417
|
-
unsubscribe();
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
|
|
421
353
|
// src/core/features/linked-sheets.ts
|
|
422
354
|
function notifyLinkedSheets(sheets, self) {
|
|
423
355
|
if (sheets.length === 0) return;
|
|
@@ -440,394 +372,65 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
440
372
|
}
|
|
441
373
|
}
|
|
442
374
|
|
|
443
|
-
// src/core/features/
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
var pendingRebrand = null;
|
|
449
|
-
var listenerInstalled = false;
|
|
450
|
-
var patchInstalled = false;
|
|
451
|
-
var origPushState = null;
|
|
452
|
-
var origReplaceState = null;
|
|
453
|
-
var patchedPushState = null;
|
|
454
|
-
var patchedReplaceState = null;
|
|
455
|
-
var hasWindow = () => typeof window !== "undefined";
|
|
456
|
-
var hasHistory = () => typeof history !== "undefined";
|
|
457
|
-
var brandMarker = (surface) => ({
|
|
458
|
-
...surface.markerState(),
|
|
459
|
-
__bs: true
|
|
460
|
-
});
|
|
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;
|
|
375
|
+
// src/core/features/resize-observer.ts
|
|
376
|
+
function installResizeObserver(deps) {
|
|
377
|
+
if (typeof window === "undefined") {
|
|
378
|
+
return () => {
|
|
379
|
+
};
|
|
527
380
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
381
|
+
const onResize = () => {
|
|
382
|
+
if (deps.isDestroyed()) return;
|
|
383
|
+
deps.recomputeSnaps();
|
|
384
|
+
const mode = deps.getMode();
|
|
385
|
+
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
386
|
+
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
387
|
+
const max = deps.getMaxAxisSize();
|
|
388
|
+
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
389
|
+
deps.setMaxAxisSize(viewportSize2);
|
|
536
390
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
391
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
392
|
+
deps.cancelInFlight();
|
|
393
|
+
deps.newCycle();
|
|
394
|
+
const current = deps.resolveActiveSnap();
|
|
395
|
+
const newMax = deps.getMaxAxisSize();
|
|
396
|
+
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
397
|
+
deps.setSize(targetSize);
|
|
398
|
+
if (current && !deps.isDragging()) {
|
|
399
|
+
deps.applySize(targetSize);
|
|
400
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
541
401
|
}
|
|
402
|
+
};
|
|
403
|
+
let resizeObserver = null;
|
|
404
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
405
|
+
resizeObserver = new ResizeObserver(onResize);
|
|
406
|
+
resizeObserver.observe(document.documentElement);
|
|
407
|
+
} else {
|
|
408
|
+
window.addEventListener("resize", onResize);
|
|
542
409
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
if (
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
555
|
-
maybeTeardownListener();
|
|
410
|
+
window.addEventListener("orientationchange", onResize);
|
|
411
|
+
const onVisibility = () => {
|
|
412
|
+
if (deps.isDestroyed()) return;
|
|
413
|
+
if (document.hidden) deps.cancelInFlight();
|
|
414
|
+
};
|
|
415
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
416
|
+
return () => {
|
|
417
|
+
resizeObserver?.disconnect();
|
|
418
|
+
window.removeEventListener("resize", onResize);
|
|
419
|
+
window.removeEventListener("orientationchange", onResize);
|
|
420
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
421
|
+
};
|
|
556
422
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
entries.push(entry);
|
|
569
|
-
ensureListener();
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
function pushBackMarker(surface) {
|
|
573
|
-
const entry = { surface, priorUrl: void 0, live: false };
|
|
574
|
-
if (!hasWindow() || !hasHistory()) {
|
|
575
|
-
return entry;
|
|
576
|
-
}
|
|
577
|
-
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
578
|
-
runInternal(() => {
|
|
579
|
-
try {
|
|
580
|
-
history.pushState(brandMarker(surface), "", surface.url);
|
|
581
|
-
entry.live = true;
|
|
582
|
-
} catch {
|
|
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
|
-
brandMarker(rebrandSurface),
|
|
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);
|
|
423
|
+
|
|
424
|
+
// src/core/features/fit-observer.ts
|
|
425
|
+
var contentTargets = (scroller) => {
|
|
426
|
+
if (!scroller) return [];
|
|
427
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
428
|
+
const out = [];
|
|
429
|
+
for (const child of Array.from(scroller.children)) {
|
|
430
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
431
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
432
|
+
} else {
|
|
433
|
+
out.push(child);
|
|
831
434
|
}
|
|
832
435
|
}
|
|
833
436
|
return out;
|
|
@@ -1669,6 +1272,52 @@ function resolveAnimationPreset(animation) {
|
|
|
1669
1272
|
}
|
|
1670
1273
|
}
|
|
1671
1274
|
|
|
1275
|
+
// src/core/animation/waapi-settle.ts
|
|
1276
|
+
var SIM_HZ = 240;
|
|
1277
|
+
var SAMPLE_STRIDE = 4;
|
|
1278
|
+
var MAX_SIM_MS = 3e3;
|
|
1279
|
+
function sampleSpringSettle(from, to, velocityPxPerS, config) {
|
|
1280
|
+
const cfg = { ...DEFAULT_SPRING, ...config };
|
|
1281
|
+
const subDt = 1 / SIM_HZ;
|
|
1282
|
+
const stepMs = SAMPLE_STRIDE / SIM_HZ * 1e3;
|
|
1283
|
+
const maxSteps = Math.ceil(MAX_SIM_MS / 1e3 * SIM_HZ);
|
|
1284
|
+
const values = [from];
|
|
1285
|
+
let x = from;
|
|
1286
|
+
let v = velocityPxPerS;
|
|
1287
|
+
for (let i = 1; i <= maxSteps; i += 1) {
|
|
1288
|
+
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1289
|
+
v += force / cfg.mass * subDt;
|
|
1290
|
+
x += v * subDt;
|
|
1291
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1292
|
+
values.push(to);
|
|
1293
|
+
break;
|
|
1294
|
+
}
|
|
1295
|
+
if (i % SAMPLE_STRIDE === 0) values.push(x);
|
|
1296
|
+
const atRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1297
|
+
if (atRest) break;
|
|
1298
|
+
}
|
|
1299
|
+
if (values[values.length - 1] !== to) values.push(to);
|
|
1300
|
+
return {
|
|
1301
|
+
values,
|
|
1302
|
+
stepMs,
|
|
1303
|
+
durationMs: (values.length - 1) * stepMs
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
function sampleTweenSettle(from, to, durationMs, easing) {
|
|
1307
|
+
const count = Math.max(2, Math.min(60, Math.round(durationMs / 16)));
|
|
1308
|
+
const values = [];
|
|
1309
|
+
for (let i = 0; i <= count; i += 1) {
|
|
1310
|
+
const t = i / count;
|
|
1311
|
+
values.push(from + (to - from) * easing(t));
|
|
1312
|
+
}
|
|
1313
|
+
values[values.length - 1] = to;
|
|
1314
|
+
return {
|
|
1315
|
+
values,
|
|
1316
|
+
stepMs: durationMs / count,
|
|
1317
|
+
durationMs
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1672
1321
|
// src/core/controllers/animation-runner.ts
|
|
1673
1322
|
var DEFAULT_DURATION2 = 220;
|
|
1674
1323
|
var VELOCITY_PX_PER_S = 1e3;
|
|
@@ -1679,6 +1328,10 @@ var AnimationRunner = class {
|
|
|
1679
1328
|
__publicField(this, "applySizeFn");
|
|
1680
1329
|
__publicField(this, "getSize");
|
|
1681
1330
|
__publicField(this, "isDragging");
|
|
1331
|
+
__publicField(this, "applyAux");
|
|
1332
|
+
__publicField(this, "getTransformFor");
|
|
1333
|
+
__publicField(this, "settleWaapi");
|
|
1334
|
+
__publicField(this, "currentWaapi", null);
|
|
1682
1335
|
__publicField(this, "animationKind");
|
|
1683
1336
|
__publicField(this, "springConfig");
|
|
1684
1337
|
__publicField(this, "duration");
|
|
@@ -1694,6 +1347,9 @@ var AnimationRunner = class {
|
|
|
1694
1347
|
this.applySizeFn = deps.applySize;
|
|
1695
1348
|
this.getSize = deps.getSize;
|
|
1696
1349
|
this.isDragging = deps.isDragging;
|
|
1350
|
+
this.applyAux = deps.applyAux;
|
|
1351
|
+
this.getTransformFor = deps.getTransformFor;
|
|
1352
|
+
this.settleWaapi = opts.settleAnimation === "waapi";
|
|
1697
1353
|
const preset = resolveAnimationPreset(opts.animation);
|
|
1698
1354
|
this.animationKind = preset.kind;
|
|
1699
1355
|
this.duration = opts.duration ?? preset.duration ?? DEFAULT_DURATION2;
|
|
@@ -1718,13 +1374,22 @@ var AnimationRunner = class {
|
|
|
1718
1374
|
}
|
|
1719
1375
|
}
|
|
1720
1376
|
get isAnimating() {
|
|
1721
|
-
return this.currentTween !== null || this.currentSpring !== null;
|
|
1377
|
+
return this.currentTween !== null || this.currentSpring !== null || this.currentWaapi !== null;
|
|
1722
1378
|
}
|
|
1723
1379
|
cancel() {
|
|
1724
1380
|
this.currentTween?.cancel();
|
|
1725
1381
|
this.currentSpring?.cancel();
|
|
1726
|
-
|
|
1727
|
-
|
|
1382
|
+
if (this.currentWaapi) {
|
|
1383
|
+
const entry = this.currentWaapi;
|
|
1384
|
+
this.currentWaapi = null;
|
|
1385
|
+
entry.stop();
|
|
1386
|
+
try {
|
|
1387
|
+
entry.anim.cancel();
|
|
1388
|
+
} catch {
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
async animateTo(target, velocityPxPerMs) {
|
|
1728
1393
|
if (target === this.getSize()) {
|
|
1729
1394
|
if (!this.isAnimating && !this.isDragging()) {
|
|
1730
1395
|
this.element.style.willChange = "";
|
|
@@ -1741,6 +1406,27 @@ var AnimationRunner = class {
|
|
|
1741
1406
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1742
1407
|
return;
|
|
1743
1408
|
}
|
|
1409
|
+
if (this.settleWaapi && this.applyAux && this.getTransformFor && typeof this.element.animate === "function") {
|
|
1410
|
+
const samples = this.animationKind === "spring" ? sampleSpringSettle(
|
|
1411
|
+
this.getSize(),
|
|
1412
|
+
target,
|
|
1413
|
+
velocityPxPerMs * VELOCITY_PX_PER_S,
|
|
1414
|
+
this.springConfig
|
|
1415
|
+
) : sampleTweenSettle(
|
|
1416
|
+
this.getSize(),
|
|
1417
|
+
target,
|
|
1418
|
+
this.duration,
|
|
1419
|
+
this.easing
|
|
1420
|
+
);
|
|
1421
|
+
if (samples.values.length >= 2 && samples.durationMs > 0) {
|
|
1422
|
+
await this.runWaapiSettle(samples, target);
|
|
1423
|
+
if (!this.isAnimating) {
|
|
1424
|
+
this.getRootEl()?.removeAttribute("data-animating");
|
|
1425
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1426
|
+
}
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1744
1430
|
if (this.animationKind === "spring") {
|
|
1745
1431
|
const spring = runSpring({
|
|
1746
1432
|
from: this.getSize(),
|
|
@@ -1769,11 +1455,66 @@ var AnimationRunner = class {
|
|
|
1769
1455
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1770
1456
|
}
|
|
1771
1457
|
}
|
|
1458
|
+
async runWaapiSettle(samples, target) {
|
|
1459
|
+
const applyAux = this.applyAux;
|
|
1460
|
+
const getTransformFor = this.getTransformFor;
|
|
1461
|
+
const frames = samples.values.map((v) => ({
|
|
1462
|
+
transform: getTransformFor(v)
|
|
1463
|
+
}));
|
|
1464
|
+
const anim = this.element.animate(frames, {
|
|
1465
|
+
duration: samples.durationMs,
|
|
1466
|
+
easing: "linear",
|
|
1467
|
+
fill: "forwards"
|
|
1468
|
+
});
|
|
1469
|
+
let stopped = false;
|
|
1470
|
+
let auxRaf = 0;
|
|
1471
|
+
const start = performance.now();
|
|
1472
|
+
const lastIdx = samples.values.length - 1;
|
|
1473
|
+
const auxTick = () => {
|
|
1474
|
+
if (stopped) return;
|
|
1475
|
+
const elapsed = performance.now() - start;
|
|
1476
|
+
const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
|
|
1477
|
+
applyAux(samples.values[idx]);
|
|
1478
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1479
|
+
};
|
|
1480
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1481
|
+
const entry = {
|
|
1482
|
+
anim,
|
|
1483
|
+
stop: () => {
|
|
1484
|
+
stopped = true;
|
|
1485
|
+
cancelAnimationFrame(auxRaf);
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
this.currentWaapi = entry;
|
|
1489
|
+
try {
|
|
1490
|
+
await anim.finished;
|
|
1491
|
+
} catch {
|
|
1492
|
+
}
|
|
1493
|
+
entry.stop();
|
|
1494
|
+
const wasCurrent = this.currentWaapi === entry;
|
|
1495
|
+
if (wasCurrent) this.currentWaapi = null;
|
|
1496
|
+
if (wasCurrent && anim.playState === "finished") {
|
|
1497
|
+
this.applySizeFn(target);
|
|
1498
|
+
try {
|
|
1499
|
+
anim.cancel();
|
|
1500
|
+
} catch {
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1772
1504
|
destroy() {
|
|
1773
1505
|
this.detachReducedMotion?.();
|
|
1774
1506
|
this.detachReducedMotion = null;
|
|
1775
1507
|
this.currentTween = null;
|
|
1776
1508
|
this.currentSpring = null;
|
|
1509
|
+
if (this.currentWaapi) {
|
|
1510
|
+
const entry = this.currentWaapi;
|
|
1511
|
+
this.currentWaapi = null;
|
|
1512
|
+
entry.stop();
|
|
1513
|
+
try {
|
|
1514
|
+
entry.anim.cancel();
|
|
1515
|
+
} catch {
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1777
1518
|
}
|
|
1778
1519
|
};
|
|
1779
1520
|
|
|
@@ -2630,7 +2371,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2630
2371
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2631
2372
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2632
2373
|
if (opts.persistKey) {
|
|
2633
|
-
const restored =
|
|
2374
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2634
2375
|
if (restored && initialAllowed.includes(restored)) {
|
|
2635
2376
|
initialId = restored;
|
|
2636
2377
|
}
|
|
@@ -2661,6 +2402,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2661
2402
|
},
|
|
2662
2403
|
animation: {
|
|
2663
2404
|
animation: opts.animation,
|
|
2405
|
+
settleAnimation: opts.settleAnimation,
|
|
2664
2406
|
duration: opts.duration,
|
|
2665
2407
|
easing: opts.easing,
|
|
2666
2408
|
spring: opts.spring,
|
|
@@ -2678,6 +2420,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2678
2420
|
}
|
|
2679
2421
|
};
|
|
2680
2422
|
}
|
|
2423
|
+
var readPersistedIdSafe = (key) => {
|
|
2424
|
+
if (typeof window === "undefined") return null;
|
|
2425
|
+
if (typeof localStorage === "undefined") return null;
|
|
2426
|
+
try {
|
|
2427
|
+
return localStorage.getItem(key);
|
|
2428
|
+
} catch {
|
|
2429
|
+
return null;
|
|
2430
|
+
}
|
|
2431
|
+
};
|
|
2681
2432
|
|
|
2682
2433
|
// src/core/primitives/teardown-stack.ts
|
|
2683
2434
|
var TeardownStack = class {
|
|
@@ -2700,9 +2451,9 @@ var TeardownStack = class {
|
|
|
2700
2451
|
}
|
|
2701
2452
|
};
|
|
2702
2453
|
|
|
2703
|
-
// src/core/
|
|
2454
|
+
// src/core/BottomSheetCore.ts
|
|
2704
2455
|
var HAPTIC_DURATION_MS = 8;
|
|
2705
|
-
var
|
|
2456
|
+
var BottomSheetCore = class {
|
|
2706
2457
|
constructor(opts) {
|
|
2707
2458
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
2708
2459
|
__publicField(this, "element");
|
|
@@ -2763,6 +2514,8 @@ var BottomSheetEngine = class {
|
|
|
2763
2514
|
__publicField(this, "stackEffectPrimed", false);
|
|
2764
2515
|
__publicField(this, "fitDeps");
|
|
2765
2516
|
__publicField(this, "transformTemplate");
|
|
2517
|
+
__publicField(this, "featureList", []);
|
|
2518
|
+
__publicField(this, "featureCtx");
|
|
2766
2519
|
const resolved = resolveEngineOptions(opts, {
|
|
2767
2520
|
shouldApplyInertSiblings: () => {
|
|
2768
2521
|
if (typeof document === "undefined") return false;
|
|
@@ -2809,7 +2562,9 @@ var BottomSheetEngine = class {
|
|
|
2809
2562
|
getRootEl: () => this.rootEl,
|
|
2810
2563
|
applySize: (size) => this.applySize(size),
|
|
2811
2564
|
getSize: () => this.size,
|
|
2812
|
-
isDragging: () => this.gesture?.isDragging ?? false
|
|
2565
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2566
|
+
applyAux: (size) => this.applySize(size, true),
|
|
2567
|
+
getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
|
|
2813
2568
|
},
|
|
2814
2569
|
resolved.animation
|
|
2815
2570
|
);
|
|
@@ -2832,6 +2587,11 @@ var BottomSheetEngine = class {
|
|
|
2832
2587
|
if (opts.linkedSheets) {
|
|
2833
2588
|
this.linkedSheets = opts.linkedSheets;
|
|
2834
2589
|
}
|
|
2590
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2591
|
+
for (const feature of opts.features ?? []) {
|
|
2592
|
+
byName.set(feature.name, feature);
|
|
2593
|
+
}
|
|
2594
|
+
this.featureList = Array.from(byName.values());
|
|
2835
2595
|
this.activeId = resolved.initialId;
|
|
2836
2596
|
auditVhUsage(this.snapPointsRaw);
|
|
2837
2597
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
@@ -2868,6 +2628,7 @@ var BottomSheetEngine = class {
|
|
|
2868
2628
|
scrollContainer: this.scrollContainer,
|
|
2869
2629
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize()
|
|
2870
2630
|
});
|
|
2631
|
+
this.featureCtx = this.buildFeatureContext(opts.autoCollapseAfter);
|
|
2871
2632
|
this.attach();
|
|
2872
2633
|
this.registerInStack();
|
|
2873
2634
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
@@ -2899,46 +2660,77 @@ var BottomSheetEngine = class {
|
|
|
2899
2660
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2900
2661
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2901
2662
|
this.applyAutoAriaLabelledBy();
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
getSize: () => this.size,
|
|
2907
|
-
close: () => this.close()
|
|
2908
|
-
})
|
|
2909
|
-
);
|
|
2910
|
-
}
|
|
2911
|
-
if (this.persistKey) {
|
|
2912
|
-
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2663
|
+
this.runFeatureStage("post");
|
|
2664
|
+
this.warnOrphanFeatureOptions();
|
|
2665
|
+
if (this.size > 0) {
|
|
2666
|
+
this.handleOpen();
|
|
2913
2667
|
}
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
resolveSnap: (id) => this.snaps.findById(id),
|
|
2922
|
-
snapTo: (id) => {
|
|
2923
|
-
void this.snapTo(id);
|
|
2924
|
-
},
|
|
2925
|
-
on: (event, fn) => this.on(event, fn)
|
|
2926
|
-
})
|
|
2927
|
-
);
|
|
2928
|
-
this.teardowns.add(
|
|
2929
|
-
installRoute({
|
|
2668
|
+
}
|
|
2669
|
+
buildFeatureContext(autoCollapseAfter) {
|
|
2670
|
+
return {
|
|
2671
|
+
element: this.element,
|
|
2672
|
+
scrollContainer: this.scrollContainer,
|
|
2673
|
+
sheetId: this.id,
|
|
2674
|
+
options: {
|
|
2930
2675
|
routedTo: this.routedTo,
|
|
2931
2676
|
closeOnBack: this.closeOnBack,
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
this.
|
|
2677
|
+
closeOnRouteChange: this.closeOnRouteChange,
|
|
2678
|
+
persistKey: this.persistKey,
|
|
2679
|
+
autoCollapseAfter
|
|
2680
|
+
},
|
|
2681
|
+
isDestroyed: () => this.destroyed,
|
|
2682
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2683
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2684
|
+
isTopSheet: () => this.isTopSheet,
|
|
2685
|
+
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
2686
|
+
getSize: () => this.size,
|
|
2687
|
+
getActiveId: () => this.activeId,
|
|
2688
|
+
getAllowedIds: () => this.snaps.getAllowedIds().slice(),
|
|
2689
|
+
allowedIdsBySize: () => this.allowedIdsBySize(),
|
|
2690
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2691
|
+
resolveSnap: (id) => this.snaps.findById(id),
|
|
2692
|
+
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
2693
|
+
setSize: (size) => {
|
|
2694
|
+
this.size = size;
|
|
2695
|
+
},
|
|
2696
|
+
setMaxAxisSize: (size) => {
|
|
2697
|
+
this.snaps.setMaxAxisSize(size);
|
|
2698
|
+
},
|
|
2699
|
+
applySize: (size) => this.applySize(size),
|
|
2700
|
+
recomputeSnaps: () => this.recomputeSnaps(),
|
|
2701
|
+
newCycle: () => {
|
|
2702
|
+
this.newCycle();
|
|
2703
|
+
},
|
|
2704
|
+
cancelInFlight: () => {
|
|
2705
|
+
this.animation.cancel();
|
|
2706
|
+
},
|
|
2707
|
+
resyncAfterResize: () => this.resyncAfterResize(),
|
|
2708
|
+
snapTo: (id) => {
|
|
2709
|
+
void this.snapTo(id);
|
|
2710
|
+
},
|
|
2711
|
+
close: (reason) => this.close(reason),
|
|
2712
|
+
on: (event, fn) => this.on(event, fn),
|
|
2713
|
+
addTeardown: (fn) => this.teardowns.add(fn)
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
runFeatureStage(stage) {
|
|
2717
|
+
for (const feature of this.featureList) {
|
|
2718
|
+
if ((feature.stage ?? "post") !== stage) continue;
|
|
2719
|
+
const teardown = feature.install(this.featureCtx);
|
|
2720
|
+
if (teardown) this.teardowns.add(teardown);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
warnOrphanFeatureOptions() {
|
|
2724
|
+
const names = new Set(this.featureList.map((f) => f.name));
|
|
2725
|
+
if ((this.closeOnBack || this.routedTo !== void 0 || this.closeOnRouteChange) && !names.has("route")) {
|
|
2726
|
+
devWarn(
|
|
2727
|
+
"[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
|
|
2728
|
+
);
|
|
2729
|
+
}
|
|
2730
|
+
if (this.persistKey && !names.has("persist")) {
|
|
2731
|
+
devWarn(
|
|
2732
|
+
"[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
|
|
2733
|
+
);
|
|
2942
2734
|
}
|
|
2943
2735
|
}
|
|
2944
2736
|
get state() {
|
|
@@ -3481,18 +3273,7 @@ var BottomSheetEngine = class {
|
|
|
3481
3273
|
}
|
|
3482
3274
|
}
|
|
3483
3275
|
attachFeatures() {
|
|
3484
|
-
|
|
3485
|
-
this.teardowns.add(installContentSwipe({
|
|
3486
|
-
container: this.scrollContainer,
|
|
3487
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3488
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3489
|
-
getAllowedIds: () => this.allowedIdsBySize(),
|
|
3490
|
-
getActiveId: () => this.activeId,
|
|
3491
|
-
snapTo: (id) => {
|
|
3492
|
-
void this.snapTo(id);
|
|
3493
|
-
}
|
|
3494
|
-
}));
|
|
3495
|
-
}
|
|
3276
|
+
this.runFeatureStage("attach");
|
|
3496
3277
|
if (typeof window !== "undefined") {
|
|
3497
3278
|
this.teardowns.add(installResizeObserver({
|
|
3498
3279
|
element: this.element,
|
|
@@ -3532,31 +3313,6 @@ var BottomSheetEngine = class {
|
|
|
3532
3313
|
() => document.removeEventListener("keydown", onKey)
|
|
3533
3314
|
);
|
|
3534
3315
|
}
|
|
3535
|
-
this.teardowns.add(installVisualViewport({
|
|
3536
|
-
element: this.element,
|
|
3537
|
-
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
3538
|
-
isDestroyed: () => this.destroyed,
|
|
3539
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3540
|
-
recomputeSnaps: () => this.recomputeSnaps(),
|
|
3541
|
-
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3542
|
-
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3543
|
-
getSize: () => this.size,
|
|
3544
|
-
setMaxAxisSize: (size) => {
|
|
3545
|
-
this.snaps.setMaxAxisSize(size);
|
|
3546
|
-
},
|
|
3547
|
-
setSize: (size) => {
|
|
3548
|
-
this.size = size;
|
|
3549
|
-
},
|
|
3550
|
-
applySize: (size) => this.applySize(size),
|
|
3551
|
-
cancelInFlight: () => {
|
|
3552
|
-
this.animation.cancel();
|
|
3553
|
-
},
|
|
3554
|
-
newCycle: () => {
|
|
3555
|
-
this.newCycle();
|
|
3556
|
-
},
|
|
3557
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3558
|
-
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3559
|
-
}));
|
|
3560
3316
|
}
|
|
3561
3317
|
this.teardowns.add(installSliderKeyboard({
|
|
3562
3318
|
handle: this.handle,
|
|
@@ -3633,13 +3389,13 @@ var BottomSheetEngine = class {
|
|
|
3633
3389
|
}
|
|
3634
3390
|
}
|
|
3635
3391
|
}
|
|
3636
|
-
applySize(size) {
|
|
3392
|
+
applySize(size, skipTransform = false) {
|
|
3637
3393
|
const cap = this.snaps.getMaxAxisSize();
|
|
3638
3394
|
const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
|
|
3639
3395
|
this.size = clamped;
|
|
3640
3396
|
const offset = cap - clamped;
|
|
3641
3397
|
const style = this.element.style;
|
|
3642
|
-
style.transform = this.transformTemplate(offset);
|
|
3398
|
+
if (!skipTransform) style.transform = this.transformTemplate(offset);
|
|
3643
3399
|
if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
|
|
3644
3400
|
style.setProperty("--bs-size", `${clamped}px`);
|
|
3645
3401
|
if (this.scrimParent) {
|
|
@@ -3717,6 +3473,514 @@ var BottomSheetEngine = class {
|
|
|
3717
3473
|
}
|
|
3718
3474
|
};
|
|
3719
3475
|
|
|
3476
|
+
// src/core/features/history-coordinator.ts
|
|
3477
|
+
var entries = [];
|
|
3478
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3479
|
+
var suppress = 0;
|
|
3480
|
+
var internalDepth = 0;
|
|
3481
|
+
var pendingRebrands = [];
|
|
3482
|
+
var listenerInstalled = false;
|
|
3483
|
+
var patchInstalled = false;
|
|
3484
|
+
var origPushState = null;
|
|
3485
|
+
var origReplaceState = null;
|
|
3486
|
+
var patchedPushState = null;
|
|
3487
|
+
var patchedReplaceState = null;
|
|
3488
|
+
var hasWindow = () => typeof window !== "undefined";
|
|
3489
|
+
var hasHistory = () => typeof history !== "undefined";
|
|
3490
|
+
var brandMarker = (surface) => ({
|
|
3491
|
+
...surface.markerState(),
|
|
3492
|
+
__bs: true
|
|
3493
|
+
});
|
|
3494
|
+
var runInternal = (fn) => {
|
|
3495
|
+
internalDepth += 1;
|
|
3496
|
+
try {
|
|
3497
|
+
fn();
|
|
3498
|
+
} finally {
|
|
3499
|
+
internalDepth -= 1;
|
|
3500
|
+
}
|
|
3501
|
+
};
|
|
3502
|
+
var notifyRouteChange = () => {
|
|
3503
|
+
const snapshot = Array.from(subscribers);
|
|
3504
|
+
for (const fn of snapshot) fn();
|
|
3505
|
+
};
|
|
3506
|
+
var ensureListener = () => {
|
|
3507
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
3508
|
+
window.addEventListener("popstate", onPopState);
|
|
3509
|
+
listenerInstalled = true;
|
|
3510
|
+
};
|
|
3511
|
+
var maybeTeardownListener = () => {
|
|
3512
|
+
if (!listenerInstalled) return;
|
|
3513
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
3514
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
3515
|
+
listenerInstalled = false;
|
|
3516
|
+
};
|
|
3517
|
+
var installPatch = () => {
|
|
3518
|
+
if (patchInstalled || !hasHistory()) return;
|
|
3519
|
+
origPushState = history.pushState;
|
|
3520
|
+
origReplaceState = history.replaceState;
|
|
3521
|
+
patchedPushState = function(...args) {
|
|
3522
|
+
origPushState.apply(this, args);
|
|
3523
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3524
|
+
};
|
|
3525
|
+
patchedReplaceState = function(...args) {
|
|
3526
|
+
origReplaceState.apply(this, args);
|
|
3527
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3528
|
+
};
|
|
3529
|
+
history.pushState = patchedPushState;
|
|
3530
|
+
history.replaceState = patchedReplaceState;
|
|
3531
|
+
patchInstalled = true;
|
|
3532
|
+
};
|
|
3533
|
+
var removePatch = () => {
|
|
3534
|
+
if (!patchInstalled) return;
|
|
3535
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
3536
|
+
history.pushState = origPushState;
|
|
3537
|
+
}
|
|
3538
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
3539
|
+
history.replaceState = origReplaceState;
|
|
3540
|
+
}
|
|
3541
|
+
origPushState = null;
|
|
3542
|
+
origReplaceState = null;
|
|
3543
|
+
patchedPushState = null;
|
|
3544
|
+
patchedReplaceState = null;
|
|
3545
|
+
patchInstalled = false;
|
|
3546
|
+
};
|
|
3547
|
+
function onPopState() {
|
|
3548
|
+
if (suppress > 0) {
|
|
3549
|
+
suppress -= 1;
|
|
3550
|
+
const rebrand = pendingRebrands.shift();
|
|
3551
|
+
if (rebrand) rebrand();
|
|
3552
|
+
maybeTeardownListener();
|
|
3553
|
+
return;
|
|
3554
|
+
}
|
|
3555
|
+
if (entries.length === 0) {
|
|
3556
|
+
notifyRouteChange();
|
|
3557
|
+
maybeTeardownListener();
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3560
|
+
let target = null;
|
|
3561
|
+
let targetIdx = -1;
|
|
3562
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3563
|
+
const entry = entries[i];
|
|
3564
|
+
if (!entry.surface.isOpen()) continue;
|
|
3565
|
+
if (!target) {
|
|
3566
|
+
target = entry;
|
|
3567
|
+
targetIdx = i;
|
|
3568
|
+
}
|
|
3569
|
+
if (entry.surface.isTop()) {
|
|
3570
|
+
target = entry;
|
|
3571
|
+
targetIdx = i;
|
|
3572
|
+
break;
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
if (!target) {
|
|
3576
|
+
const removed = entries.pop();
|
|
3577
|
+
if (removed) removed.live = false;
|
|
3578
|
+
maybeTeardownListener();
|
|
3579
|
+
return;
|
|
3580
|
+
}
|
|
3581
|
+
target.live = false;
|
|
3582
|
+
entries.splice(targetIdx, 1);
|
|
3583
|
+
const settled = target;
|
|
3584
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
3585
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
3586
|
+
});
|
|
3587
|
+
maybeTeardownListener();
|
|
3588
|
+
}
|
|
3589
|
+
function restore(entry) {
|
|
3590
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3591
|
+
entry.live = true;
|
|
3592
|
+
runInternal(() => {
|
|
3593
|
+
try {
|
|
3594
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
3595
|
+
} catch {
|
|
3596
|
+
entry.live = false;
|
|
3597
|
+
}
|
|
3598
|
+
});
|
|
3599
|
+
if (entry.live) {
|
|
3600
|
+
entries.push(entry);
|
|
3601
|
+
ensureListener();
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
function pushBackMarker(surface) {
|
|
3605
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
3606
|
+
if (!hasWindow() || !hasHistory()) {
|
|
3607
|
+
return entry;
|
|
3608
|
+
}
|
|
3609
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
3610
|
+
runInternal(() => {
|
|
3611
|
+
try {
|
|
3612
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
3613
|
+
entry.live = true;
|
|
3614
|
+
} catch {
|
|
3615
|
+
entry.live = false;
|
|
3616
|
+
}
|
|
3617
|
+
});
|
|
3618
|
+
if (entry.live) {
|
|
3619
|
+
entries.push(entry);
|
|
3620
|
+
ensureListener();
|
|
3621
|
+
}
|
|
3622
|
+
return entry;
|
|
3623
|
+
}
|
|
3624
|
+
function popBackMarker(handle) {
|
|
3625
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3626
|
+
const entry = handle;
|
|
3627
|
+
const idx = entries.indexOf(entry);
|
|
3628
|
+
if (idx === -1 || !entry.live) return;
|
|
3629
|
+
const last = entries.length - 1;
|
|
3630
|
+
entry.live = false;
|
|
3631
|
+
entries.splice(idx, 1);
|
|
3632
|
+
let rebrand = null;
|
|
3633
|
+
if (idx !== last) {
|
|
3634
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
3635
|
+
const rebrandUrl = entry.priorUrl;
|
|
3636
|
+
rebrand = () => {
|
|
3637
|
+
runInternal(() => {
|
|
3638
|
+
history.replaceState(
|
|
3639
|
+
brandMarker(rebrandSurface),
|
|
3640
|
+
"",
|
|
3641
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
3642
|
+
);
|
|
3643
|
+
});
|
|
3644
|
+
};
|
|
3645
|
+
}
|
|
3646
|
+
pendingRebrands.push(rebrand);
|
|
3647
|
+
suppress += 1;
|
|
3648
|
+
runInternal(() => {
|
|
3649
|
+
try {
|
|
3650
|
+
history.back();
|
|
3651
|
+
} catch {
|
|
3652
|
+
suppress = Math.max(0, suppress - 1);
|
|
3653
|
+
pendingRebrands.pop();
|
|
3654
|
+
}
|
|
3655
|
+
});
|
|
3656
|
+
maybeTeardownListener();
|
|
3657
|
+
}
|
|
3658
|
+
function subscribeRouteChange(fn) {
|
|
3659
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
3660
|
+
};
|
|
3661
|
+
subscribers.add(fn);
|
|
3662
|
+
if (subscribers.size === 1) installPatch();
|
|
3663
|
+
ensureListener();
|
|
3664
|
+
return () => {
|
|
3665
|
+
if (!subscribers.has(fn)) return;
|
|
3666
|
+
subscribers.delete(fn);
|
|
3667
|
+
if (subscribers.size === 0) removePatch();
|
|
3668
|
+
maybeTeardownListener();
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3672
|
+
// src/core/features/route.ts
|
|
3673
|
+
function installRoute(deps) {
|
|
3674
|
+
if (typeof window === "undefined") {
|
|
3675
|
+
return () => {
|
|
3676
|
+
};
|
|
3677
|
+
}
|
|
3678
|
+
if (!deps.routedTo && !deps.closeOnBack) {
|
|
3679
|
+
return () => {
|
|
3680
|
+
};
|
|
3681
|
+
}
|
|
3682
|
+
let handle = null;
|
|
3683
|
+
const onOpen = () => {
|
|
3684
|
+
if (handle) return;
|
|
3685
|
+
handle = pushBackMarker({
|
|
3686
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
3687
|
+
isTop: deps.isTopSheet,
|
|
3688
|
+
close: deps.close,
|
|
3689
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
3690
|
+
url: deps.routedTo
|
|
3691
|
+
});
|
|
3692
|
+
};
|
|
3693
|
+
const onClose = () => {
|
|
3694
|
+
if (!handle) return;
|
|
3695
|
+
popBackMarker(handle);
|
|
3696
|
+
handle = null;
|
|
3697
|
+
};
|
|
3698
|
+
const unsubscribeOpen = deps.on("open", onOpen);
|
|
3699
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
3700
|
+
if (deps.getSize() > 0) onOpen();
|
|
3701
|
+
return () => {
|
|
3702
|
+
unsubscribeOpen();
|
|
3703
|
+
unsubscribeClose();
|
|
3704
|
+
if (handle) {
|
|
3705
|
+
popBackMarker(handle);
|
|
3706
|
+
handle = null;
|
|
3707
|
+
}
|
|
3708
|
+
};
|
|
3709
|
+
}
|
|
3710
|
+
function installRouteChange(deps) {
|
|
3711
|
+
return subscribeRouteChange(() => {
|
|
3712
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
3713
|
+
void deps.close();
|
|
3714
|
+
});
|
|
3715
|
+
}
|
|
3716
|
+
|
|
3717
|
+
// src/core/features/persist.ts
|
|
3718
|
+
function installPersist(engine, key) {
|
|
3719
|
+
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
3720
|
+
if (typeof window === "undefined") return;
|
|
3721
|
+
if (typeof localStorage === "undefined") return;
|
|
3722
|
+
try {
|
|
3723
|
+
localStorage.setItem(key, id);
|
|
3724
|
+
} catch {
|
|
3725
|
+
}
|
|
3726
|
+
});
|
|
3727
|
+
return unsubscribe;
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3730
|
+
// src/core/features/auto-collapse.ts
|
|
3731
|
+
function installAutoCollapse(deps) {
|
|
3732
|
+
const { ms } = deps;
|
|
3733
|
+
if (ms === void 0 || ms <= 0) {
|
|
3734
|
+
return () => {
|
|
3735
|
+
};
|
|
3736
|
+
}
|
|
3737
|
+
let timer = null;
|
|
3738
|
+
const clearTimer = () => {
|
|
3739
|
+
if (timer !== null) {
|
|
3740
|
+
clearTimeout(timer);
|
|
3741
|
+
timer = null;
|
|
3742
|
+
}
|
|
3743
|
+
};
|
|
3744
|
+
const fire = () => {
|
|
3745
|
+
if (deps.isDestroyed()) return;
|
|
3746
|
+
if (deps.isDragging()) return;
|
|
3747
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
3748
|
+
if (!active || active.size === 0) return;
|
|
3749
|
+
let target = null;
|
|
3750
|
+
for (const id of deps.getAllowedIds()) {
|
|
3751
|
+
const snap = deps.resolveSnap(id);
|
|
3752
|
+
if (!snap || snap.size <= 0) continue;
|
|
3753
|
+
if (!target || snap.size < target.size) target = snap;
|
|
3754
|
+
}
|
|
3755
|
+
if (!target) return;
|
|
3756
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
3757
|
+
deps.snapTo(target.id);
|
|
3758
|
+
};
|
|
3759
|
+
const reset = () => {
|
|
3760
|
+
clearTimer();
|
|
3761
|
+
if (deps.isDestroyed()) return;
|
|
3762
|
+
timer = setTimeout(() => {
|
|
3763
|
+
timer = null;
|
|
3764
|
+
fire();
|
|
3765
|
+
}, ms);
|
|
3766
|
+
};
|
|
3767
|
+
const unsubscribe = deps.on("snap", () => reset());
|
|
3768
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
3769
|
+
return () => {
|
|
3770
|
+
clearTimer();
|
|
3771
|
+
unsubscribe();
|
|
3772
|
+
};
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3775
|
+
// src/core/features/content-swipe.ts
|
|
3776
|
+
var CONTENT_PULL_THRESHOLD = 60;
|
|
3777
|
+
function installContentSwipe(deps) {
|
|
3778
|
+
const { container } = deps;
|
|
3779
|
+
let startY = 0;
|
|
3780
|
+
let startScrollTop = 0;
|
|
3781
|
+
let moved = false;
|
|
3782
|
+
const onTouchStart = (e) => {
|
|
3783
|
+
const t = e.touches[0];
|
|
3784
|
+
if (!t) return;
|
|
3785
|
+
startY = t.clientY;
|
|
3786
|
+
startScrollTop = container.scrollTop;
|
|
3787
|
+
moved = false;
|
|
3788
|
+
};
|
|
3789
|
+
const onTouchMove = (e) => {
|
|
3790
|
+
const t = e.touches[0];
|
|
3791
|
+
if (!t) return;
|
|
3792
|
+
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
3793
|
+
};
|
|
3794
|
+
const onTouchEnd = (e) => {
|
|
3795
|
+
if (!moved) return;
|
|
3796
|
+
if (deps.isDragging() || deps.isAnimating()) return;
|
|
3797
|
+
if (container.scrollTop !== startScrollTop) return;
|
|
3798
|
+
const t = e.changedTouches[0];
|
|
3799
|
+
if (!t) return;
|
|
3800
|
+
const deltaY = t.clientY - startY;
|
|
3801
|
+
const atTop = container.scrollTop <= 0;
|
|
3802
|
+
const allowed = deps.getAllowedIds();
|
|
3803
|
+
const idx = allowed.indexOf(deps.getActiveId());
|
|
3804
|
+
if (idx === -1) return;
|
|
3805
|
+
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
3806
|
+
deps.snapTo(allowed[idx - 1]);
|
|
3807
|
+
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
3808
|
+
deps.snapTo(allowed[idx + 1]);
|
|
3809
|
+
}
|
|
3810
|
+
};
|
|
3811
|
+
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
3812
|
+
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
3813
|
+
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
3814
|
+
return () => {
|
|
3815
|
+
container.removeEventListener("touchstart", onTouchStart);
|
|
3816
|
+
container.removeEventListener("touchmove", onTouchMove);
|
|
3817
|
+
container.removeEventListener("touchend", onTouchEnd);
|
|
3818
|
+
};
|
|
3819
|
+
}
|
|
3820
|
+
|
|
3821
|
+
// src/core/features/visual-viewport.ts
|
|
3822
|
+
var SAFETY_PAD = 8;
|
|
3823
|
+
function installVisualViewport(deps) {
|
|
3824
|
+
if (typeof window === "undefined" || !window.visualViewport) {
|
|
3825
|
+
return () => {
|
|
3826
|
+
};
|
|
3827
|
+
}
|
|
3828
|
+
const vv = window.visualViewport;
|
|
3829
|
+
let rafId = null;
|
|
3830
|
+
const onResize = () => {
|
|
3831
|
+
if (rafId !== null) return;
|
|
3832
|
+
rafId = requestAnimationFrame(() => {
|
|
3833
|
+
rafId = null;
|
|
3834
|
+
if (deps.isDestroyed()) return;
|
|
3835
|
+
deps.recomputeSnaps();
|
|
3836
|
+
const isVertical = deps.isVerticalAxis();
|
|
3837
|
+
const visible = isVertical ? vv.height : vv.width;
|
|
3838
|
+
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
3839
|
+
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
3840
|
+
if (clamp < deps.getMaxAxisSize()) {
|
|
3841
|
+
deps.setMaxAxisSize(clamp);
|
|
3842
|
+
}
|
|
3843
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
3844
|
+
deps.cancelInFlight();
|
|
3845
|
+
deps.newCycle();
|
|
3846
|
+
const max = deps.getMaxAxisSize();
|
|
3847
|
+
deps.setSize(Math.min(deps.getSize(), max));
|
|
3848
|
+
const current = deps.resolveActiveSnap();
|
|
3849
|
+
if (current && !deps.isDragging()) {
|
|
3850
|
+
deps.applySize(Math.min(current.size, max));
|
|
3851
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
3852
|
+
} else {
|
|
3853
|
+
deps.applySize(deps.getSize());
|
|
3854
|
+
}
|
|
3855
|
+
});
|
|
3856
|
+
};
|
|
3857
|
+
vv.addEventListener("resize", onResize);
|
|
3858
|
+
return () => {
|
|
3859
|
+
vv.removeEventListener("resize", onResize);
|
|
3860
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
3861
|
+
};
|
|
3862
|
+
}
|
|
3863
|
+
|
|
3864
|
+
// src/core/features/engine-features.ts
|
|
3865
|
+
function routeFeature() {
|
|
3866
|
+
return {
|
|
3867
|
+
name: "route",
|
|
3868
|
+
install: (ctx) => {
|
|
3869
|
+
const teardowns = new TeardownStack();
|
|
3870
|
+
if (ctx.options.closeOnRouteChange) {
|
|
3871
|
+
teardowns.add(
|
|
3872
|
+
installRouteChange({
|
|
3873
|
+
isDestroyed: ctx.isDestroyed,
|
|
3874
|
+
getSize: ctx.getSize,
|
|
3875
|
+
close: () => ctx.close()
|
|
3876
|
+
})
|
|
3877
|
+
);
|
|
3878
|
+
}
|
|
3879
|
+
teardowns.add(
|
|
3880
|
+
installRoute({
|
|
3881
|
+
routedTo: ctx.options.routedTo,
|
|
3882
|
+
closeOnBack: ctx.options.closeOnBack,
|
|
3883
|
+
isTopSheet: ctx.isTopSheet,
|
|
3884
|
+
getSize: ctx.getSize,
|
|
3885
|
+
isDestroyed: ctx.isDestroyed,
|
|
3886
|
+
close: () => ctx.close("back"),
|
|
3887
|
+
on: ctx.on,
|
|
3888
|
+
sheetId: ctx.sheetId
|
|
3889
|
+
})
|
|
3890
|
+
);
|
|
3891
|
+
return () => teardowns.drain();
|
|
3892
|
+
}
|
|
3893
|
+
};
|
|
3894
|
+
}
|
|
3895
|
+
function persistFeature() {
|
|
3896
|
+
return {
|
|
3897
|
+
name: "persist",
|
|
3898
|
+
install: (ctx) => {
|
|
3899
|
+
const key = ctx.options.persistKey;
|
|
3900
|
+
if (!key) return;
|
|
3901
|
+
return installPersist({ on: ctx.on }, key);
|
|
3902
|
+
}
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3905
|
+
function autoCollapseFeature() {
|
|
3906
|
+
return {
|
|
3907
|
+
name: "auto-collapse",
|
|
3908
|
+
install: (ctx) => installAutoCollapse({
|
|
3909
|
+
ms: ctx.options.autoCollapseAfter,
|
|
3910
|
+
isDestroyed: ctx.isDestroyed,
|
|
3911
|
+
isDragging: ctx.isDragging,
|
|
3912
|
+
getAllowedIds: ctx.getAllowedIds,
|
|
3913
|
+
getActiveId: ctx.getActiveId,
|
|
3914
|
+
resolveSnap: ctx.resolveSnap,
|
|
3915
|
+
snapTo: ctx.snapTo,
|
|
3916
|
+
on: ctx.on
|
|
3917
|
+
})
|
|
3918
|
+
};
|
|
3919
|
+
}
|
|
3920
|
+
function contentSwipeFeature() {
|
|
3921
|
+
return {
|
|
3922
|
+
name: "content-swipe",
|
|
3923
|
+
stage: "attach",
|
|
3924
|
+
install: (ctx) => {
|
|
3925
|
+
if (!ctx.scrollContainer) return;
|
|
3926
|
+
return installContentSwipe({
|
|
3927
|
+
container: ctx.scrollContainer,
|
|
3928
|
+
isDragging: ctx.isDragging,
|
|
3929
|
+
isAnimating: ctx.isAnimating,
|
|
3930
|
+
getAllowedIds: ctx.allowedIdsBySize,
|
|
3931
|
+
getActiveId: ctx.getActiveId,
|
|
3932
|
+
snapTo: ctx.snapTo
|
|
3933
|
+
});
|
|
3934
|
+
}
|
|
3935
|
+
};
|
|
3936
|
+
}
|
|
3937
|
+
function visualViewportFeature() {
|
|
3938
|
+
return {
|
|
3939
|
+
name: "visual-viewport",
|
|
3940
|
+
install: (ctx) => {
|
|
3941
|
+
if (typeof window === "undefined") return;
|
|
3942
|
+
return installVisualViewport({
|
|
3943
|
+
element: ctx.element,
|
|
3944
|
+
isVerticalAxis: ctx.isVerticalAxis,
|
|
3945
|
+
isDestroyed: ctx.isDestroyed,
|
|
3946
|
+
isDragging: ctx.isDragging,
|
|
3947
|
+
recomputeSnaps: ctx.recomputeSnaps,
|
|
3948
|
+
resolveActiveSnap: ctx.resolveActiveSnap,
|
|
3949
|
+
getMaxAxisSize: ctx.getMaxAxisSize,
|
|
3950
|
+
getSize: ctx.getSize,
|
|
3951
|
+
setMaxAxisSize: ctx.setMaxAxisSize,
|
|
3952
|
+
setSize: ctx.setSize,
|
|
3953
|
+
applySize: ctx.applySize,
|
|
3954
|
+
cancelInFlight: ctx.cancelInFlight,
|
|
3955
|
+
newCycle: ctx.newCycle,
|
|
3956
|
+
isAnimating: ctx.isAnimating,
|
|
3957
|
+
resyncAfterCancel: ctx.resyncAfterResize
|
|
3958
|
+
});
|
|
3959
|
+
}
|
|
3960
|
+
};
|
|
3961
|
+
}
|
|
3962
|
+
|
|
3963
|
+
// src/core/default-features.ts
|
|
3964
|
+
function defaultEngineFeatures() {
|
|
3965
|
+
return [
|
|
3966
|
+
contentSwipeFeature(),
|
|
3967
|
+
visualViewportFeature(),
|
|
3968
|
+
persistFeature(),
|
|
3969
|
+
autoCollapseFeature(),
|
|
3970
|
+
routeFeature()
|
|
3971
|
+
];
|
|
3972
|
+
}
|
|
3973
|
+
|
|
3974
|
+
// src/core/BottomSheetEngine.ts
|
|
3975
|
+
var BottomSheetEngine = class extends BottomSheetCore {
|
|
3976
|
+
constructor(opts) {
|
|
3977
|
+
super({
|
|
3978
|
+
...opts,
|
|
3979
|
+
features: [...defaultEngineFeatures(), ...opts.features ?? []]
|
|
3980
|
+
});
|
|
3981
|
+
}
|
|
3982
|
+
};
|
|
3983
|
+
|
|
3720
3984
|
// src/core/features/teleport.ts
|
|
3721
3985
|
var resolveTeleportTarget = (target) => {
|
|
3722
3986
|
if (!target) return null;
|