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