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