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