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