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