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