@surdeddd/bottom-sheet 0.12.0 → 0.14.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 +85 -1
- package/dist/{BottomSheetEngine-D6oiEfZ4.d.cts → BottomSheetCore-Cp7dWy91.d.cts} +85 -5
- package/dist/{BottomSheetEngine-Dhy0X_e9.d.ts → BottomSheetCore-DJYwWOqt.d.ts} +85 -5
- package/dist/BottomSheetEngine-Lm7HIVHv.d.cts +7 -0
- package/dist/BottomSheetEngine-O5PbeKfe.d.ts +7 -0
- package/dist/core.cjs +3680 -0
- package/dist/core.d.cts +3 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +3678 -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 +1314 -829
- 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 +1314 -829
- package/dist/features.cjs +489 -0
- package/dist/features.d.cts +13 -0
- package/dist/features.d.ts +13 -0
- package/dist/features.js +482 -0
- package/dist/index-Bb5TRmyg.d.cts +9 -0
- package/dist/index-Cl9ebCP2.d.ts +9 -0
- package/dist/index.cjs +979 -1293
- package/dist/index.d.cts +43 -55
- package/dist/index.d.ts +43 -55
- package/dist/index.js +973 -1280
- 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 +11 -10
- package/dist/overlay.js +11 -10
- package/dist/preact.d.cts +2 -1
- package/dist/preact.d.ts +2 -1
- package/dist/qwik-lib/index.qwik.cjs +4418 -0
- package/dist/qwik-lib/index.qwik.mjs +4418 -0
- package/dist/qwik.cjs +1089 -657
- package/dist/qwik.d.cts +4 -2
- package/dist/qwik.d.ts +4 -2
- package/dist/qwik.js +1089 -657
- package/dist/react.cjs +1100 -665
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/react.js +1100 -665
- package/dist/solid.cjs +1095 -657
- package/dist/solid.d.cts +90 -4
- package/dist/solid.d.ts +90 -4
- package/dist/solid.js +1095 -657
- package/dist/solid.source.jsx +1103 -657
- package/dist/styles.css +24 -4
- package/dist/svelte-core.cjs +981 -557
- package/dist/svelte-core.js +981 -557
- package/dist/svelte-src/BottomSheet.svelte +14 -0
- package/dist/svelte.cjs +1091 -657
- package/dist/svelte.d.cts +2 -0
- package/dist/svelte.d.ts +2 -0
- package/dist/svelte.js +1091 -657
- package/dist/vue.cjs +1105 -657
- package/dist/vue.js +1105 -657
- package/dist/webgl.cjs +583 -0
- package/dist/webgl.d.cts +17 -0
- package/dist/webgl.d.ts +17 -0
- package/dist/webgl.js +581 -0
- package/package.json +88 -12
package/dist/solid.source.jsx
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
Show
|
|
10
10
|
} from "solid-js";
|
|
11
11
|
|
|
12
|
-
// src/core/lifecycle/
|
|
12
|
+
// src/core/lifecycle/sheet-stack.ts
|
|
13
13
|
var BASE_Z = 100;
|
|
14
14
|
var STEP = 10;
|
|
15
15
|
var SheetStack = class {
|
|
@@ -132,7 +132,7 @@ function createEventBus() {
|
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
// src/core/primitives/
|
|
135
|
+
// src/core/primitives/css-length.ts
|
|
136
136
|
var probe = null;
|
|
137
137
|
var PROBE_ATTR = "data-bs-probe";
|
|
138
138
|
var ensureProbe = (axis) => {
|
|
@@ -186,7 +186,7 @@ var resolveSnap = (point, mode, measureFit) => {
|
|
|
186
186
|
return Math.max(0, el.getBoundingClientRect().width);
|
|
187
187
|
};
|
|
188
188
|
|
|
189
|
-
// src/core/primitives/
|
|
189
|
+
// src/core/primitives/dev-warn.ts
|
|
190
190
|
function devWarn(...args) {
|
|
191
191
|
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
|
|
192
192
|
console.warn(...args);
|
|
@@ -354,74 +354,6 @@ var SnapResolver = class {
|
|
|
354
354
|
}
|
|
355
355
|
};
|
|
356
356
|
|
|
357
|
-
// src/core/features/persist.ts
|
|
358
|
-
function readPersistedId(key) {
|
|
359
|
-
if (!key) return null;
|
|
360
|
-
if (typeof window === "undefined") return null;
|
|
361
|
-
if (typeof localStorage === "undefined") return null;
|
|
362
|
-
try {
|
|
363
|
-
return localStorage.getItem(key);
|
|
364
|
-
} catch {
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
function installPersist(engine, key) {
|
|
369
|
-
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
370
|
-
if (typeof window === "undefined") return;
|
|
371
|
-
if (typeof localStorage === "undefined") return;
|
|
372
|
-
try {
|
|
373
|
-
localStorage.setItem(key, id);
|
|
374
|
-
} catch {
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
return unsubscribe;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// src/core/features/auto-collapse.ts
|
|
381
|
-
function installAutoCollapse(deps) {
|
|
382
|
-
const { ms } = deps;
|
|
383
|
-
if (ms === void 0 || ms <= 0) {
|
|
384
|
-
return () => {
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
let timer = null;
|
|
388
|
-
const clearTimer = () => {
|
|
389
|
-
if (timer !== null) {
|
|
390
|
-
clearTimeout(timer);
|
|
391
|
-
timer = null;
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
const fire = () => {
|
|
395
|
-
if (deps.isDestroyed()) return;
|
|
396
|
-
if (deps.isDragging()) return;
|
|
397
|
-
const active = deps.resolveSnap(deps.getActiveId());
|
|
398
|
-
if (!active || active.size === 0) return;
|
|
399
|
-
let target = null;
|
|
400
|
-
for (const id of deps.getAllowedIds()) {
|
|
401
|
-
const snap = deps.resolveSnap(id);
|
|
402
|
-
if (!snap || snap.size <= 0) continue;
|
|
403
|
-
if (!target || snap.size < target.size) target = snap;
|
|
404
|
-
}
|
|
405
|
-
if (!target) return;
|
|
406
|
-
if (target.id === active.id || target.size >= active.size) return;
|
|
407
|
-
deps.snapTo(target.id);
|
|
408
|
-
};
|
|
409
|
-
const reset = () => {
|
|
410
|
-
clearTimer();
|
|
411
|
-
if (deps.isDestroyed()) return;
|
|
412
|
-
timer = setTimeout(() => {
|
|
413
|
-
timer = null;
|
|
414
|
-
fire();
|
|
415
|
-
}, ms);
|
|
416
|
-
};
|
|
417
|
-
const unsubscribe = deps.on("snap", () => reset());
|
|
418
|
-
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
419
|
-
return () => {
|
|
420
|
-
clearTimer();
|
|
421
|
-
unsubscribe();
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
|
|
425
357
|
// src/core/features/linked-sheets.ts
|
|
426
358
|
function notifyLinkedSheets(sheets, self) {
|
|
427
359
|
if (sheets.length === 0) return;
|
|
@@ -444,394 +376,65 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
444
376
|
}
|
|
445
377
|
}
|
|
446
378
|
|
|
447
|
-
// src/core/features/
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
var pendingRebrand = null;
|
|
453
|
-
var listenerInstalled = false;
|
|
454
|
-
var patchInstalled = false;
|
|
455
|
-
var origPushState = null;
|
|
456
|
-
var origReplaceState = null;
|
|
457
|
-
var patchedPushState = null;
|
|
458
|
-
var patchedReplaceState = null;
|
|
459
|
-
var hasWindow = () => typeof window !== "undefined";
|
|
460
|
-
var hasHistory = () => typeof history !== "undefined";
|
|
461
|
-
var brandMarker = (surface) => ({
|
|
462
|
-
...surface.markerState(),
|
|
463
|
-
__bs: true
|
|
464
|
-
});
|
|
465
|
-
var runInternal = (fn) => {
|
|
466
|
-
internalDepth += 1;
|
|
467
|
-
try {
|
|
468
|
-
fn();
|
|
469
|
-
} finally {
|
|
470
|
-
internalDepth -= 1;
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
var notifyRouteChange = () => {
|
|
474
|
-
const snapshot = Array.from(subscribers);
|
|
475
|
-
for (const fn of snapshot) fn();
|
|
476
|
-
};
|
|
477
|
-
var ensureListener = () => {
|
|
478
|
-
if (listenerInstalled || !hasWindow()) return;
|
|
479
|
-
window.addEventListener("popstate", onPopState);
|
|
480
|
-
listenerInstalled = true;
|
|
481
|
-
};
|
|
482
|
-
var maybeTeardownListener = () => {
|
|
483
|
-
if (!listenerInstalled) return;
|
|
484
|
-
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
485
|
-
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
486
|
-
listenerInstalled = false;
|
|
487
|
-
};
|
|
488
|
-
var installPatch = () => {
|
|
489
|
-
if (patchInstalled || !hasHistory()) return;
|
|
490
|
-
origPushState = history.pushState;
|
|
491
|
-
origReplaceState = history.replaceState;
|
|
492
|
-
patchedPushState = function(...args) {
|
|
493
|
-
origPushState.apply(this, args);
|
|
494
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
495
|
-
};
|
|
496
|
-
patchedReplaceState = function(...args) {
|
|
497
|
-
origReplaceState.apply(this, args);
|
|
498
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
499
|
-
};
|
|
500
|
-
history.pushState = patchedPushState;
|
|
501
|
-
history.replaceState = patchedReplaceState;
|
|
502
|
-
patchInstalled = true;
|
|
503
|
-
};
|
|
504
|
-
var removePatch = () => {
|
|
505
|
-
if (!patchInstalled) return;
|
|
506
|
-
if (history.pushState === patchedPushState && origPushState) {
|
|
507
|
-
history.pushState = origPushState;
|
|
508
|
-
}
|
|
509
|
-
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
510
|
-
history.replaceState = origReplaceState;
|
|
511
|
-
}
|
|
512
|
-
origPushState = null;
|
|
513
|
-
origReplaceState = null;
|
|
514
|
-
patchedPushState = null;
|
|
515
|
-
patchedReplaceState = null;
|
|
516
|
-
patchInstalled = false;
|
|
517
|
-
};
|
|
518
|
-
function onPopState() {
|
|
519
|
-
if (suppress > 0) {
|
|
520
|
-
suppress -= 1;
|
|
521
|
-
const rebrand = pendingRebrand;
|
|
522
|
-
pendingRebrand = null;
|
|
523
|
-
if (rebrand) rebrand();
|
|
524
|
-
maybeTeardownListener();
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
if (entries.length === 0) {
|
|
528
|
-
notifyRouteChange();
|
|
529
|
-
maybeTeardownListener();
|
|
530
|
-
return;
|
|
379
|
+
// src/core/features/resize-observer.ts
|
|
380
|
+
function installResizeObserver(deps) {
|
|
381
|
+
if (typeof window === "undefined") {
|
|
382
|
+
return () => {
|
|
383
|
+
};
|
|
531
384
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
385
|
+
const onResize = () => {
|
|
386
|
+
if (deps.isDestroyed()) return;
|
|
387
|
+
deps.recomputeSnaps();
|
|
388
|
+
const mode = deps.getMode();
|
|
389
|
+
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
390
|
+
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
391
|
+
const max = deps.getMaxAxisSize();
|
|
392
|
+
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
393
|
+
deps.setMaxAxisSize(viewportSize2);
|
|
540
394
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
395
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
396
|
+
deps.cancelInFlight();
|
|
397
|
+
deps.newCycle();
|
|
398
|
+
const current = deps.resolveActiveSnap();
|
|
399
|
+
const newMax = deps.getMaxAxisSize();
|
|
400
|
+
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
401
|
+
deps.setSize(targetSize);
|
|
402
|
+
if (current && !deps.isDragging()) {
|
|
403
|
+
deps.applySize(targetSize);
|
|
404
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
545
405
|
}
|
|
406
|
+
};
|
|
407
|
+
let resizeObserver = null;
|
|
408
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
409
|
+
resizeObserver = new ResizeObserver(onResize);
|
|
410
|
+
resizeObserver.observe(document.documentElement);
|
|
411
|
+
} else {
|
|
412
|
+
window.addEventListener("resize", onResize);
|
|
546
413
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
maybeTeardownListener();
|
|
414
|
+
window.addEventListener("orientationchange", onResize);
|
|
415
|
+
const onVisibility = () => {
|
|
416
|
+
if (deps.isDestroyed()) return;
|
|
417
|
+
if (document.hidden) deps.cancelInFlight();
|
|
418
|
+
};
|
|
419
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
420
|
+
return () => {
|
|
421
|
+
resizeObserver?.disconnect();
|
|
422
|
+
window.removeEventListener("resize", onResize);
|
|
423
|
+
window.removeEventListener("orientationchange", onResize);
|
|
424
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
425
|
+
};
|
|
560
426
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
entries.push(entry);
|
|
573
|
-
ensureListener();
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
function pushBackMarker(surface) {
|
|
577
|
-
const entry = { surface, priorUrl: void 0, live: false };
|
|
578
|
-
if (!hasWindow() || !hasHistory()) {
|
|
579
|
-
return entry;
|
|
580
|
-
}
|
|
581
|
-
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
582
|
-
runInternal(() => {
|
|
583
|
-
try {
|
|
584
|
-
history.pushState(brandMarker(surface), "", surface.url);
|
|
585
|
-
entry.live = true;
|
|
586
|
-
} catch {
|
|
587
|
-
entry.live = false;
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
if (entry.live) {
|
|
591
|
-
entries.push(entry);
|
|
592
|
-
ensureListener();
|
|
593
|
-
}
|
|
594
|
-
return entry;
|
|
595
|
-
}
|
|
596
|
-
function popBackMarker(handle) {
|
|
597
|
-
if (!hasWindow() || !hasHistory()) return;
|
|
598
|
-
const entry = handle;
|
|
599
|
-
const idx = entries.indexOf(entry);
|
|
600
|
-
if (idx === -1 || !entry.live) return;
|
|
601
|
-
const last = entries.length - 1;
|
|
602
|
-
entry.live = false;
|
|
603
|
-
entries.splice(idx, 1);
|
|
604
|
-
if (idx !== last) {
|
|
605
|
-
const rebrandSurface = entries[entries.length - 1].surface;
|
|
606
|
-
const rebrandUrl = entry.priorUrl;
|
|
607
|
-
pendingRebrand = () => {
|
|
608
|
-
runInternal(() => {
|
|
609
|
-
history.replaceState(
|
|
610
|
-
brandMarker(rebrandSurface),
|
|
611
|
-
"",
|
|
612
|
-
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
613
|
-
);
|
|
614
|
-
});
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
suppress += 1;
|
|
618
|
-
runInternal(() => {
|
|
619
|
-
try {
|
|
620
|
-
history.back();
|
|
621
|
-
} catch {
|
|
622
|
-
suppress = Math.max(0, suppress - 1);
|
|
623
|
-
pendingRebrand = null;
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
maybeTeardownListener();
|
|
627
|
-
}
|
|
628
|
-
function subscribeRouteChange(fn) {
|
|
629
|
-
if (!hasWindow() || !hasHistory()) return () => {
|
|
630
|
-
};
|
|
631
|
-
subscribers.add(fn);
|
|
632
|
-
if (subscribers.size === 1) installPatch();
|
|
633
|
-
ensureListener();
|
|
634
|
-
return () => {
|
|
635
|
-
if (!subscribers.has(fn)) return;
|
|
636
|
-
subscribers.delete(fn);
|
|
637
|
-
if (subscribers.size === 0) removePatch();
|
|
638
|
-
maybeTeardownListener();
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// src/core/features/route.ts
|
|
643
|
-
function installRoute(deps) {
|
|
644
|
-
if (typeof window === "undefined") {
|
|
645
|
-
return () => {
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
if (!deps.routedTo && !deps.closeOnBack) {
|
|
649
|
-
return () => {
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
let handle = null;
|
|
653
|
-
const onOpen = () => {
|
|
654
|
-
if (handle) return;
|
|
655
|
-
handle = pushBackMarker({
|
|
656
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
657
|
-
isTop: deps.isTopSheet,
|
|
658
|
-
close: deps.close,
|
|
659
|
-
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
660
|
-
url: deps.routedTo
|
|
661
|
-
});
|
|
662
|
-
};
|
|
663
|
-
const onClose = () => {
|
|
664
|
-
if (!handle) return;
|
|
665
|
-
popBackMarker(handle);
|
|
666
|
-
handle = null;
|
|
667
|
-
};
|
|
668
|
-
const unsubscribeOpen = deps.on("open", onOpen);
|
|
669
|
-
const unsubscribeClose = deps.on("close", onClose);
|
|
670
|
-
if (deps.getSize() > 0) onOpen();
|
|
671
|
-
return () => {
|
|
672
|
-
unsubscribeOpen();
|
|
673
|
-
unsubscribeClose();
|
|
674
|
-
if (handle) {
|
|
675
|
-
popBackMarker(handle);
|
|
676
|
-
handle = null;
|
|
677
|
-
}
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
function installRouteChange(deps) {
|
|
681
|
-
return subscribeRouteChange(() => {
|
|
682
|
-
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
683
|
-
void deps.close();
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// src/core/features/content-swipe.ts
|
|
688
|
-
var CONTENT_PULL_THRESHOLD = 60;
|
|
689
|
-
function installContentSwipe(deps) {
|
|
690
|
-
const { container } = deps;
|
|
691
|
-
let startY = 0;
|
|
692
|
-
let startScrollTop = 0;
|
|
693
|
-
let moved = false;
|
|
694
|
-
const onTouchStart = (e) => {
|
|
695
|
-
const t = e.touches[0];
|
|
696
|
-
if (!t) return;
|
|
697
|
-
startY = t.clientY;
|
|
698
|
-
startScrollTop = container.scrollTop;
|
|
699
|
-
moved = false;
|
|
700
|
-
};
|
|
701
|
-
const onTouchMove = (e) => {
|
|
702
|
-
const t = e.touches[0];
|
|
703
|
-
if (!t) return;
|
|
704
|
-
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
705
|
-
};
|
|
706
|
-
const onTouchEnd = (e) => {
|
|
707
|
-
if (!moved) return;
|
|
708
|
-
if (deps.isDragging() || deps.isAnimating()) return;
|
|
709
|
-
if (container.scrollTop !== startScrollTop) return;
|
|
710
|
-
const t = e.changedTouches[0];
|
|
711
|
-
if (!t) return;
|
|
712
|
-
const deltaY = t.clientY - startY;
|
|
713
|
-
const atTop = container.scrollTop <= 0;
|
|
714
|
-
const allowed = deps.getAllowedIds();
|
|
715
|
-
const idx = allowed.indexOf(deps.getActiveId());
|
|
716
|
-
if (idx === -1) return;
|
|
717
|
-
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
718
|
-
deps.snapTo(allowed[idx - 1]);
|
|
719
|
-
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
720
|
-
deps.snapTo(allowed[idx + 1]);
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
|
-
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
724
|
-
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
725
|
-
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
726
|
-
return () => {
|
|
727
|
-
container.removeEventListener("touchstart", onTouchStart);
|
|
728
|
-
container.removeEventListener("touchmove", onTouchMove);
|
|
729
|
-
container.removeEventListener("touchend", onTouchEnd);
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
// src/core/features/visual-viewport.ts
|
|
734
|
-
var SAFETY_PAD = 8;
|
|
735
|
-
function installVisualViewport(deps) {
|
|
736
|
-
if (typeof window === "undefined" || !window.visualViewport) {
|
|
737
|
-
return () => {
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
const vv = window.visualViewport;
|
|
741
|
-
let rafId = null;
|
|
742
|
-
const onResize = () => {
|
|
743
|
-
if (rafId !== null) return;
|
|
744
|
-
rafId = requestAnimationFrame(() => {
|
|
745
|
-
rafId = null;
|
|
746
|
-
if (deps.isDestroyed()) return;
|
|
747
|
-
deps.recomputeSnaps();
|
|
748
|
-
const isVertical = deps.isVerticalAxis();
|
|
749
|
-
const visible = isVertical ? vv.height : vv.width;
|
|
750
|
-
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
751
|
-
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
752
|
-
if (clamp < deps.getMaxAxisSize()) {
|
|
753
|
-
deps.setMaxAxisSize(clamp);
|
|
754
|
-
}
|
|
755
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
756
|
-
deps.cancelInFlight();
|
|
757
|
-
deps.newCycle();
|
|
758
|
-
const max = deps.getMaxAxisSize();
|
|
759
|
-
deps.setSize(Math.min(deps.getSize(), max));
|
|
760
|
-
const current = deps.resolveActiveSnap();
|
|
761
|
-
if (current && !deps.isDragging()) {
|
|
762
|
-
deps.applySize(Math.min(current.size, max));
|
|
763
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
764
|
-
} else {
|
|
765
|
-
deps.applySize(deps.getSize());
|
|
766
|
-
}
|
|
767
|
-
});
|
|
768
|
-
};
|
|
769
|
-
vv.addEventListener("resize", onResize);
|
|
770
|
-
return () => {
|
|
771
|
-
vv.removeEventListener("resize", onResize);
|
|
772
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
// src/core/features/resize-observer.ts
|
|
777
|
-
function installResizeObserver(deps) {
|
|
778
|
-
if (typeof window === "undefined") {
|
|
779
|
-
return () => {
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
const onResize = () => {
|
|
783
|
-
if (deps.isDestroyed()) return;
|
|
784
|
-
deps.recomputeSnaps();
|
|
785
|
-
const mode = deps.getMode();
|
|
786
|
-
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
787
|
-
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
788
|
-
const max = deps.getMaxAxisSize();
|
|
789
|
-
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
790
|
-
deps.setMaxAxisSize(viewportSize2);
|
|
791
|
-
}
|
|
792
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
793
|
-
deps.cancelInFlight();
|
|
794
|
-
deps.newCycle();
|
|
795
|
-
const current = deps.resolveActiveSnap();
|
|
796
|
-
const newMax = deps.getMaxAxisSize();
|
|
797
|
-
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
798
|
-
deps.setSize(targetSize);
|
|
799
|
-
if (current && !deps.isDragging()) {
|
|
800
|
-
deps.applySize(targetSize);
|
|
801
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
let resizeObserver = null;
|
|
805
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
806
|
-
resizeObserver = new ResizeObserver(onResize);
|
|
807
|
-
resizeObserver.observe(document.documentElement);
|
|
808
|
-
} else {
|
|
809
|
-
window.addEventListener("resize", onResize);
|
|
810
|
-
}
|
|
811
|
-
window.addEventListener("orientationchange", onResize);
|
|
812
|
-
const onVisibility = () => {
|
|
813
|
-
if (deps.isDestroyed()) return;
|
|
814
|
-
if (document.hidden) deps.cancelInFlight();
|
|
815
|
-
};
|
|
816
|
-
document.addEventListener("visibilitychange", onVisibility);
|
|
817
|
-
return () => {
|
|
818
|
-
resizeObserver?.disconnect();
|
|
819
|
-
window.removeEventListener("resize", onResize);
|
|
820
|
-
window.removeEventListener("orientationchange", onResize);
|
|
821
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
822
|
-
};
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
// src/core/features/fit-observer.ts
|
|
826
|
-
var contentTargets = (scroller) => {
|
|
827
|
-
if (!scroller) return [];
|
|
828
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
829
|
-
const out = [];
|
|
830
|
-
for (const child of Array.from(scroller.children)) {
|
|
831
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
832
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
833
|
-
} else {
|
|
834
|
-
out.push(child);
|
|
427
|
+
|
|
428
|
+
// src/core/features/fit-observer.ts
|
|
429
|
+
var contentTargets = (scroller) => {
|
|
430
|
+
if (!scroller) return [];
|
|
431
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
432
|
+
const out = [];
|
|
433
|
+
for (const child of Array.from(scroller.children)) {
|
|
434
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
435
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
436
|
+
} else {
|
|
437
|
+
out.push(child);
|
|
835
438
|
}
|
|
836
439
|
}
|
|
837
440
|
return out;
|
|
@@ -1671,6 +1274,52 @@ function resolveAnimationPreset(animation) {
|
|
|
1671
1274
|
}
|
|
1672
1275
|
}
|
|
1673
1276
|
|
|
1277
|
+
// src/core/animation/waapi-settle.ts
|
|
1278
|
+
var SIM_HZ = 240;
|
|
1279
|
+
var SAMPLE_STRIDE = 4;
|
|
1280
|
+
var MAX_SIM_MS = 3e3;
|
|
1281
|
+
function sampleSpringSettle(from, to, velocityPxPerS, config) {
|
|
1282
|
+
const cfg = { ...DEFAULT_SPRING, ...config };
|
|
1283
|
+
const subDt = 1 / SIM_HZ;
|
|
1284
|
+
const stepMs = SAMPLE_STRIDE / SIM_HZ * 1e3;
|
|
1285
|
+
const maxSteps = Math.ceil(MAX_SIM_MS / 1e3 * SIM_HZ);
|
|
1286
|
+
const values = [from];
|
|
1287
|
+
let x = from;
|
|
1288
|
+
let v = velocityPxPerS;
|
|
1289
|
+
for (let i = 1; i <= maxSteps; i += 1) {
|
|
1290
|
+
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1291
|
+
v += force / cfg.mass * subDt;
|
|
1292
|
+
x += v * subDt;
|
|
1293
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1294
|
+
values.push(to);
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
if (i % SAMPLE_STRIDE === 0) values.push(x);
|
|
1298
|
+
const atRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1299
|
+
if (atRest) break;
|
|
1300
|
+
}
|
|
1301
|
+
if (values[values.length - 1] !== to) values.push(to);
|
|
1302
|
+
return {
|
|
1303
|
+
values,
|
|
1304
|
+
stepMs,
|
|
1305
|
+
durationMs: (values.length - 1) * stepMs
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
function sampleTweenSettle(from, to, durationMs, easing) {
|
|
1309
|
+
const count = Math.max(2, Math.min(60, Math.round(durationMs / 16)));
|
|
1310
|
+
const values = [];
|
|
1311
|
+
for (let i = 0; i <= count; i += 1) {
|
|
1312
|
+
const t = i / count;
|
|
1313
|
+
values.push(from + (to - from) * easing(t));
|
|
1314
|
+
}
|
|
1315
|
+
values[values.length - 1] = to;
|
|
1316
|
+
return {
|
|
1317
|
+
values,
|
|
1318
|
+
stepMs: durationMs / count,
|
|
1319
|
+
durationMs
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1674
1323
|
// src/core/controllers/animation-runner.ts
|
|
1675
1324
|
var DEFAULT_DURATION2 = 220;
|
|
1676
1325
|
var VELOCITY_PX_PER_S = 1e3;
|
|
@@ -1680,6 +1329,10 @@ var AnimationRunner = class {
|
|
|
1680
1329
|
applySizeFn;
|
|
1681
1330
|
getSize;
|
|
1682
1331
|
isDragging;
|
|
1332
|
+
applyAux;
|
|
1333
|
+
getTransformFor;
|
|
1334
|
+
settleWaapi;
|
|
1335
|
+
currentWaapi = null;
|
|
1683
1336
|
animationKind;
|
|
1684
1337
|
springConfig;
|
|
1685
1338
|
duration;
|
|
@@ -1696,6 +1349,9 @@ var AnimationRunner = class {
|
|
|
1696
1349
|
this.applySizeFn = deps.applySize;
|
|
1697
1350
|
this.getSize = deps.getSize;
|
|
1698
1351
|
this.isDragging = deps.isDragging;
|
|
1352
|
+
this.applyAux = deps.applyAux;
|
|
1353
|
+
this.getTransformFor = deps.getTransformFor;
|
|
1354
|
+
this.settleWaapi = opts.settleAnimation === "waapi";
|
|
1699
1355
|
const preset = resolveAnimationPreset(opts.animation);
|
|
1700
1356
|
this.animationKind = preset.kind;
|
|
1701
1357
|
this.duration = opts.duration ?? preset.duration ?? DEFAULT_DURATION2;
|
|
@@ -1720,11 +1376,20 @@ var AnimationRunner = class {
|
|
|
1720
1376
|
}
|
|
1721
1377
|
}
|
|
1722
1378
|
get isAnimating() {
|
|
1723
|
-
return this.currentTween !== null || this.currentSpring !== null;
|
|
1379
|
+
return this.currentTween !== null || this.currentSpring !== null || this.currentWaapi !== null;
|
|
1724
1380
|
}
|
|
1725
1381
|
cancel() {
|
|
1726
1382
|
this.currentTween?.cancel();
|
|
1727
1383
|
this.currentSpring?.cancel();
|
|
1384
|
+
if (this.currentWaapi) {
|
|
1385
|
+
const entry = this.currentWaapi;
|
|
1386
|
+
this.currentWaapi = null;
|
|
1387
|
+
entry.stop();
|
|
1388
|
+
try {
|
|
1389
|
+
entry.anim.cancel();
|
|
1390
|
+
} catch {
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1728
1393
|
}
|
|
1729
1394
|
async animateTo(target, velocityPxPerMs) {
|
|
1730
1395
|
if (target === this.getSize()) {
|
|
@@ -1743,6 +1408,27 @@ var AnimationRunner = class {
|
|
|
1743
1408
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1744
1409
|
return;
|
|
1745
1410
|
}
|
|
1411
|
+
if (this.settleWaapi && this.applyAux && this.getTransformFor && typeof this.element.animate === "function") {
|
|
1412
|
+
const samples = this.animationKind === "spring" ? sampleSpringSettle(
|
|
1413
|
+
this.getSize(),
|
|
1414
|
+
target,
|
|
1415
|
+
velocityPxPerMs * VELOCITY_PX_PER_S,
|
|
1416
|
+
this.springConfig
|
|
1417
|
+
) : sampleTweenSettle(
|
|
1418
|
+
this.getSize(),
|
|
1419
|
+
target,
|
|
1420
|
+
this.duration,
|
|
1421
|
+
this.easing
|
|
1422
|
+
);
|
|
1423
|
+
if (samples.values.length >= 2 && samples.durationMs > 0) {
|
|
1424
|
+
await this.runWaapiSettle(samples, target);
|
|
1425
|
+
if (!this.isAnimating) {
|
|
1426
|
+
this.getRootEl()?.removeAttribute("data-animating");
|
|
1427
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1428
|
+
}
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1746
1432
|
if (this.animationKind === "spring") {
|
|
1747
1433
|
const spring = runSpring({
|
|
1748
1434
|
from: this.getSize(),
|
|
@@ -1771,15 +1457,70 @@ var AnimationRunner = class {
|
|
|
1771
1457
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1772
1458
|
}
|
|
1773
1459
|
}
|
|
1460
|
+
async runWaapiSettle(samples, target) {
|
|
1461
|
+
const applyAux = this.applyAux;
|
|
1462
|
+
const getTransformFor = this.getTransformFor;
|
|
1463
|
+
const frames = samples.values.map((v) => ({
|
|
1464
|
+
transform: getTransformFor(v)
|
|
1465
|
+
}));
|
|
1466
|
+
const anim = this.element.animate(frames, {
|
|
1467
|
+
duration: samples.durationMs,
|
|
1468
|
+
easing: "linear",
|
|
1469
|
+
fill: "forwards"
|
|
1470
|
+
});
|
|
1471
|
+
let stopped = false;
|
|
1472
|
+
let auxRaf = 0;
|
|
1473
|
+
const start = performance.now();
|
|
1474
|
+
const lastIdx = samples.values.length - 1;
|
|
1475
|
+
const auxTick = () => {
|
|
1476
|
+
if (stopped) return;
|
|
1477
|
+
const elapsed = performance.now() - start;
|
|
1478
|
+
const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
|
|
1479
|
+
applyAux(samples.values[idx]);
|
|
1480
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1481
|
+
};
|
|
1482
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1483
|
+
const entry = {
|
|
1484
|
+
anim,
|
|
1485
|
+
stop: () => {
|
|
1486
|
+
stopped = true;
|
|
1487
|
+
cancelAnimationFrame(auxRaf);
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
this.currentWaapi = entry;
|
|
1491
|
+
try {
|
|
1492
|
+
await anim.finished;
|
|
1493
|
+
} catch {
|
|
1494
|
+
}
|
|
1495
|
+
entry.stop();
|
|
1496
|
+
const wasCurrent = this.currentWaapi === entry;
|
|
1497
|
+
if (wasCurrent) this.currentWaapi = null;
|
|
1498
|
+
if (wasCurrent && anim.playState === "finished") {
|
|
1499
|
+
this.applySizeFn(target);
|
|
1500
|
+
try {
|
|
1501
|
+
anim.cancel();
|
|
1502
|
+
} catch {
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1774
1506
|
destroy() {
|
|
1775
1507
|
this.detachReducedMotion?.();
|
|
1776
1508
|
this.detachReducedMotion = null;
|
|
1777
1509
|
this.currentTween = null;
|
|
1778
1510
|
this.currentSpring = null;
|
|
1511
|
+
if (this.currentWaapi) {
|
|
1512
|
+
const entry = this.currentWaapi;
|
|
1513
|
+
this.currentWaapi = null;
|
|
1514
|
+
entry.stop();
|
|
1515
|
+
try {
|
|
1516
|
+
entry.anim.cancel();
|
|
1517
|
+
} catch {
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1779
1520
|
}
|
|
1780
1521
|
};
|
|
1781
1522
|
|
|
1782
|
-
// src/core/lifecycle/
|
|
1523
|
+
// src/core/lifecycle/focus-trap.ts
|
|
1783
1524
|
var FOCUSABLE = [
|
|
1784
1525
|
"a[href]",
|
|
1785
1526
|
"area[href]",
|
|
@@ -1897,7 +1638,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1897
1638
|
};
|
|
1898
1639
|
};
|
|
1899
1640
|
|
|
1900
|
-
// src/core/lifecycle/
|
|
1641
|
+
// src/core/lifecycle/scroll-lock.ts
|
|
1901
1642
|
var lockCount = 0;
|
|
1902
1643
|
var savedStyles = null;
|
|
1903
1644
|
var lockBodyScroll = () => {
|
|
@@ -2079,30 +1820,44 @@ var SampleRing = class {
|
|
|
2079
1820
|
this.size = 0;
|
|
2080
1821
|
}
|
|
2081
1822
|
};
|
|
2082
|
-
var installGestures = (handle, mode, callbacks) => {
|
|
1823
|
+
var installGestures = (handle, mode, callbacks, options = {}) => {
|
|
2083
1824
|
let activePointerId = null;
|
|
2084
1825
|
let activePointerType = "touch";
|
|
2085
1826
|
let startCoord = 0;
|
|
2086
1827
|
let lastCoord = 0;
|
|
1828
|
+
let pendingStart = false;
|
|
2087
1829
|
const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
|
|
2088
1830
|
const MAX_SAMPLES = 32;
|
|
2089
1831
|
const samples = new SampleRing(MAX_SAMPLES);
|
|
2090
1832
|
const axis = isAxisVertical(mode) ? "Y" : "X";
|
|
2091
1833
|
const sign = mode === "bottom" || mode === "right" ? -1 : 1;
|
|
2092
1834
|
const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
|
|
1835
|
+
const capture = (pointerId) => {
|
|
1836
|
+
try {
|
|
1837
|
+
handle.setPointerCapture(pointerId);
|
|
1838
|
+
} catch {
|
|
1839
|
+
}
|
|
1840
|
+
};
|
|
1841
|
+
const releaseTracking = () => {
|
|
1842
|
+
activePointerId = null;
|
|
1843
|
+
pendingStart = false;
|
|
1844
|
+
samples.reset();
|
|
1845
|
+
};
|
|
2093
1846
|
const onPointerDown = (e) => {
|
|
2094
1847
|
if (activePointerId !== null) return;
|
|
2095
1848
|
if (e.button !== void 0 && e.button !== 0) return;
|
|
1849
|
+
if (options.shouldStart && !options.shouldStart(e)) return;
|
|
2096
1850
|
activePointerId = e.pointerId;
|
|
2097
1851
|
activePointerType = e.pointerType || "touch";
|
|
2098
1852
|
startCoord = coordOf(e);
|
|
2099
1853
|
lastCoord = startCoord;
|
|
2100
1854
|
samples.reset();
|
|
2101
1855
|
samples.push(e.timeStamp, startCoord);
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
1856
|
+
if (options.deferStart) {
|
|
1857
|
+
pendingStart = true;
|
|
1858
|
+
return;
|
|
2105
1859
|
}
|
|
1860
|
+
capture(e.pointerId);
|
|
2106
1861
|
callbacks.onStart(startCoord, activePointerType);
|
|
2107
1862
|
};
|
|
2108
1863
|
const onPointerMove = (e) => {
|
|
@@ -2110,6 +1865,22 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2110
1865
|
const coord = coordOf(e);
|
|
2111
1866
|
const rawDelta = coord - startCoord;
|
|
2112
1867
|
const delta = rawDelta * sign;
|
|
1868
|
+
if (pendingStart) {
|
|
1869
|
+
const verdict = options.deferStart(e, delta);
|
|
1870
|
+
if (verdict === false) {
|
|
1871
|
+
releaseTracking();
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
if (verdict !== true) return;
|
|
1875
|
+
pendingStart = false;
|
|
1876
|
+
startCoord = coord;
|
|
1877
|
+
lastCoord = coord;
|
|
1878
|
+
samples.reset();
|
|
1879
|
+
samples.push(e.timeStamp, coord);
|
|
1880
|
+
capture(e.pointerId);
|
|
1881
|
+
callbacks.onStart(startCoord, activePointerType);
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
2113
1884
|
lastCoord = coord;
|
|
2114
1885
|
samples.push(e.timeStamp, coord);
|
|
2115
1886
|
const cutoff = e.timeStamp - VELOCITY_WINDOW_MS(activePointerType);
|
|
@@ -2118,6 +1889,10 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2118
1889
|
};
|
|
2119
1890
|
const finishGesture = (e) => {
|
|
2120
1891
|
if (e.pointerId !== activePointerId) return;
|
|
1892
|
+
if (pendingStart) {
|
|
1893
|
+
releaseTracking();
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
2121
1896
|
const rawDelta = lastCoord - startCoord;
|
|
2122
1897
|
const delta = rawDelta * sign;
|
|
2123
1898
|
let velocity = 0;
|
|
@@ -2140,22 +1915,26 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2140
1915
|
};
|
|
2141
1916
|
const onPointerCancel = (e) => {
|
|
2142
1917
|
if (e.pointerId !== activePointerId) return;
|
|
2143
|
-
|
|
2144
|
-
|
|
1918
|
+
const wasPending = pendingStart;
|
|
1919
|
+
releaseTracking();
|
|
1920
|
+
if (wasPending) return;
|
|
2145
1921
|
callbacks.onCancel?.();
|
|
2146
1922
|
};
|
|
2147
1923
|
handle.addEventListener("pointerdown", onPointerDown);
|
|
2148
1924
|
handle.addEventListener("pointermove", onPointerMove);
|
|
2149
1925
|
handle.addEventListener("pointerup", finishGesture);
|
|
2150
1926
|
handle.addEventListener("pointercancel", onPointerCancel);
|
|
1927
|
+
const managesTouchAction = options.manageTouchAction !== false;
|
|
2151
1928
|
const prevTouchAction = handle.style.touchAction;
|
|
2152
|
-
|
|
1929
|
+
if (managesTouchAction) {
|
|
1930
|
+
handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
|
|
1931
|
+
}
|
|
2153
1932
|
return () => {
|
|
2154
1933
|
handle.removeEventListener("pointerdown", onPointerDown);
|
|
2155
1934
|
handle.removeEventListener("pointermove", onPointerMove);
|
|
2156
1935
|
handle.removeEventListener("pointerup", finishGesture);
|
|
2157
1936
|
handle.removeEventListener("pointercancel", onPointerCancel);
|
|
2158
|
-
handle.style.touchAction = prevTouchAction;
|
|
1937
|
+
if (managesTouchAction) handle.style.touchAction = prevTouchAction;
|
|
2159
1938
|
if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
|
|
2160
1939
|
handle.releasePointerCapture(activePointerId);
|
|
2161
1940
|
}
|
|
@@ -2274,7 +2053,7 @@ var GestureController = class {
|
|
|
2274
2053
|
const restoreTo = this.dragStartSize;
|
|
2275
2054
|
void this.deps.animateTo(restoreTo, 0);
|
|
2276
2055
|
}
|
|
2277
|
-
});
|
|
2056
|
+
}, this.deps.gestureOptions);
|
|
2278
2057
|
return this.detach;
|
|
2279
2058
|
}
|
|
2280
2059
|
forceClearDragState() {
|
|
@@ -2286,6 +2065,41 @@ var GestureController = class {
|
|
|
2286
2065
|
}
|
|
2287
2066
|
};
|
|
2288
2067
|
|
|
2068
|
+
// src/core/primitives/drag-zones.ts
|
|
2069
|
+
var DRAG_ZONE_SELECTOR = "[data-bs-drag]";
|
|
2070
|
+
var NO_DRAG_SELECTOR = "[data-bs-no-drag]";
|
|
2071
|
+
var asElement = (target) => {
|
|
2072
|
+
const candidate = target;
|
|
2073
|
+
return candidate && typeof candidate.closest === "function" ? candidate : null;
|
|
2074
|
+
};
|
|
2075
|
+
function isDragAllowedFrom(target, mode) {
|
|
2076
|
+
const el = asElement(target);
|
|
2077
|
+
if (!el) return mode !== "zones";
|
|
2078
|
+
if (el.closest(NO_DRAG_SELECTOR)) return false;
|
|
2079
|
+
if (mode === "zones") return el.closest(DRAG_ZONE_SELECTOR) !== null;
|
|
2080
|
+
return true;
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
// src/core/primitives/content-gesture.ts
|
|
2084
|
+
var CONTENT_DRAG_SLOP = 6;
|
|
2085
|
+
function decideContentGesture(input) {
|
|
2086
|
+
const slop = input.slop ?? CONTENT_DRAG_SLOP;
|
|
2087
|
+
if (Math.abs(input.delta) < slop) return "pending";
|
|
2088
|
+
if (input.scrollTop > 0) return "scroll";
|
|
2089
|
+
if (input.delta > 0 && input.atMaxSnap) return "scroll";
|
|
2090
|
+
return "drag";
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// src/core/primitives/touch-scroll-guard.ts
|
|
2094
|
+
function installTouchScrollGuard(surface, isDragging) {
|
|
2095
|
+
const onTouchMove = (e) => {
|
|
2096
|
+
if (!isDragging()) return;
|
|
2097
|
+
if (e.cancelable) e.preventDefault();
|
|
2098
|
+
};
|
|
2099
|
+
surface.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
2100
|
+
return () => surface.removeEventListener("touchmove", onTouchMove);
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2289
2103
|
// src/core/primitives/aria-slider-writer.ts
|
|
2290
2104
|
var AriaSliderWriter = class {
|
|
2291
2105
|
constructor(handle, mode) {
|
|
@@ -2633,7 +2447,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2633
2447
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2634
2448
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2635
2449
|
if (opts.persistKey) {
|
|
2636
|
-
const restored =
|
|
2450
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2637
2451
|
if (restored && initialAllowed.includes(restored)) {
|
|
2638
2452
|
initialId = restored;
|
|
2639
2453
|
}
|
|
@@ -2642,6 +2456,8 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2642
2456
|
mode: opts.mode ?? "bottom",
|
|
2643
2457
|
flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
|
|
2644
2458
|
dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
|
|
2459
|
+
dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
|
|
2460
|
+
dragFromContent: opts.dragFromContent ?? true,
|
|
2645
2461
|
rubberBandEnabled: opts.rubberBand ?? true,
|
|
2646
2462
|
closeOnBack: opts.closeOnBack ?? false,
|
|
2647
2463
|
persistent: opts.persistent ?? false,
|
|
@@ -2664,6 +2480,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2664
2480
|
},
|
|
2665
2481
|
animation: {
|
|
2666
2482
|
animation: opts.animation,
|
|
2483
|
+
settleAnimation: opts.settleAnimation,
|
|
2667
2484
|
duration: opts.duration,
|
|
2668
2485
|
easing: opts.easing,
|
|
2669
2486
|
spring: opts.spring,
|
|
@@ -2681,6 +2498,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2681
2498
|
}
|
|
2682
2499
|
};
|
|
2683
2500
|
}
|
|
2501
|
+
var readPersistedIdSafe = (key) => {
|
|
2502
|
+
if (typeof window === "undefined") return null;
|
|
2503
|
+
if (typeof localStorage === "undefined") return null;
|
|
2504
|
+
try {
|
|
2505
|
+
return localStorage.getItem(key);
|
|
2506
|
+
} catch {
|
|
2507
|
+
return null;
|
|
2508
|
+
}
|
|
2509
|
+
};
|
|
2684
2510
|
|
|
2685
2511
|
// src/core/primitives/teardown-stack.ts
|
|
2686
2512
|
var TeardownStack = class {
|
|
@@ -2701,9 +2527,9 @@ var TeardownStack = class {
|
|
|
2701
2527
|
}
|
|
2702
2528
|
};
|
|
2703
2529
|
|
|
2704
|
-
// src/core/
|
|
2530
|
+
// src/core/BottomSheetCore.ts
|
|
2705
2531
|
var HAPTIC_DURATION_MS = 8;
|
|
2706
|
-
var
|
|
2532
|
+
var BottomSheetCore = class {
|
|
2707
2533
|
id = nextInstanceId("bs");
|
|
2708
2534
|
element;
|
|
2709
2535
|
handle;
|
|
@@ -2714,6 +2540,8 @@ var BottomSheetEngine = class {
|
|
|
2714
2540
|
mode;
|
|
2715
2541
|
flickVelocity;
|
|
2716
2542
|
dragThreshold;
|
|
2543
|
+
dragFromMode;
|
|
2544
|
+
dragFromContentDefault;
|
|
2717
2545
|
rubberBandEnabled;
|
|
2718
2546
|
scrim;
|
|
2719
2547
|
aria;
|
|
@@ -2731,8 +2559,11 @@ var BottomSheetEngine = class {
|
|
|
2731
2559
|
activeId;
|
|
2732
2560
|
size = 0;
|
|
2733
2561
|
gesture;
|
|
2562
|
+
contentGesture;
|
|
2563
|
+
detachSheetGesture = null;
|
|
2734
2564
|
rootEl = null;
|
|
2735
2565
|
destroyed = false;
|
|
2566
|
+
restClosed = false;
|
|
2736
2567
|
currentViewTransition = null;
|
|
2737
2568
|
currentAbort = new AbortController();
|
|
2738
2569
|
sizeWriteSentinel = new WriteSentinel();
|
|
@@ -2763,6 +2594,8 @@ var BottomSheetEngine = class {
|
|
|
2763
2594
|
stackEffectPrimed = false;
|
|
2764
2595
|
fitDeps;
|
|
2765
2596
|
transformTemplate;
|
|
2597
|
+
featureList = [];
|
|
2598
|
+
featureCtx;
|
|
2766
2599
|
constructor(opts) {
|
|
2767
2600
|
const resolved = resolveEngineOptions(opts, {
|
|
2768
2601
|
shouldApplyInertSiblings: () => {
|
|
@@ -2784,6 +2617,8 @@ var BottomSheetEngine = class {
|
|
|
2784
2617
|
this.aria = new AriaSliderWriter(this.handle, this.mode);
|
|
2785
2618
|
this.flickVelocity = resolved.flickVelocity;
|
|
2786
2619
|
this.dragThreshold = resolved.dragThreshold;
|
|
2620
|
+
this.dragFromMode = resolved.dragFrom;
|
|
2621
|
+
this.dragFromContentDefault = resolved.dragFromContent;
|
|
2787
2622
|
this.rubberBandEnabled = resolved.rubberBandEnabled;
|
|
2788
2623
|
this.scrim = new ScrimController(
|
|
2789
2624
|
{
|
|
@@ -2810,7 +2645,9 @@ var BottomSheetEngine = class {
|
|
|
2810
2645
|
getRootEl: () => this.rootEl,
|
|
2811
2646
|
applySize: (size) => this.applySize(size),
|
|
2812
2647
|
getSize: () => this.size,
|
|
2813
|
-
isDragging: () => this.
|
|
2648
|
+
isDragging: () => this.isDraggingAny(),
|
|
2649
|
+
applyAux: (size) => this.applySize(size, true),
|
|
2650
|
+
getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
|
|
2814
2651
|
},
|
|
2815
2652
|
resolved.animation
|
|
2816
2653
|
);
|
|
@@ -2833,6 +2670,11 @@ var BottomSheetEngine = class {
|
|
|
2833
2670
|
if (opts.linkedSheets) {
|
|
2834
2671
|
this.linkedSheets = opts.linkedSheets;
|
|
2835
2672
|
}
|
|
2673
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2674
|
+
for (const feature of opts.features ?? []) {
|
|
2675
|
+
byName.set(feature.name, feature);
|
|
2676
|
+
}
|
|
2677
|
+
this.featureList = Array.from(byName.values());
|
|
2836
2678
|
this.activeId = resolved.initialId;
|
|
2837
2679
|
auditVhUsage(this.snapPointsRaw);
|
|
2838
2680
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
@@ -2864,11 +2706,13 @@ var BottomSheetEngine = class {
|
|
|
2864
2706
|
const initial = this.snaps.findById(this.activeId);
|
|
2865
2707
|
if (initial) this.size = initial.size;
|
|
2866
2708
|
this.applySize(this.size);
|
|
2709
|
+
this.setRestClosed(this.size === 0);
|
|
2867
2710
|
this.updateAriaSlider();
|
|
2868
2711
|
this.scrollCache = createScrollCache({
|
|
2869
2712
|
scrollContainer: this.scrollContainer,
|
|
2870
2713
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize()
|
|
2871
2714
|
});
|
|
2715
|
+
this.featureCtx = this.buildFeatureContext(opts.autoCollapseAfter);
|
|
2872
2716
|
this.attach();
|
|
2873
2717
|
this.registerInStack();
|
|
2874
2718
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
@@ -2893,60 +2737,92 @@ var BottomSheetEngine = class {
|
|
|
2893
2737
|
(p) => p.size === "fit" || p.size === "content"
|
|
2894
2738
|
),
|
|
2895
2739
|
isDestroyed: () => this.destroyed,
|
|
2896
|
-
isDragging: () => this.
|
|
2740
|
+
isDragging: () => this.isDraggingAny(),
|
|
2897
2741
|
recompute: () => this.recompute()
|
|
2898
2742
|
})
|
|
2899
2743
|
);
|
|
2900
2744
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2901
2745
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2902
2746
|
this.applyAutoAriaLabelledBy();
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
getSize: () => this.size,
|
|
2908
|
-
close: () => this.close()
|
|
2909
|
-
})
|
|
2910
|
-
);
|
|
2911
|
-
}
|
|
2912
|
-
if (this.persistKey) {
|
|
2913
|
-
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2747
|
+
this.runFeatureStage("post");
|
|
2748
|
+
this.warnOrphanFeatureOptions();
|
|
2749
|
+
if (this.size > 0) {
|
|
2750
|
+
this.handleOpen();
|
|
2914
2751
|
}
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
resolveSnap: (id) => this.snaps.findById(id),
|
|
2923
|
-
snapTo: (id) => {
|
|
2924
|
-
void this.snapTo(id);
|
|
2925
|
-
},
|
|
2926
|
-
on: (event, fn) => this.on(event, fn)
|
|
2927
|
-
})
|
|
2928
|
-
);
|
|
2929
|
-
this.teardowns.add(
|
|
2930
|
-
installRoute({
|
|
2752
|
+
}
|
|
2753
|
+
buildFeatureContext(autoCollapseAfter) {
|
|
2754
|
+
return {
|
|
2755
|
+
element: this.element,
|
|
2756
|
+
scrollContainer: this.scrollContainer,
|
|
2757
|
+
sheetId: this.id,
|
|
2758
|
+
options: {
|
|
2931
2759
|
routedTo: this.routedTo,
|
|
2932
2760
|
closeOnBack: this.closeOnBack,
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
this.
|
|
2761
|
+
closeOnRouteChange: this.closeOnRouteChange,
|
|
2762
|
+
persistKey: this.persistKey,
|
|
2763
|
+
autoCollapseAfter
|
|
2764
|
+
},
|
|
2765
|
+
isDestroyed: () => this.destroyed,
|
|
2766
|
+
isDragging: () => this.isDraggingAny(),
|
|
2767
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2768
|
+
isTopSheet: () => this.isTopSheet,
|
|
2769
|
+
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
2770
|
+
getSize: () => this.size,
|
|
2771
|
+
getActiveId: () => this.activeId,
|
|
2772
|
+
getAllowedIds: () => this.snaps.getAllowedIds().slice(),
|
|
2773
|
+
allowedIdsBySize: () => this.allowedIdsBySize(),
|
|
2774
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2775
|
+
resolveSnap: (id) => this.snaps.findById(id),
|
|
2776
|
+
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
2777
|
+
setSize: (size) => {
|
|
2778
|
+
this.size = size;
|
|
2779
|
+
},
|
|
2780
|
+
setMaxAxisSize: (size) => {
|
|
2781
|
+
this.snaps.setMaxAxisSize(size);
|
|
2782
|
+
},
|
|
2783
|
+
applySize: (size) => this.applySize(size),
|
|
2784
|
+
recomputeSnaps: () => this.recomputeSnaps(),
|
|
2785
|
+
newCycle: () => {
|
|
2786
|
+
this.newCycle();
|
|
2787
|
+
},
|
|
2788
|
+
cancelInFlight: () => {
|
|
2789
|
+
this.animation.cancel();
|
|
2790
|
+
},
|
|
2791
|
+
resyncAfterResize: () => this.resyncAfterResize(),
|
|
2792
|
+
snapTo: (id) => {
|
|
2793
|
+
void this.snapTo(id);
|
|
2794
|
+
},
|
|
2795
|
+
close: (reason) => this.close(reason),
|
|
2796
|
+
attachDragSurface: (surface, kind) => this.attachDragSurface(surface, kind),
|
|
2797
|
+
on: (event, fn) => this.on(event, fn),
|
|
2798
|
+
addTeardown: (fn) => this.teardowns.add(fn)
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
runFeatureStage(stage) {
|
|
2802
|
+
for (const feature of this.featureList) {
|
|
2803
|
+
if ((feature.stage ?? "post") !== stage) continue;
|
|
2804
|
+
const teardown = feature.install(this.featureCtx);
|
|
2805
|
+
if (teardown) this.teardowns.add(teardown);
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
warnOrphanFeatureOptions() {
|
|
2809
|
+
const names = new Set(this.featureList.map((f) => f.name));
|
|
2810
|
+
if ((this.closeOnBack || this.routedTo !== void 0 || this.closeOnRouteChange) && !names.has("route")) {
|
|
2811
|
+
devWarn(
|
|
2812
|
+
"[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
|
|
2813
|
+
);
|
|
2814
|
+
}
|
|
2815
|
+
if (this.persistKey && !names.has("persist")) {
|
|
2816
|
+
devWarn(
|
|
2817
|
+
"[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
|
|
2818
|
+
);
|
|
2943
2819
|
}
|
|
2944
2820
|
}
|
|
2945
2821
|
get state() {
|
|
2946
2822
|
return {
|
|
2947
2823
|
size: this.size,
|
|
2948
2824
|
activeId: this.activeId,
|
|
2949
|
-
isDragging: this.
|
|
2825
|
+
isDragging: this.isDraggingAny(),
|
|
2950
2826
|
isAnimating: this.animation.isAnimating,
|
|
2951
2827
|
progress: this.computeProgress(this.size)
|
|
2952
2828
|
};
|
|
@@ -3066,9 +2942,16 @@ var BottomSheetEngine = class {
|
|
|
3066
2942
|
progress: this.computeProgress(this.size)
|
|
3067
2943
|
});
|
|
3068
2944
|
if (withHaptic) this.haptic();
|
|
2945
|
+
this.setRestClosed(targetSize === 0);
|
|
3069
2946
|
if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
|
|
3070
2947
|
if (targetSize === 0) this.emitCloseSequence();
|
|
3071
2948
|
}
|
|
2949
|
+
setRestClosed(closed) {
|
|
2950
|
+
if (closed === this.restClosed) return;
|
|
2951
|
+
this.restClosed = closed;
|
|
2952
|
+
if (closed) this.element.setAttribute("data-bs-rest", "closed");
|
|
2953
|
+
else this.element.removeAttribute("data-bs-rest");
|
|
2954
|
+
}
|
|
3072
2955
|
emitOpenSequence(id) {
|
|
3073
2956
|
this.emit("open", { id });
|
|
3074
2957
|
this.handleOpen();
|
|
@@ -3124,6 +3007,20 @@ var BottomSheetEngine = class {
|
|
|
3124
3007
|
if (this.destroyed) return;
|
|
3125
3008
|
this.disableDragFlag = value;
|
|
3126
3009
|
}
|
|
3010
|
+
setDragFromContent(value) {
|
|
3011
|
+
if (this.destroyed) return;
|
|
3012
|
+
this.dragFromContentDefault = value;
|
|
3013
|
+
}
|
|
3014
|
+
setDragFrom(mode) {
|
|
3015
|
+
if (this.destroyed || mode === this.dragFromMode) return;
|
|
3016
|
+
this.gesture?.forceClearDragState();
|
|
3017
|
+
this.detachSheetGesture?.();
|
|
3018
|
+
this.dragFromMode = mode;
|
|
3019
|
+
this.mountSheetGesture();
|
|
3020
|
+
}
|
|
3021
|
+
getDragFrom() {
|
|
3022
|
+
return this.dragFromMode;
|
|
3023
|
+
}
|
|
3127
3024
|
isTop() {
|
|
3128
3025
|
return this.isTopSheet;
|
|
3129
3026
|
}
|
|
@@ -3278,12 +3175,24 @@ var BottomSheetEngine = class {
|
|
|
3278
3175
|
auditVhUsage(points);
|
|
3279
3176
|
this.auditDuplicateSnapIds(points);
|
|
3280
3177
|
this.snaps.setRaw(points);
|
|
3281
|
-
if (allowed)
|
|
3178
|
+
if (allowed) {
|
|
3179
|
+
this.snaps.setAllowedIds(allowed);
|
|
3180
|
+
} else {
|
|
3181
|
+
const present = this.snaps.getResolvedSnaps().map((s) => s.id);
|
|
3182
|
+
const kept = this.snaps.getAllowedIds().filter((id) => present.includes(id));
|
|
3183
|
+
this.snaps.setAllowedIds(kept.length ? kept : present);
|
|
3184
|
+
}
|
|
3282
3185
|
this.scrollCache.clear();
|
|
3283
3186
|
this.scrim.invalidateOpacityCache();
|
|
3284
3187
|
const current = this.snaps.findById(this.activeId);
|
|
3285
3188
|
if (current) {
|
|
3286
3189
|
this.applySize(current.size);
|
|
3190
|
+
} else {
|
|
3191
|
+
const fallback = this.snaps.getResolvedSnaps().find((s) => this.snaps.getAllowedIds().includes(s.id)) ?? this.snaps.getResolvedSnaps()[0];
|
|
3192
|
+
if (fallback) {
|
|
3193
|
+
this.activeId = fallback.id;
|
|
3194
|
+
this.applySize(fallback.size);
|
|
3195
|
+
}
|
|
3287
3196
|
}
|
|
3288
3197
|
this.updateAriaSlider();
|
|
3289
3198
|
}
|
|
@@ -3293,7 +3202,7 @@ var BottomSheetEngine = class {
|
|
|
3293
3202
|
this.snaps.recompute();
|
|
3294
3203
|
this.maxHeight.clampTo();
|
|
3295
3204
|
this.scrim.invalidateOpacityCache();
|
|
3296
|
-
if (this.
|
|
3205
|
+
if (this.isDraggingAny()) return;
|
|
3297
3206
|
this.healActiveSnap();
|
|
3298
3207
|
}
|
|
3299
3208
|
healActiveSnap() {
|
|
@@ -3315,6 +3224,8 @@ var BottomSheetEngine = class {
|
|
|
3315
3224
|
this.bus.clear();
|
|
3316
3225
|
this.animation.cancel();
|
|
3317
3226
|
this.gesture?.forceClearDragState();
|
|
3227
|
+
this.contentGesture?.forceClearDragState();
|
|
3228
|
+
this.setRestClosed(false);
|
|
3318
3229
|
this.teardowns.drain();
|
|
3319
3230
|
this.scrim.destroy();
|
|
3320
3231
|
this.animation.destroy();
|
|
@@ -3427,11 +3338,12 @@ var BottomSheetEngine = class {
|
|
|
3427
3338
|
const scale = Math.max(1 - depth * 0.04, 0.86);
|
|
3428
3339
|
this.element.style.scale = scale === 1 ? "" : String(scale);
|
|
3429
3340
|
}
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
handle:
|
|
3341
|
+
buildGestureDeps(surface, gestureOptions) {
|
|
3342
|
+
return {
|
|
3343
|
+
handle: surface,
|
|
3433
3344
|
element: this.element,
|
|
3434
3345
|
mode: this.mode,
|
|
3346
|
+
gestureOptions,
|
|
3435
3347
|
getRoot: () => this.rootEl,
|
|
3436
3348
|
getDragContext: () => {
|
|
3437
3349
|
const buf = this.dragContextBuf;
|
|
@@ -3450,8 +3362,88 @@ var BottomSheetEngine = class {
|
|
|
3450
3362
|
settleAfterDrag: (delta, velocity, kind) => this.settleAfterDrag(delta, velocity, kind),
|
|
3451
3363
|
emit: (event, payload) => this.emit(event, payload),
|
|
3452
3364
|
listenerCount: (event) => this.bus.listenerCount(event)
|
|
3365
|
+
};
|
|
3366
|
+
}
|
|
3367
|
+
isContentDragAllowed() {
|
|
3368
|
+
if (this.disableDragFlag) return false;
|
|
3369
|
+
const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
|
|
3370
|
+
return point?.dragFromContent ?? this.dragFromContentDefault;
|
|
3371
|
+
}
|
|
3372
|
+
decideContentDrag(surface, e, delta) {
|
|
3373
|
+
if (this.destroyed) return false;
|
|
3374
|
+
if (e.pointerType === "mouse") return false;
|
|
3375
|
+
if (this.gesture?.isDragging) return false;
|
|
3376
|
+
if (!this.isContentDragAllowed()) return false;
|
|
3377
|
+
if (!isDragAllowedFrom(e.target, "sheet")) return false;
|
|
3378
|
+
const decision = decideContentGesture({
|
|
3379
|
+
delta,
|
|
3380
|
+
scrollTop: surface.scrollTop,
|
|
3381
|
+
atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
|
|
3382
|
+
});
|
|
3383
|
+
if (decision === "pending") return null;
|
|
3384
|
+
return decision === "drag";
|
|
3385
|
+
}
|
|
3386
|
+
attachDragSurface(surface, kind) {
|
|
3387
|
+
if (this.destroyed || kind !== "content") return;
|
|
3388
|
+
if (this.contentGesture) return;
|
|
3389
|
+
const controller = new GestureController(
|
|
3390
|
+
this.buildGestureDeps(surface, {
|
|
3391
|
+
manageTouchAction: false,
|
|
3392
|
+
deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
|
|
3393
|
+
})
|
|
3394
|
+
);
|
|
3395
|
+
this.contentGesture = controller;
|
|
3396
|
+
const detachGestures = controller.install();
|
|
3397
|
+
const detachGuard = installTouchScrollGuard(
|
|
3398
|
+
surface,
|
|
3399
|
+
() => controller.isDragging
|
|
3400
|
+
);
|
|
3401
|
+
return () => {
|
|
3402
|
+
detachGuard();
|
|
3403
|
+
detachGestures();
|
|
3404
|
+
if (this.contentGesture === controller) this.contentGesture = void 0;
|
|
3405
|
+
};
|
|
3406
|
+
}
|
|
3407
|
+
sheetDragSurface() {
|
|
3408
|
+
return this.dragFromMode === "handle" ? this.handle : this.element;
|
|
3409
|
+
}
|
|
3410
|
+
canStartSheetDrag(e) {
|
|
3411
|
+
if (this.contentGesture?.isDragging) return false;
|
|
3412
|
+
const target = e.target;
|
|
3413
|
+
const scoped = typeof target?.closest === "function";
|
|
3414
|
+
if (scoped && target.closest(NO_DRAG_SELECTOR)) return false;
|
|
3415
|
+
if (this.handle !== this.element && scoped && this.handle.contains(target)) {
|
|
3416
|
+
return true;
|
|
3417
|
+
}
|
|
3418
|
+
if (!isDragAllowedFrom(e.target, this.dragFromMode)) return false;
|
|
3419
|
+
if (this.dragFromMode === "handle") return true;
|
|
3420
|
+
if (this.scrollContainer && scoped && this.scrollContainer.contains(target) && !target.closest(DRAG_ZONE_SELECTOR)) {
|
|
3421
|
+
return false;
|
|
3422
|
+
}
|
|
3423
|
+
return true;
|
|
3424
|
+
}
|
|
3425
|
+
mountSheetGesture() {
|
|
3426
|
+
const surface = this.sheetDragSurface();
|
|
3427
|
+
const controller = new GestureController(
|
|
3428
|
+
this.buildGestureDeps(surface, {
|
|
3429
|
+
shouldStart: (e) => this.canStartSheetDrag(e),
|
|
3430
|
+
manageTouchAction: this.dragFromMode === "handle"
|
|
3431
|
+
})
|
|
3432
|
+
);
|
|
3433
|
+
this.gesture = controller;
|
|
3434
|
+
const detachGestures = controller.install();
|
|
3435
|
+
const detachGuard = this.dragFromMode === "handle" ? null : installTouchScrollGuard(surface, () => controller.isDragging);
|
|
3436
|
+
this.detachSheetGesture = () => {
|
|
3437
|
+
detachGuard?.();
|
|
3438
|
+
detachGestures();
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
attach() {
|
|
3442
|
+
this.mountSheetGesture();
|
|
3443
|
+
this.teardowns.add(() => {
|
|
3444
|
+
this.detachSheetGesture?.();
|
|
3445
|
+
this.detachSheetGesture = null;
|
|
3453
3446
|
});
|
|
3454
|
-
this.teardowns.add(this.gesture.install());
|
|
3455
3447
|
try {
|
|
3456
3448
|
this.attachFeatures();
|
|
3457
3449
|
} catch (err) {
|
|
@@ -3482,24 +3474,13 @@ var BottomSheetEngine = class {
|
|
|
3482
3474
|
}
|
|
3483
3475
|
}
|
|
3484
3476
|
attachFeatures() {
|
|
3485
|
-
|
|
3486
|
-
this.teardowns.add(installContentSwipe({
|
|
3487
|
-
container: this.scrollContainer,
|
|
3488
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3489
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3490
|
-
getAllowedIds: () => this.allowedIdsBySize(),
|
|
3491
|
-
getActiveId: () => this.activeId,
|
|
3492
|
-
snapTo: (id) => {
|
|
3493
|
-
void this.snapTo(id);
|
|
3494
|
-
}
|
|
3495
|
-
}));
|
|
3496
|
-
}
|
|
3477
|
+
this.runFeatureStage("attach");
|
|
3497
3478
|
if (typeof window !== "undefined") {
|
|
3498
3479
|
this.teardowns.add(installResizeObserver({
|
|
3499
3480
|
element: this.element,
|
|
3500
3481
|
getMode: () => this.mode,
|
|
3501
3482
|
isDestroyed: () => this.destroyed,
|
|
3502
|
-
isDragging: () => this.
|
|
3483
|
+
isDragging: () => this.isDraggingAny(),
|
|
3503
3484
|
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3504
3485
|
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3505
3486
|
getSize: () => this.size,
|
|
@@ -3533,31 +3514,6 @@ var BottomSheetEngine = class {
|
|
|
3533
3514
|
() => document.removeEventListener("keydown", onKey)
|
|
3534
3515
|
);
|
|
3535
3516
|
}
|
|
3536
|
-
this.teardowns.add(installVisualViewport({
|
|
3537
|
-
element: this.element,
|
|
3538
|
-
isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
|
|
3539
|
-
isDestroyed: () => this.destroyed,
|
|
3540
|
-
isDragging: () => this.gesture?.isDragging ?? false,
|
|
3541
|
-
recomputeSnaps: () => this.recomputeSnaps(),
|
|
3542
|
-
resolveActiveSnap: () => this.snaps.findById(this.activeId),
|
|
3543
|
-
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
3544
|
-
getSize: () => this.size,
|
|
3545
|
-
setMaxAxisSize: (size) => {
|
|
3546
|
-
this.snaps.setMaxAxisSize(size);
|
|
3547
|
-
},
|
|
3548
|
-
setSize: (size) => {
|
|
3549
|
-
this.size = size;
|
|
3550
|
-
},
|
|
3551
|
-
applySize: (size) => this.applySize(size),
|
|
3552
|
-
cancelInFlight: () => {
|
|
3553
|
-
this.animation.cancel();
|
|
3554
|
-
},
|
|
3555
|
-
newCycle: () => {
|
|
3556
|
-
this.newCycle();
|
|
3557
|
-
},
|
|
3558
|
-
isAnimating: () => this.animation.isAnimating,
|
|
3559
|
-
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3560
|
-
}));
|
|
3561
3517
|
}
|
|
3562
3518
|
this.teardowns.add(installSliderKeyboard({
|
|
3563
3519
|
handle: this.handle,
|
|
@@ -3598,123 +3554,591 @@ var BottomSheetEngine = class {
|
|
|
3598
3554
|
}
|
|
3599
3555
|
return;
|
|
3600
3556
|
}
|
|
3601
|
-
const previousSize = this.size;
|
|
3602
|
-
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
3603
|
-
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
3604
|
-
this.activeId = target.id;
|
|
3605
|
-
if (previousSnapSize === 0 && target.size > 0) {
|
|
3606
|
-
this.opening = true;
|
|
3607
|
-
sheetStack.promote(this.id);
|
|
3557
|
+
const previousSize = this.size;
|
|
3558
|
+
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
3559
|
+
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
3560
|
+
this.activeId = target.id;
|
|
3561
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
3562
|
+
this.opening = true;
|
|
3563
|
+
sheetStack.promote(this.id);
|
|
3564
|
+
}
|
|
3565
|
+
const settleCap = this.snaps.getMaxAxisSize();
|
|
3566
|
+
const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
|
|
3567
|
+
this.allowOvershoot = true;
|
|
3568
|
+
void this.animation.animateTo(settleSize, velocity).then(() => {
|
|
3569
|
+
if (signal.aborted) return;
|
|
3570
|
+
this.allowOvershoot = false;
|
|
3571
|
+
this.opening = false;
|
|
3572
|
+
this.completeSnap(
|
|
3573
|
+
target.id,
|
|
3574
|
+
target.size,
|
|
3575
|
+
previousSize,
|
|
3576
|
+
previousSnapSize === 0,
|
|
3577
|
+
true
|
|
3578
|
+
);
|
|
3579
|
+
});
|
|
3580
|
+
}
|
|
3581
|
+
isDraggingAny() {
|
|
3582
|
+
return (this.gesture?.isDragging ?? false) || (this.contentGesture?.isDragging ?? false);
|
|
3583
|
+
}
|
|
3584
|
+
clearWillChangeIfIdle() {
|
|
3585
|
+
if (this.animation.isAnimating || this.isDraggingAny()) return;
|
|
3586
|
+
this.element.style.willChange = "";
|
|
3587
|
+
}
|
|
3588
|
+
haptic() {
|
|
3589
|
+
if (typeof navigator !== "undefined" && "vibrate" in navigator) {
|
|
3590
|
+
try {
|
|
3591
|
+
navigator.vibrate(HAPTIC_DURATION_MS);
|
|
3592
|
+
} catch {
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
applySize(size, skipTransform = false) {
|
|
3597
|
+
const cap = this.snaps.getMaxAxisSize();
|
|
3598
|
+
const clamped = cap > 0 && size > cap && !this.isDraggingAny() && !this.allowOvershoot ? cap : size;
|
|
3599
|
+
this.size = clamped;
|
|
3600
|
+
if (clamped > 0) this.setRestClosed(false);
|
|
3601
|
+
const offset = cap - clamped;
|
|
3602
|
+
const style = this.element.style;
|
|
3603
|
+
if (!skipTransform) style.transform = this.transformTemplate(offset);
|
|
3604
|
+
if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
|
|
3605
|
+
style.setProperty("--bs-size", `${clamped}px`);
|
|
3606
|
+
if (this.scrimParent) {
|
|
3607
|
+
this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
|
|
3608
|
+
}
|
|
3609
|
+
if (this.anchorHost && this.anchorHost !== this.scrimParent) {
|
|
3610
|
+
this.anchorHost.style.setProperty("--bs-size", `${clamped}px`);
|
|
3611
|
+
}
|
|
3612
|
+
if (this.rootEl && this.rootEl !== this.scrimParent && this.rootEl !== this.anchorHost) {
|
|
3613
|
+
this.rootEl.style.setProperty("--bs-size", `${clamped}px`);
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
const progress = this.computeProgress(clamped);
|
|
3617
|
+
const progressChanged = this.progressWriteSentinel.shouldWrite(
|
|
3618
|
+
progress,
|
|
3619
|
+
OPACITY_WRITE_EPSILON
|
|
3620
|
+
);
|
|
3621
|
+
if (progressChanged) {
|
|
3622
|
+
style.setProperty("--bs-progress", String(progress));
|
|
3623
|
+
if (this.anchorHost) {
|
|
3624
|
+
this.anchorHost.style.setProperty("--bs-progress", String(progress));
|
|
3625
|
+
}
|
|
3626
|
+
if (this.rootEl && this.rootEl !== this.anchorHost) {
|
|
3627
|
+
this.rootEl.style.setProperty("--bs-progress", String(progress));
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
this.scrim.applyOpacity(progress, progressChanged);
|
|
3631
|
+
if (progressChanged && this.bus.listenerCount("progress") > 0) {
|
|
3632
|
+
this.progressPayload.value = progress;
|
|
3633
|
+
this.progressPayload.size = clamped;
|
|
3634
|
+
this.emit("progress", this.progressPayload);
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
computeProgress(size) {
|
|
3638
|
+
const { min, max } = this.getAllowedRange();
|
|
3639
|
+
const reachableMax = Math.min(max, this.snaps.getMaxAxisSize());
|
|
3640
|
+
if (reachableMax <= min) return 0;
|
|
3641
|
+
return Math.min(Math.max((size - min) / (reachableMax - min), 0), 1);
|
|
3642
|
+
}
|
|
3643
|
+
handleOpen() {
|
|
3644
|
+
sheetStack.promote(this.id);
|
|
3645
|
+
try {
|
|
3646
|
+
this.lifecycle.install();
|
|
3647
|
+
} catch (err) {
|
|
3648
|
+
if (!this.destroyed) this.newCycle();
|
|
3649
|
+
this.handleClose();
|
|
3650
|
+
this.applySize(0);
|
|
3651
|
+
this.activeId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.activeId;
|
|
3652
|
+
this.size = 0;
|
|
3653
|
+
queueMicrotask(() => {
|
|
3654
|
+
throw err;
|
|
3655
|
+
});
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
resyncAfterResize() {
|
|
3659
|
+
if (this.destroyed) return;
|
|
3660
|
+
const target = this.snaps.findById(this.activeId);
|
|
3661
|
+
if (!target) return;
|
|
3662
|
+
this.updateAriaSlider();
|
|
3663
|
+
this.emit("snap", {
|
|
3664
|
+
id: target.id,
|
|
3665
|
+
size: this.size,
|
|
3666
|
+
progress: this.computeProgress(this.size)
|
|
3667
|
+
});
|
|
3668
|
+
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3669
|
+
this.emitOpenSequence(target.id);
|
|
3670
|
+
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3671
|
+
this.emitCloseSequence();
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3674
|
+
handleClose() {
|
|
3675
|
+
this.opening = false;
|
|
3676
|
+
this.lifecycle.release();
|
|
3677
|
+
sheetStack.update();
|
|
3678
|
+
}
|
|
3679
|
+
};
|
|
3680
|
+
|
|
3681
|
+
// src/core/features/history-coordinator.ts
|
|
3682
|
+
var entries = [];
|
|
3683
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3684
|
+
var suppress = 0;
|
|
3685
|
+
var internalDepth = 0;
|
|
3686
|
+
var pendingRebrands = [];
|
|
3687
|
+
var listenerInstalled = false;
|
|
3688
|
+
var patchInstalled = false;
|
|
3689
|
+
var origPushState = null;
|
|
3690
|
+
var origReplaceState = null;
|
|
3691
|
+
var patchedPushState = null;
|
|
3692
|
+
var patchedReplaceState = null;
|
|
3693
|
+
var hasWindow = () => typeof window !== "undefined";
|
|
3694
|
+
var hasHistory = () => typeof history !== "undefined";
|
|
3695
|
+
var brandMarker = (surface) => ({
|
|
3696
|
+
...surface.markerState(),
|
|
3697
|
+
__bs: true
|
|
3698
|
+
});
|
|
3699
|
+
var runInternal = (fn) => {
|
|
3700
|
+
internalDepth += 1;
|
|
3701
|
+
try {
|
|
3702
|
+
fn();
|
|
3703
|
+
} finally {
|
|
3704
|
+
internalDepth -= 1;
|
|
3705
|
+
}
|
|
3706
|
+
};
|
|
3707
|
+
var notifyRouteChange = () => {
|
|
3708
|
+
const snapshot = Array.from(subscribers);
|
|
3709
|
+
for (const fn of snapshot) fn();
|
|
3710
|
+
};
|
|
3711
|
+
var ensureListener = () => {
|
|
3712
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
3713
|
+
window.addEventListener("popstate", onPopState);
|
|
3714
|
+
listenerInstalled = true;
|
|
3715
|
+
};
|
|
3716
|
+
var maybeTeardownListener = () => {
|
|
3717
|
+
if (!listenerInstalled) return;
|
|
3718
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
3719
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
3720
|
+
listenerInstalled = false;
|
|
3721
|
+
};
|
|
3722
|
+
var installPatch = () => {
|
|
3723
|
+
if (patchInstalled || !hasHistory()) return;
|
|
3724
|
+
origPushState = history.pushState;
|
|
3725
|
+
origReplaceState = history.replaceState;
|
|
3726
|
+
patchedPushState = function(...args) {
|
|
3727
|
+
origPushState.apply(this, args);
|
|
3728
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3729
|
+
};
|
|
3730
|
+
patchedReplaceState = function(...args) {
|
|
3731
|
+
origReplaceState.apply(this, args);
|
|
3732
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
3733
|
+
};
|
|
3734
|
+
history.pushState = patchedPushState;
|
|
3735
|
+
history.replaceState = patchedReplaceState;
|
|
3736
|
+
patchInstalled = true;
|
|
3737
|
+
};
|
|
3738
|
+
var removePatch = () => {
|
|
3739
|
+
if (!patchInstalled) return;
|
|
3740
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
3741
|
+
history.pushState = origPushState;
|
|
3742
|
+
}
|
|
3743
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
3744
|
+
history.replaceState = origReplaceState;
|
|
3745
|
+
}
|
|
3746
|
+
origPushState = null;
|
|
3747
|
+
origReplaceState = null;
|
|
3748
|
+
patchedPushState = null;
|
|
3749
|
+
patchedReplaceState = null;
|
|
3750
|
+
patchInstalled = false;
|
|
3751
|
+
};
|
|
3752
|
+
function onPopState() {
|
|
3753
|
+
if (suppress > 0) {
|
|
3754
|
+
suppress -= 1;
|
|
3755
|
+
const rebrand = pendingRebrands.shift();
|
|
3756
|
+
if (rebrand) rebrand();
|
|
3757
|
+
maybeTeardownListener();
|
|
3758
|
+
return;
|
|
3759
|
+
}
|
|
3760
|
+
if (entries.length === 0) {
|
|
3761
|
+
notifyRouteChange();
|
|
3762
|
+
maybeTeardownListener();
|
|
3763
|
+
return;
|
|
3764
|
+
}
|
|
3765
|
+
let target = null;
|
|
3766
|
+
let targetIdx = -1;
|
|
3767
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3768
|
+
const entry = entries[i];
|
|
3769
|
+
if (!entry.surface.isOpen()) continue;
|
|
3770
|
+
if (!target) {
|
|
3771
|
+
target = entry;
|
|
3772
|
+
targetIdx = i;
|
|
3773
|
+
}
|
|
3774
|
+
if (entry.surface.isTop()) {
|
|
3775
|
+
target = entry;
|
|
3776
|
+
targetIdx = i;
|
|
3777
|
+
break;
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
if (!target) {
|
|
3781
|
+
const removed = entries.pop();
|
|
3782
|
+
if (removed) removed.live = false;
|
|
3783
|
+
maybeTeardownListener();
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3786
|
+
target.live = false;
|
|
3787
|
+
entries.splice(targetIdx, 1);
|
|
3788
|
+
const settled = target;
|
|
3789
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
3790
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
3791
|
+
});
|
|
3792
|
+
maybeTeardownListener();
|
|
3793
|
+
}
|
|
3794
|
+
function restore(entry) {
|
|
3795
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3796
|
+
entry.live = true;
|
|
3797
|
+
runInternal(() => {
|
|
3798
|
+
try {
|
|
3799
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
3800
|
+
} catch {
|
|
3801
|
+
entry.live = false;
|
|
3802
|
+
}
|
|
3803
|
+
});
|
|
3804
|
+
if (entry.live) {
|
|
3805
|
+
entries.push(entry);
|
|
3806
|
+
ensureListener();
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
function pushBackMarker(surface) {
|
|
3810
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
3811
|
+
if (!hasWindow() || !hasHistory()) {
|
|
3812
|
+
return entry;
|
|
3813
|
+
}
|
|
3814
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
3815
|
+
runInternal(() => {
|
|
3816
|
+
try {
|
|
3817
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
3818
|
+
entry.live = true;
|
|
3819
|
+
} catch {
|
|
3820
|
+
entry.live = false;
|
|
3821
|
+
}
|
|
3822
|
+
});
|
|
3823
|
+
if (entry.live) {
|
|
3824
|
+
entries.push(entry);
|
|
3825
|
+
ensureListener();
|
|
3826
|
+
}
|
|
3827
|
+
return entry;
|
|
3828
|
+
}
|
|
3829
|
+
function popBackMarker(handle) {
|
|
3830
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
3831
|
+
const entry = handle;
|
|
3832
|
+
const idx = entries.indexOf(entry);
|
|
3833
|
+
if (idx === -1 || !entry.live) return;
|
|
3834
|
+
const last = entries.length - 1;
|
|
3835
|
+
entry.live = false;
|
|
3836
|
+
entries.splice(idx, 1);
|
|
3837
|
+
let rebrand = null;
|
|
3838
|
+
if (idx !== last) {
|
|
3839
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
3840
|
+
const rebrandUrl = entry.priorUrl;
|
|
3841
|
+
rebrand = () => {
|
|
3842
|
+
runInternal(() => {
|
|
3843
|
+
history.replaceState(
|
|
3844
|
+
brandMarker(rebrandSurface),
|
|
3845
|
+
"",
|
|
3846
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
3847
|
+
);
|
|
3848
|
+
});
|
|
3849
|
+
};
|
|
3850
|
+
}
|
|
3851
|
+
pendingRebrands.push(rebrand);
|
|
3852
|
+
suppress += 1;
|
|
3853
|
+
runInternal(() => {
|
|
3854
|
+
try {
|
|
3855
|
+
history.back();
|
|
3856
|
+
} catch {
|
|
3857
|
+
suppress = Math.max(0, suppress - 1);
|
|
3858
|
+
pendingRebrands.pop();
|
|
3859
|
+
}
|
|
3860
|
+
});
|
|
3861
|
+
maybeTeardownListener();
|
|
3862
|
+
}
|
|
3863
|
+
function subscribeRouteChange(fn) {
|
|
3864
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
3865
|
+
};
|
|
3866
|
+
subscribers.add(fn);
|
|
3867
|
+
if (subscribers.size === 1) installPatch();
|
|
3868
|
+
ensureListener();
|
|
3869
|
+
return () => {
|
|
3870
|
+
if (!subscribers.has(fn)) return;
|
|
3871
|
+
subscribers.delete(fn);
|
|
3872
|
+
if (subscribers.size === 0) removePatch();
|
|
3873
|
+
maybeTeardownListener();
|
|
3874
|
+
};
|
|
3875
|
+
}
|
|
3876
|
+
|
|
3877
|
+
// src/core/features/route.ts
|
|
3878
|
+
function installRoute(deps) {
|
|
3879
|
+
if (typeof window === "undefined") {
|
|
3880
|
+
return () => {
|
|
3881
|
+
};
|
|
3882
|
+
}
|
|
3883
|
+
if (!deps.routedTo && !deps.closeOnBack) {
|
|
3884
|
+
return () => {
|
|
3885
|
+
};
|
|
3886
|
+
}
|
|
3887
|
+
let handle = null;
|
|
3888
|
+
const onOpen = () => {
|
|
3889
|
+
if (handle) return;
|
|
3890
|
+
handle = pushBackMarker({
|
|
3891
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
3892
|
+
isTop: deps.isTopSheet,
|
|
3893
|
+
close: deps.close,
|
|
3894
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
3895
|
+
url: deps.routedTo
|
|
3896
|
+
});
|
|
3897
|
+
};
|
|
3898
|
+
const onClose = () => {
|
|
3899
|
+
if (!handle) return;
|
|
3900
|
+
popBackMarker(handle);
|
|
3901
|
+
handle = null;
|
|
3902
|
+
};
|
|
3903
|
+
const unsubscribeOpen = deps.on("open", onOpen);
|
|
3904
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
3905
|
+
if (deps.getSize() > 0) onOpen();
|
|
3906
|
+
return () => {
|
|
3907
|
+
unsubscribeOpen();
|
|
3908
|
+
unsubscribeClose();
|
|
3909
|
+
if (handle) {
|
|
3910
|
+
popBackMarker(handle);
|
|
3911
|
+
handle = null;
|
|
3912
|
+
}
|
|
3913
|
+
};
|
|
3914
|
+
}
|
|
3915
|
+
function installRouteChange(deps) {
|
|
3916
|
+
return subscribeRouteChange(() => {
|
|
3917
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
3918
|
+
void deps.close();
|
|
3919
|
+
});
|
|
3920
|
+
}
|
|
3921
|
+
|
|
3922
|
+
// src/core/features/persist.ts
|
|
3923
|
+
function installPersist(engine, key) {
|
|
3924
|
+
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
3925
|
+
if (typeof window === "undefined") return;
|
|
3926
|
+
if (typeof localStorage === "undefined") return;
|
|
3927
|
+
try {
|
|
3928
|
+
localStorage.setItem(key, id);
|
|
3929
|
+
} catch {
|
|
3608
3930
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
previousSize,
|
|
3620
|
-
previousSnapSize === 0,
|
|
3621
|
-
true
|
|
3622
|
-
);
|
|
3623
|
-
});
|
|
3624
|
-
}
|
|
3625
|
-
clearWillChangeIfIdle() {
|
|
3626
|
-
if (this.animation.isAnimating || this.gesture?.isDragging) return;
|
|
3627
|
-
this.element.style.willChange = "";
|
|
3931
|
+
});
|
|
3932
|
+
return unsubscribe;
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
// src/core/features/auto-collapse.ts
|
|
3936
|
+
function installAutoCollapse(deps) {
|
|
3937
|
+
const { ms } = deps;
|
|
3938
|
+
if (ms === void 0 || ms <= 0) {
|
|
3939
|
+
return () => {
|
|
3940
|
+
};
|
|
3628
3941
|
}
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3942
|
+
let timer = null;
|
|
3943
|
+
const clearTimer = () => {
|
|
3944
|
+
if (timer !== null) {
|
|
3945
|
+
clearTimeout(timer);
|
|
3946
|
+
timer = null;
|
|
3947
|
+
}
|
|
3948
|
+
};
|
|
3949
|
+
const fire = () => {
|
|
3950
|
+
if (deps.isDestroyed()) return;
|
|
3951
|
+
if (deps.isDragging()) return;
|
|
3952
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
3953
|
+
if (!active || active.size === 0) return;
|
|
3954
|
+
let target = null;
|
|
3955
|
+
for (const id of deps.getAllowedIds()) {
|
|
3956
|
+
const snap = deps.resolveSnap(id);
|
|
3957
|
+
if (!snap || snap.size <= 0) continue;
|
|
3958
|
+
if (!target || snap.size < target.size) target = snap;
|
|
3635
3959
|
}
|
|
3960
|
+
if (!target) return;
|
|
3961
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
3962
|
+
deps.snapTo(target.id);
|
|
3963
|
+
};
|
|
3964
|
+
const reset = () => {
|
|
3965
|
+
clearTimer();
|
|
3966
|
+
if (deps.isDestroyed()) return;
|
|
3967
|
+
timer = setTimeout(() => {
|
|
3968
|
+
timer = null;
|
|
3969
|
+
fire();
|
|
3970
|
+
}, ms);
|
|
3971
|
+
};
|
|
3972
|
+
const unsubscribe = deps.on("snap", () => reset());
|
|
3973
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
3974
|
+
return () => {
|
|
3975
|
+
clearTimer();
|
|
3976
|
+
unsubscribe();
|
|
3977
|
+
};
|
|
3978
|
+
}
|
|
3979
|
+
|
|
3980
|
+
// src/core/features/content-drag.ts
|
|
3981
|
+
function installContentDrag(deps) {
|
|
3982
|
+
const detach = deps.attachDragSurface(deps.container, "content");
|
|
3983
|
+
return () => detach?.();
|
|
3984
|
+
}
|
|
3985
|
+
|
|
3986
|
+
// src/core/features/visual-viewport.ts
|
|
3987
|
+
var SAFETY_PAD = 8;
|
|
3988
|
+
function installVisualViewport(deps) {
|
|
3989
|
+
if (typeof window === "undefined" || !window.visualViewport) {
|
|
3990
|
+
return () => {
|
|
3991
|
+
};
|
|
3636
3992
|
}
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3993
|
+
const vv = window.visualViewport;
|
|
3994
|
+
let rafId = null;
|
|
3995
|
+
const onResize = () => {
|
|
3996
|
+
if (rafId !== null) return;
|
|
3997
|
+
rafId = requestAnimationFrame(() => {
|
|
3998
|
+
rafId = null;
|
|
3999
|
+
if (deps.isDestroyed()) return;
|
|
4000
|
+
deps.recomputeSnaps();
|
|
4001
|
+
const isVertical = deps.isVerticalAxis();
|
|
4002
|
+
const visible = isVertical ? vv.height : vv.width;
|
|
4003
|
+
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
4004
|
+
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
4005
|
+
if (clamp < deps.getMaxAxisSize()) {
|
|
4006
|
+
deps.setMaxAxisSize(clamp);
|
|
3648
4007
|
}
|
|
3649
|
-
|
|
3650
|
-
|
|
4008
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
4009
|
+
deps.cancelInFlight();
|
|
4010
|
+
deps.newCycle();
|
|
4011
|
+
const max = deps.getMaxAxisSize();
|
|
4012
|
+
deps.setSize(Math.min(deps.getSize(), max));
|
|
4013
|
+
const current = deps.resolveActiveSnap();
|
|
4014
|
+
if (current && !deps.isDragging()) {
|
|
4015
|
+
deps.applySize(Math.min(current.size, max));
|
|
4016
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
4017
|
+
} else {
|
|
4018
|
+
deps.applySize(deps.getSize());
|
|
3651
4019
|
}
|
|
3652
|
-
|
|
3653
|
-
|
|
4020
|
+
});
|
|
4021
|
+
};
|
|
4022
|
+
vv.addEventListener("resize", onResize);
|
|
4023
|
+
return () => {
|
|
4024
|
+
vv.removeEventListener("resize", onResize);
|
|
4025
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
4026
|
+
};
|
|
4027
|
+
}
|
|
4028
|
+
|
|
4029
|
+
// src/core/features/engine-features.ts
|
|
4030
|
+
function routeFeature() {
|
|
4031
|
+
return {
|
|
4032
|
+
name: "route",
|
|
4033
|
+
install: (ctx) => {
|
|
4034
|
+
const teardowns = new TeardownStack();
|
|
4035
|
+
if (ctx.options.closeOnRouteChange) {
|
|
4036
|
+
teardowns.add(
|
|
4037
|
+
installRouteChange({
|
|
4038
|
+
isDestroyed: ctx.isDestroyed,
|
|
4039
|
+
getSize: ctx.getSize,
|
|
4040
|
+
close: () => ctx.close()
|
|
4041
|
+
})
|
|
4042
|
+
);
|
|
3654
4043
|
}
|
|
4044
|
+
teardowns.add(
|
|
4045
|
+
installRoute({
|
|
4046
|
+
routedTo: ctx.options.routedTo,
|
|
4047
|
+
closeOnBack: ctx.options.closeOnBack,
|
|
4048
|
+
isTopSheet: ctx.isTopSheet,
|
|
4049
|
+
getSize: ctx.getSize,
|
|
4050
|
+
isDestroyed: ctx.isDestroyed,
|
|
4051
|
+
close: () => ctx.close("back"),
|
|
4052
|
+
on: ctx.on,
|
|
4053
|
+
sheetId: ctx.sheetId
|
|
4054
|
+
})
|
|
4055
|
+
);
|
|
4056
|
+
return () => teardowns.drain();
|
|
3655
4057
|
}
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
if (
|
|
3664
|
-
|
|
3665
|
-
}
|
|
3666
|
-
if (this.rootEl && this.rootEl !== this.anchorHost) {
|
|
3667
|
-
this.rootEl.style.setProperty("--bs-progress", String(progress));
|
|
3668
|
-
}
|
|
4058
|
+
};
|
|
4059
|
+
}
|
|
4060
|
+
function persistFeature() {
|
|
4061
|
+
return {
|
|
4062
|
+
name: "persist",
|
|
4063
|
+
install: (ctx) => {
|
|
4064
|
+
const key = ctx.options.persistKey;
|
|
4065
|
+
if (!key) return;
|
|
4066
|
+
return installPersist({ on: ctx.on }, key);
|
|
3669
4067
|
}
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
4068
|
+
};
|
|
4069
|
+
}
|
|
4070
|
+
function autoCollapseFeature() {
|
|
4071
|
+
return {
|
|
4072
|
+
name: "auto-collapse",
|
|
4073
|
+
install: (ctx) => installAutoCollapse({
|
|
4074
|
+
ms: ctx.options.autoCollapseAfter,
|
|
4075
|
+
isDestroyed: ctx.isDestroyed,
|
|
4076
|
+
isDragging: ctx.isDragging,
|
|
4077
|
+
getAllowedIds: ctx.getAllowedIds,
|
|
4078
|
+
getActiveId: ctx.getActiveId,
|
|
4079
|
+
resolveSnap: ctx.resolveSnap,
|
|
4080
|
+
snapTo: ctx.snapTo,
|
|
4081
|
+
on: ctx.on
|
|
4082
|
+
})
|
|
4083
|
+
};
|
|
4084
|
+
}
|
|
4085
|
+
function contentSwipeFeature() {
|
|
4086
|
+
return {
|
|
4087
|
+
name: "content-swipe",
|
|
4088
|
+
stage: "attach",
|
|
4089
|
+
install: (ctx) => {
|
|
4090
|
+
if (!ctx.scrollContainer) return;
|
|
4091
|
+
return installContentDrag({
|
|
4092
|
+
container: ctx.scrollContainer,
|
|
4093
|
+
attachDragSurface: ctx.attachDragSurface
|
|
4094
|
+
});
|
|
3675
4095
|
}
|
|
3676
|
-
}
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
4096
|
+
};
|
|
4097
|
+
}
|
|
4098
|
+
function visualViewportFeature() {
|
|
4099
|
+
return {
|
|
4100
|
+
name: "visual-viewport",
|
|
4101
|
+
install: (ctx) => {
|
|
4102
|
+
if (typeof window === "undefined") return;
|
|
4103
|
+
return installVisualViewport({
|
|
4104
|
+
element: ctx.element,
|
|
4105
|
+
isVerticalAxis: ctx.isVerticalAxis,
|
|
4106
|
+
isDestroyed: ctx.isDestroyed,
|
|
4107
|
+
isDragging: ctx.isDragging,
|
|
4108
|
+
recomputeSnaps: ctx.recomputeSnaps,
|
|
4109
|
+
resolveActiveSnap: ctx.resolveActiveSnap,
|
|
4110
|
+
getMaxAxisSize: ctx.getMaxAxisSize,
|
|
4111
|
+
getSize: ctx.getSize,
|
|
4112
|
+
setMaxAxisSize: ctx.setMaxAxisSize,
|
|
4113
|
+
setSize: ctx.setSize,
|
|
4114
|
+
applySize: ctx.applySize,
|
|
4115
|
+
cancelInFlight: ctx.cancelInFlight,
|
|
4116
|
+
newCycle: ctx.newCycle,
|
|
4117
|
+
isAnimating: ctx.isAnimating,
|
|
4118
|
+
resyncAfterCancel: ctx.resyncAfterResize
|
|
3695
4119
|
});
|
|
3696
4120
|
}
|
|
3697
|
-
}
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
4121
|
+
};
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
// src/core/default-features.ts
|
|
4125
|
+
function defaultEngineFeatures() {
|
|
4126
|
+
return [
|
|
4127
|
+
contentSwipeFeature(),
|
|
4128
|
+
visualViewportFeature(),
|
|
4129
|
+
persistFeature(),
|
|
4130
|
+
autoCollapseFeature(),
|
|
4131
|
+
routeFeature()
|
|
4132
|
+
];
|
|
4133
|
+
}
|
|
4134
|
+
|
|
4135
|
+
// src/core/BottomSheetEngine.ts
|
|
4136
|
+
var BottomSheetEngine = class extends BottomSheetCore {
|
|
4137
|
+
constructor(opts) {
|
|
4138
|
+
super({
|
|
4139
|
+
...opts,
|
|
4140
|
+
features: [...defaultEngineFeatures(), ...opts.features ?? []]
|
|
3707
4141
|
});
|
|
3708
|
-
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3709
|
-
this.emitOpenSequence(target.id);
|
|
3710
|
-
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3711
|
-
this.emitCloseSequence();
|
|
3712
|
-
}
|
|
3713
|
-
}
|
|
3714
|
-
handleClose() {
|
|
3715
|
-
this.opening = false;
|
|
3716
|
-
this.lifecycle.release();
|
|
3717
|
-
sheetStack.update();
|
|
3718
4142
|
}
|
|
3719
4143
|
};
|
|
3720
4144
|
|
|
@@ -3792,6 +4216,8 @@ var BottomSheet = (props) => {
|
|
|
3792
4216
|
persistent: props.persistent,
|
|
3793
4217
|
disableClose: props.disableClose,
|
|
3794
4218
|
disableDrag: props.disableDrag,
|
|
4219
|
+
dragFrom: props.dragFrom,
|
|
4220
|
+
dragFromContent: props.dragFromContent,
|
|
3795
4221
|
closeOnRouteChange: props.closeOnRouteChange,
|
|
3796
4222
|
stackEffect: props.stackEffect,
|
|
3797
4223
|
returnFocusTo: props.returnFocusTo
|
|
@@ -3904,6 +4330,26 @@ var BottomSheet = (props) => {
|
|
|
3904
4330
|
{ defer: true }
|
|
3905
4331
|
)
|
|
3906
4332
|
);
|
|
4333
|
+
createEffect(
|
|
4334
|
+
on(
|
|
4335
|
+
() => props.dragFromContent,
|
|
4336
|
+
(value, prev) => {
|
|
4337
|
+
if (!engine || prev === void 0 || value === void 0) return;
|
|
4338
|
+
engine.setDragFromContent(value);
|
|
4339
|
+
},
|
|
4340
|
+
{ defer: true }
|
|
4341
|
+
)
|
|
4342
|
+
);
|
|
4343
|
+
createEffect(
|
|
4344
|
+
on(
|
|
4345
|
+
() => props.dragFrom,
|
|
4346
|
+
(value, prev) => {
|
|
4347
|
+
if (!engine || prev === void 0 || value === void 0) return;
|
|
4348
|
+
engine.setDragFrom(value);
|
|
4349
|
+
},
|
|
4350
|
+
{ defer: true }
|
|
4351
|
+
)
|
|
4352
|
+
);
|
|
3907
4353
|
const showBackdrop = createMemo(() => props.backdrop !== false);
|
|
3908
4354
|
const mode = createMemo(() => props.mode ?? "bottom");
|
|
3909
4355
|
const ariaLabel = createMemo(() => props.ariaLabel ?? "Bottom sheet");
|