@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/qwik.cjs
CHANGED
|
@@ -7,7 +7,7 @@ var __defProp = Object.defineProperty;
|
|
|
7
7
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
8
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
9
9
|
|
|
10
|
-
// src/core/lifecycle/
|
|
10
|
+
// src/core/lifecycle/sheet-stack.ts
|
|
11
11
|
var BASE_Z = 100;
|
|
12
12
|
var STEP = 10;
|
|
13
13
|
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);
|
|
@@ -351,74 +351,6 @@ var SnapResolver = class {
|
|
|
351
351
|
}
|
|
352
352
|
};
|
|
353
353
|
|
|
354
|
-
// src/core/features/persist.ts
|
|
355
|
-
function readPersistedId(key) {
|
|
356
|
-
if (!key) return null;
|
|
357
|
-
if (typeof window === "undefined") return null;
|
|
358
|
-
if (typeof localStorage === "undefined") return null;
|
|
359
|
-
try {
|
|
360
|
-
return localStorage.getItem(key);
|
|
361
|
-
} catch {
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
function installPersist(engine, key) {
|
|
366
|
-
const unsubscribe = engine.on("snap", ({ id }) => {
|
|
367
|
-
if (typeof window === "undefined") return;
|
|
368
|
-
if (typeof localStorage === "undefined") return;
|
|
369
|
-
try {
|
|
370
|
-
localStorage.setItem(key, id);
|
|
371
|
-
} catch {
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
return unsubscribe;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// src/core/features/auto-collapse.ts
|
|
378
|
-
function installAutoCollapse(deps) {
|
|
379
|
-
const { ms } = deps;
|
|
380
|
-
if (ms === void 0 || ms <= 0) {
|
|
381
|
-
return () => {
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
let timer = null;
|
|
385
|
-
const clearTimer = () => {
|
|
386
|
-
if (timer !== null) {
|
|
387
|
-
clearTimeout(timer);
|
|
388
|
-
timer = null;
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
const fire = () => {
|
|
392
|
-
if (deps.isDestroyed()) return;
|
|
393
|
-
if (deps.isDragging()) return;
|
|
394
|
-
const active = deps.resolveSnap(deps.getActiveId());
|
|
395
|
-
if (!active || active.size === 0) return;
|
|
396
|
-
let target = null;
|
|
397
|
-
for (const id of deps.getAllowedIds()) {
|
|
398
|
-
const snap = deps.resolveSnap(id);
|
|
399
|
-
if (!snap || snap.size <= 0) continue;
|
|
400
|
-
if (!target || snap.size < target.size) target = snap;
|
|
401
|
-
}
|
|
402
|
-
if (!target) return;
|
|
403
|
-
if (target.id === active.id || target.size >= active.size) return;
|
|
404
|
-
deps.snapTo(target.id);
|
|
405
|
-
};
|
|
406
|
-
const reset = () => {
|
|
407
|
-
clearTimer();
|
|
408
|
-
if (deps.isDestroyed()) return;
|
|
409
|
-
timer = setTimeout(() => {
|
|
410
|
-
timer = null;
|
|
411
|
-
fire();
|
|
412
|
-
}, ms);
|
|
413
|
-
};
|
|
414
|
-
const unsubscribe = deps.on("snap", () => reset());
|
|
415
|
-
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
416
|
-
return () => {
|
|
417
|
-
clearTimer();
|
|
418
|
-
unsubscribe();
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
|
|
422
354
|
// src/core/features/linked-sheets.ts
|
|
423
355
|
function notifyLinkedSheets(sheets, self) {
|
|
424
356
|
if (sheets.length === 0) return;
|
|
@@ -441,394 +373,65 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
441
373
|
}
|
|
442
374
|
}
|
|
443
375
|
|
|
444
|
-
// src/core/features/
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
var pendingRebrand = null;
|
|
450
|
-
var listenerInstalled = false;
|
|
451
|
-
var patchInstalled = false;
|
|
452
|
-
var origPushState = null;
|
|
453
|
-
var origReplaceState = null;
|
|
454
|
-
var patchedPushState = null;
|
|
455
|
-
var patchedReplaceState = null;
|
|
456
|
-
var hasWindow = () => typeof window !== "undefined";
|
|
457
|
-
var hasHistory = () => typeof history !== "undefined";
|
|
458
|
-
var brandMarker = (surface) => ({
|
|
459
|
-
...surface.markerState(),
|
|
460
|
-
__bs: true
|
|
461
|
-
});
|
|
462
|
-
var runInternal = (fn) => {
|
|
463
|
-
internalDepth += 1;
|
|
464
|
-
try {
|
|
465
|
-
fn();
|
|
466
|
-
} finally {
|
|
467
|
-
internalDepth -= 1;
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
var notifyRouteChange = () => {
|
|
471
|
-
const snapshot = Array.from(subscribers);
|
|
472
|
-
for (const fn of snapshot) fn();
|
|
473
|
-
};
|
|
474
|
-
var ensureListener = () => {
|
|
475
|
-
if (listenerInstalled || !hasWindow()) return;
|
|
476
|
-
window.addEventListener("popstate", onPopState);
|
|
477
|
-
listenerInstalled = true;
|
|
478
|
-
};
|
|
479
|
-
var maybeTeardownListener = () => {
|
|
480
|
-
if (!listenerInstalled) return;
|
|
481
|
-
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
482
|
-
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
483
|
-
listenerInstalled = false;
|
|
484
|
-
};
|
|
485
|
-
var installPatch = () => {
|
|
486
|
-
if (patchInstalled || !hasHistory()) return;
|
|
487
|
-
origPushState = history.pushState;
|
|
488
|
-
origReplaceState = history.replaceState;
|
|
489
|
-
patchedPushState = function(...args) {
|
|
490
|
-
origPushState.apply(this, args);
|
|
491
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
492
|
-
};
|
|
493
|
-
patchedReplaceState = function(...args) {
|
|
494
|
-
origReplaceState.apply(this, args);
|
|
495
|
-
if (internalDepth === 0) notifyRouteChange();
|
|
496
|
-
};
|
|
497
|
-
history.pushState = patchedPushState;
|
|
498
|
-
history.replaceState = patchedReplaceState;
|
|
499
|
-
patchInstalled = true;
|
|
500
|
-
};
|
|
501
|
-
var removePatch = () => {
|
|
502
|
-
if (!patchInstalled) return;
|
|
503
|
-
if (history.pushState === patchedPushState && origPushState) {
|
|
504
|
-
history.pushState = origPushState;
|
|
505
|
-
}
|
|
506
|
-
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
507
|
-
history.replaceState = origReplaceState;
|
|
508
|
-
}
|
|
509
|
-
origPushState = null;
|
|
510
|
-
origReplaceState = null;
|
|
511
|
-
patchedPushState = null;
|
|
512
|
-
patchedReplaceState = null;
|
|
513
|
-
patchInstalled = false;
|
|
514
|
-
};
|
|
515
|
-
function onPopState() {
|
|
516
|
-
if (suppress > 0) {
|
|
517
|
-
suppress -= 1;
|
|
518
|
-
const rebrand = pendingRebrand;
|
|
519
|
-
pendingRebrand = null;
|
|
520
|
-
if (rebrand) rebrand();
|
|
521
|
-
maybeTeardownListener();
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
if (entries.length === 0) {
|
|
525
|
-
notifyRouteChange();
|
|
526
|
-
maybeTeardownListener();
|
|
527
|
-
return;
|
|
376
|
+
// src/core/features/resize-observer.ts
|
|
377
|
+
function installResizeObserver(deps) {
|
|
378
|
+
if (typeof window === "undefined") {
|
|
379
|
+
return () => {
|
|
380
|
+
};
|
|
528
381
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
382
|
+
const onResize = () => {
|
|
383
|
+
if (deps.isDestroyed()) return;
|
|
384
|
+
deps.recomputeSnaps();
|
|
385
|
+
const mode = deps.getMode();
|
|
386
|
+
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
387
|
+
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
388
|
+
const max = deps.getMaxAxisSize();
|
|
389
|
+
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
390
|
+
deps.setMaxAxisSize(viewportSize2);
|
|
537
391
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
392
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
393
|
+
deps.cancelInFlight();
|
|
394
|
+
deps.newCycle();
|
|
395
|
+
const current = deps.resolveActiveSnap();
|
|
396
|
+
const newMax = deps.getMaxAxisSize();
|
|
397
|
+
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
398
|
+
deps.setSize(targetSize);
|
|
399
|
+
if (current && !deps.isDragging()) {
|
|
400
|
+
deps.applySize(targetSize);
|
|
401
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
542
402
|
}
|
|
403
|
+
};
|
|
404
|
+
let resizeObserver = null;
|
|
405
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
406
|
+
resizeObserver = new ResizeObserver(onResize);
|
|
407
|
+
resizeObserver.observe(document.documentElement);
|
|
408
|
+
} else {
|
|
409
|
+
window.addEventListener("resize", onResize);
|
|
543
410
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
if (
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
}
|
|
556
|
-
maybeTeardownListener();
|
|
411
|
+
window.addEventListener("orientationchange", onResize);
|
|
412
|
+
const onVisibility = () => {
|
|
413
|
+
if (deps.isDestroyed()) return;
|
|
414
|
+
if (document.hidden) deps.cancelInFlight();
|
|
415
|
+
};
|
|
416
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
417
|
+
return () => {
|
|
418
|
+
resizeObserver?.disconnect();
|
|
419
|
+
window.removeEventListener("resize", onResize);
|
|
420
|
+
window.removeEventListener("orientationchange", onResize);
|
|
421
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
422
|
+
};
|
|
557
423
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
entries.push(entry);
|
|
570
|
-
ensureListener();
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function pushBackMarker(surface) {
|
|
574
|
-
const entry = { surface, priorUrl: void 0, live: false };
|
|
575
|
-
if (!hasWindow() || !hasHistory()) {
|
|
576
|
-
return entry;
|
|
577
|
-
}
|
|
578
|
-
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
579
|
-
runInternal(() => {
|
|
580
|
-
try {
|
|
581
|
-
history.pushState(brandMarker(surface), "", surface.url);
|
|
582
|
-
entry.live = true;
|
|
583
|
-
} catch {
|
|
584
|
-
entry.live = false;
|
|
585
|
-
}
|
|
586
|
-
});
|
|
587
|
-
if (entry.live) {
|
|
588
|
-
entries.push(entry);
|
|
589
|
-
ensureListener();
|
|
590
|
-
}
|
|
591
|
-
return entry;
|
|
592
|
-
}
|
|
593
|
-
function popBackMarker(handle) {
|
|
594
|
-
if (!hasWindow() || !hasHistory()) return;
|
|
595
|
-
const entry = handle;
|
|
596
|
-
const idx = entries.indexOf(entry);
|
|
597
|
-
if (idx === -1 || !entry.live) return;
|
|
598
|
-
const last = entries.length - 1;
|
|
599
|
-
entry.live = false;
|
|
600
|
-
entries.splice(idx, 1);
|
|
601
|
-
if (idx !== last) {
|
|
602
|
-
const rebrandSurface = entries[entries.length - 1].surface;
|
|
603
|
-
const rebrandUrl = entry.priorUrl;
|
|
604
|
-
pendingRebrand = () => {
|
|
605
|
-
runInternal(() => {
|
|
606
|
-
history.replaceState(
|
|
607
|
-
brandMarker(rebrandSurface),
|
|
608
|
-
"",
|
|
609
|
-
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
610
|
-
);
|
|
611
|
-
});
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
suppress += 1;
|
|
615
|
-
runInternal(() => {
|
|
616
|
-
try {
|
|
617
|
-
history.back();
|
|
618
|
-
} catch {
|
|
619
|
-
suppress = Math.max(0, suppress - 1);
|
|
620
|
-
pendingRebrand = null;
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
maybeTeardownListener();
|
|
624
|
-
}
|
|
625
|
-
function subscribeRouteChange(fn) {
|
|
626
|
-
if (!hasWindow() || !hasHistory()) return () => {
|
|
627
|
-
};
|
|
628
|
-
subscribers.add(fn);
|
|
629
|
-
if (subscribers.size === 1) installPatch();
|
|
630
|
-
ensureListener();
|
|
631
|
-
return () => {
|
|
632
|
-
if (!subscribers.has(fn)) return;
|
|
633
|
-
subscribers.delete(fn);
|
|
634
|
-
if (subscribers.size === 0) removePatch();
|
|
635
|
-
maybeTeardownListener();
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// src/core/features/route.ts
|
|
640
|
-
function installRoute(deps) {
|
|
641
|
-
if (typeof window === "undefined") {
|
|
642
|
-
return () => {
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
if (!deps.routedTo && !deps.closeOnBack) {
|
|
646
|
-
return () => {
|
|
647
|
-
};
|
|
648
|
-
}
|
|
649
|
-
let handle = null;
|
|
650
|
-
const onOpen = () => {
|
|
651
|
-
if (handle) return;
|
|
652
|
-
handle = pushBackMarker({
|
|
653
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
654
|
-
isTop: deps.isTopSheet,
|
|
655
|
-
close: deps.close,
|
|
656
|
-
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
657
|
-
url: deps.routedTo
|
|
658
|
-
});
|
|
659
|
-
};
|
|
660
|
-
const onClose = () => {
|
|
661
|
-
if (!handle) return;
|
|
662
|
-
popBackMarker(handle);
|
|
663
|
-
handle = null;
|
|
664
|
-
};
|
|
665
|
-
const unsubscribeOpen = deps.on("open", onOpen);
|
|
666
|
-
const unsubscribeClose = deps.on("close", onClose);
|
|
667
|
-
if (deps.getSize() > 0) onOpen();
|
|
668
|
-
return () => {
|
|
669
|
-
unsubscribeOpen();
|
|
670
|
-
unsubscribeClose();
|
|
671
|
-
if (handle) {
|
|
672
|
-
popBackMarker(handle);
|
|
673
|
-
handle = null;
|
|
674
|
-
}
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
function installRouteChange(deps) {
|
|
678
|
-
return subscribeRouteChange(() => {
|
|
679
|
-
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
680
|
-
void deps.close();
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
// src/core/features/content-swipe.ts
|
|
685
|
-
var CONTENT_PULL_THRESHOLD = 60;
|
|
686
|
-
function installContentSwipe(deps) {
|
|
687
|
-
const { container } = deps;
|
|
688
|
-
let startY = 0;
|
|
689
|
-
let startScrollTop = 0;
|
|
690
|
-
let moved = false;
|
|
691
|
-
const onTouchStart = (e) => {
|
|
692
|
-
const t = e.touches[0];
|
|
693
|
-
if (!t) return;
|
|
694
|
-
startY = t.clientY;
|
|
695
|
-
startScrollTop = container.scrollTop;
|
|
696
|
-
moved = false;
|
|
697
|
-
};
|
|
698
|
-
const onTouchMove = (e) => {
|
|
699
|
-
const t = e.touches[0];
|
|
700
|
-
if (!t) return;
|
|
701
|
-
if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
|
|
702
|
-
};
|
|
703
|
-
const onTouchEnd = (e) => {
|
|
704
|
-
if (!moved) return;
|
|
705
|
-
if (deps.isDragging() || deps.isAnimating()) return;
|
|
706
|
-
if (container.scrollTop !== startScrollTop) return;
|
|
707
|
-
const t = e.changedTouches[0];
|
|
708
|
-
if (!t) return;
|
|
709
|
-
const deltaY = t.clientY - startY;
|
|
710
|
-
const atTop = container.scrollTop <= 0;
|
|
711
|
-
const allowed = deps.getAllowedIds();
|
|
712
|
-
const idx = allowed.indexOf(deps.getActiveId());
|
|
713
|
-
if (idx === -1) return;
|
|
714
|
-
if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
|
|
715
|
-
deps.snapTo(allowed[idx - 1]);
|
|
716
|
-
} else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
|
|
717
|
-
deps.snapTo(allowed[idx + 1]);
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
container.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
721
|
-
container.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
722
|
-
container.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
723
|
-
return () => {
|
|
724
|
-
container.removeEventListener("touchstart", onTouchStart);
|
|
725
|
-
container.removeEventListener("touchmove", onTouchMove);
|
|
726
|
-
container.removeEventListener("touchend", onTouchEnd);
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// src/core/features/visual-viewport.ts
|
|
731
|
-
var SAFETY_PAD = 8;
|
|
732
|
-
function installVisualViewport(deps) {
|
|
733
|
-
if (typeof window === "undefined" || !window.visualViewport) {
|
|
734
|
-
return () => {
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
const vv = window.visualViewport;
|
|
738
|
-
let rafId = null;
|
|
739
|
-
const onResize = () => {
|
|
740
|
-
if (rafId !== null) return;
|
|
741
|
-
rafId = requestAnimationFrame(() => {
|
|
742
|
-
rafId = null;
|
|
743
|
-
if (deps.isDestroyed()) return;
|
|
744
|
-
deps.recomputeSnaps();
|
|
745
|
-
const isVertical = deps.isVerticalAxis();
|
|
746
|
-
const visible = isVertical ? vv.height : vv.width;
|
|
747
|
-
const windowSize = isVertical ? window.innerHeight : window.innerWidth;
|
|
748
|
-
const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
|
|
749
|
-
if (clamp < deps.getMaxAxisSize()) {
|
|
750
|
-
deps.setMaxAxisSize(clamp);
|
|
751
|
-
}
|
|
752
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
753
|
-
deps.cancelInFlight();
|
|
754
|
-
deps.newCycle();
|
|
755
|
-
const max = deps.getMaxAxisSize();
|
|
756
|
-
deps.setSize(Math.min(deps.getSize(), max));
|
|
757
|
-
const current = deps.resolveActiveSnap();
|
|
758
|
-
if (current && !deps.isDragging()) {
|
|
759
|
-
deps.applySize(Math.min(current.size, max));
|
|
760
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
761
|
-
} else {
|
|
762
|
-
deps.applySize(deps.getSize());
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
};
|
|
766
|
-
vv.addEventListener("resize", onResize);
|
|
767
|
-
return () => {
|
|
768
|
-
vv.removeEventListener("resize", onResize);
|
|
769
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
// src/core/features/resize-observer.ts
|
|
774
|
-
function installResizeObserver(deps) {
|
|
775
|
-
if (typeof window === "undefined") {
|
|
776
|
-
return () => {
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
const onResize = () => {
|
|
780
|
-
if (deps.isDestroyed()) return;
|
|
781
|
-
deps.recomputeSnaps();
|
|
782
|
-
const mode = deps.getMode();
|
|
783
|
-
const isVerticalAxis = mode === "bottom" || mode === "top";
|
|
784
|
-
const viewportSize2 = isVerticalAxis ? window.innerHeight : window.innerWidth;
|
|
785
|
-
const max = deps.getMaxAxisSize();
|
|
786
|
-
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
787
|
-
deps.setMaxAxisSize(viewportSize2);
|
|
788
|
-
}
|
|
789
|
-
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
790
|
-
deps.cancelInFlight();
|
|
791
|
-
deps.newCycle();
|
|
792
|
-
const current = deps.resolveActiveSnap();
|
|
793
|
-
const newMax = deps.getMaxAxisSize();
|
|
794
|
-
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
795
|
-
deps.setSize(targetSize);
|
|
796
|
-
if (current && !deps.isDragging()) {
|
|
797
|
-
deps.applySize(targetSize);
|
|
798
|
-
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
let resizeObserver = null;
|
|
802
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
803
|
-
resizeObserver = new ResizeObserver(onResize);
|
|
804
|
-
resizeObserver.observe(document.documentElement);
|
|
805
|
-
} else {
|
|
806
|
-
window.addEventListener("resize", onResize);
|
|
807
|
-
}
|
|
808
|
-
window.addEventListener("orientationchange", onResize);
|
|
809
|
-
const onVisibility = () => {
|
|
810
|
-
if (deps.isDestroyed()) return;
|
|
811
|
-
if (document.hidden) deps.cancelInFlight();
|
|
812
|
-
};
|
|
813
|
-
document.addEventListener("visibilitychange", onVisibility);
|
|
814
|
-
return () => {
|
|
815
|
-
resizeObserver?.disconnect();
|
|
816
|
-
window.removeEventListener("resize", onResize);
|
|
817
|
-
window.removeEventListener("orientationchange", onResize);
|
|
818
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
// src/core/features/fit-observer.ts
|
|
823
|
-
var contentTargets = (scroller) => {
|
|
824
|
-
if (!scroller) return [];
|
|
825
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
826
|
-
const out = [];
|
|
827
|
-
for (const child of Array.from(scroller.children)) {
|
|
828
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
829
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
830
|
-
} else {
|
|
831
|
-
out.push(child);
|
|
424
|
+
|
|
425
|
+
// src/core/features/fit-observer.ts
|
|
426
|
+
var contentTargets = (scroller) => {
|
|
427
|
+
if (!scroller) return [];
|
|
428
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
429
|
+
const out = [];
|
|
430
|
+
for (const child of Array.from(scroller.children)) {
|
|
431
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
432
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
433
|
+
} else {
|
|
434
|
+
out.push(child);
|
|
832
435
|
}
|
|
833
436
|
}
|
|
834
437
|
return out;
|
|
@@ -1670,6 +1273,52 @@ function resolveAnimationPreset(animation) {
|
|
|
1670
1273
|
}
|
|
1671
1274
|
}
|
|
1672
1275
|
|
|
1276
|
+
// src/core/animation/waapi-settle.ts
|
|
1277
|
+
var SIM_HZ = 240;
|
|
1278
|
+
var SAMPLE_STRIDE = 4;
|
|
1279
|
+
var MAX_SIM_MS = 3e3;
|
|
1280
|
+
function sampleSpringSettle(from, to, velocityPxPerS, config) {
|
|
1281
|
+
const cfg = { ...DEFAULT_SPRING, ...config };
|
|
1282
|
+
const subDt = 1 / SIM_HZ;
|
|
1283
|
+
const stepMs = SAMPLE_STRIDE / SIM_HZ * 1e3;
|
|
1284
|
+
const maxSteps = Math.ceil(MAX_SIM_MS / 1e3 * SIM_HZ);
|
|
1285
|
+
const values = [from];
|
|
1286
|
+
let x = from;
|
|
1287
|
+
let v = velocityPxPerS;
|
|
1288
|
+
for (let i = 1; i <= maxSteps; i += 1) {
|
|
1289
|
+
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1290
|
+
v += force / cfg.mass * subDt;
|
|
1291
|
+
x += v * subDt;
|
|
1292
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1293
|
+
values.push(to);
|
|
1294
|
+
break;
|
|
1295
|
+
}
|
|
1296
|
+
if (i % SAMPLE_STRIDE === 0) values.push(x);
|
|
1297
|
+
const atRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1298
|
+
if (atRest) break;
|
|
1299
|
+
}
|
|
1300
|
+
if (values[values.length - 1] !== to) values.push(to);
|
|
1301
|
+
return {
|
|
1302
|
+
values,
|
|
1303
|
+
stepMs,
|
|
1304
|
+
durationMs: (values.length - 1) * stepMs
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
function sampleTweenSettle(from, to, durationMs, easing) {
|
|
1308
|
+
const count = Math.max(2, Math.min(60, Math.round(durationMs / 16)));
|
|
1309
|
+
const values = [];
|
|
1310
|
+
for (let i = 0; i <= count; i += 1) {
|
|
1311
|
+
const t = i / count;
|
|
1312
|
+
values.push(from + (to - from) * easing(t));
|
|
1313
|
+
}
|
|
1314
|
+
values[values.length - 1] = to;
|
|
1315
|
+
return {
|
|
1316
|
+
values,
|
|
1317
|
+
stepMs: durationMs / count,
|
|
1318
|
+
durationMs
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1673
1322
|
// src/core/controllers/animation-runner.ts
|
|
1674
1323
|
var DEFAULT_DURATION2 = 220;
|
|
1675
1324
|
var VELOCITY_PX_PER_S = 1e3;
|
|
@@ -1680,6 +1329,10 @@ var AnimationRunner = class {
|
|
|
1680
1329
|
__publicField(this, "applySizeFn");
|
|
1681
1330
|
__publicField(this, "getSize");
|
|
1682
1331
|
__publicField(this, "isDragging");
|
|
1332
|
+
__publicField(this, "applyAux");
|
|
1333
|
+
__publicField(this, "getTransformFor");
|
|
1334
|
+
__publicField(this, "settleWaapi");
|
|
1335
|
+
__publicField(this, "currentWaapi", null);
|
|
1683
1336
|
__publicField(this, "animationKind");
|
|
1684
1337
|
__publicField(this, "springConfig");
|
|
1685
1338
|
__publicField(this, "duration");
|
|
@@ -1695,6 +1348,9 @@ var AnimationRunner = class {
|
|
|
1695
1348
|
this.applySizeFn = deps.applySize;
|
|
1696
1349
|
this.getSize = deps.getSize;
|
|
1697
1350
|
this.isDragging = deps.isDragging;
|
|
1351
|
+
this.applyAux = deps.applyAux;
|
|
1352
|
+
this.getTransformFor = deps.getTransformFor;
|
|
1353
|
+
this.settleWaapi = opts.settleAnimation === "waapi";
|
|
1698
1354
|
const preset = resolveAnimationPreset(opts.animation);
|
|
1699
1355
|
this.animationKind = preset.kind;
|
|
1700
1356
|
this.duration = opts.duration ?? preset.duration ?? DEFAULT_DURATION2;
|
|
@@ -1719,11 +1375,20 @@ var AnimationRunner = class {
|
|
|
1719
1375
|
}
|
|
1720
1376
|
}
|
|
1721
1377
|
get isAnimating() {
|
|
1722
|
-
return this.currentTween !== null || this.currentSpring !== null;
|
|
1378
|
+
return this.currentTween !== null || this.currentSpring !== null || this.currentWaapi !== null;
|
|
1723
1379
|
}
|
|
1724
1380
|
cancel() {
|
|
1725
1381
|
this.currentTween?.cancel();
|
|
1726
1382
|
this.currentSpring?.cancel();
|
|
1383
|
+
if (this.currentWaapi) {
|
|
1384
|
+
const entry = this.currentWaapi;
|
|
1385
|
+
this.currentWaapi = null;
|
|
1386
|
+
entry.stop();
|
|
1387
|
+
try {
|
|
1388
|
+
entry.anim.cancel();
|
|
1389
|
+
} catch {
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1727
1392
|
}
|
|
1728
1393
|
async animateTo(target, velocityPxPerMs) {
|
|
1729
1394
|
if (target === this.getSize()) {
|
|
@@ -1742,6 +1407,27 @@ var AnimationRunner = class {
|
|
|
1742
1407
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1743
1408
|
return;
|
|
1744
1409
|
}
|
|
1410
|
+
if (this.settleWaapi && this.applyAux && this.getTransformFor && typeof this.element.animate === "function") {
|
|
1411
|
+
const samples = this.animationKind === "spring" ? sampleSpringSettle(
|
|
1412
|
+
this.getSize(),
|
|
1413
|
+
target,
|
|
1414
|
+
velocityPxPerMs * VELOCITY_PX_PER_S,
|
|
1415
|
+
this.springConfig
|
|
1416
|
+
) : sampleTweenSettle(
|
|
1417
|
+
this.getSize(),
|
|
1418
|
+
target,
|
|
1419
|
+
this.duration,
|
|
1420
|
+
this.easing
|
|
1421
|
+
);
|
|
1422
|
+
if (samples.values.length >= 2 && samples.durationMs > 0) {
|
|
1423
|
+
await this.runWaapiSettle(samples, target);
|
|
1424
|
+
if (!this.isAnimating) {
|
|
1425
|
+
this.getRootEl()?.removeAttribute("data-animating");
|
|
1426
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1427
|
+
}
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1745
1431
|
if (this.animationKind === "spring") {
|
|
1746
1432
|
const spring = runSpring({
|
|
1747
1433
|
from: this.getSize(),
|
|
@@ -1770,15 +1456,70 @@ var AnimationRunner = class {
|
|
|
1770
1456
|
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1771
1457
|
}
|
|
1772
1458
|
}
|
|
1459
|
+
async runWaapiSettle(samples, target) {
|
|
1460
|
+
const applyAux = this.applyAux;
|
|
1461
|
+
const getTransformFor = this.getTransformFor;
|
|
1462
|
+
const frames = samples.values.map((v) => ({
|
|
1463
|
+
transform: getTransformFor(v)
|
|
1464
|
+
}));
|
|
1465
|
+
const anim = this.element.animate(frames, {
|
|
1466
|
+
duration: samples.durationMs,
|
|
1467
|
+
easing: "linear",
|
|
1468
|
+
fill: "forwards"
|
|
1469
|
+
});
|
|
1470
|
+
let stopped = false;
|
|
1471
|
+
let auxRaf = 0;
|
|
1472
|
+
const start = performance.now();
|
|
1473
|
+
const lastIdx = samples.values.length - 1;
|
|
1474
|
+
const auxTick = () => {
|
|
1475
|
+
if (stopped) return;
|
|
1476
|
+
const elapsed = performance.now() - start;
|
|
1477
|
+
const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
|
|
1478
|
+
applyAux(samples.values[idx]);
|
|
1479
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1480
|
+
};
|
|
1481
|
+
auxRaf = requestAnimationFrame(auxTick);
|
|
1482
|
+
const entry = {
|
|
1483
|
+
anim,
|
|
1484
|
+
stop: () => {
|
|
1485
|
+
stopped = true;
|
|
1486
|
+
cancelAnimationFrame(auxRaf);
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
this.currentWaapi = entry;
|
|
1490
|
+
try {
|
|
1491
|
+
await anim.finished;
|
|
1492
|
+
} catch {
|
|
1493
|
+
}
|
|
1494
|
+
entry.stop();
|
|
1495
|
+
const wasCurrent = this.currentWaapi === entry;
|
|
1496
|
+
if (wasCurrent) this.currentWaapi = null;
|
|
1497
|
+
if (wasCurrent && anim.playState === "finished") {
|
|
1498
|
+
this.applySizeFn(target);
|
|
1499
|
+
try {
|
|
1500
|
+
anim.cancel();
|
|
1501
|
+
} catch {
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1773
1505
|
destroy() {
|
|
1774
1506
|
this.detachReducedMotion?.();
|
|
1775
1507
|
this.detachReducedMotion = null;
|
|
1776
1508
|
this.currentTween = null;
|
|
1777
1509
|
this.currentSpring = null;
|
|
1510
|
+
if (this.currentWaapi) {
|
|
1511
|
+
const entry = this.currentWaapi;
|
|
1512
|
+
this.currentWaapi = null;
|
|
1513
|
+
entry.stop();
|
|
1514
|
+
try {
|
|
1515
|
+
entry.anim.cancel();
|
|
1516
|
+
} catch {
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1778
1519
|
}
|
|
1779
1520
|
};
|
|
1780
1521
|
|
|
1781
|
-
// src/core/lifecycle/
|
|
1522
|
+
// src/core/lifecycle/focus-trap.ts
|
|
1782
1523
|
var FOCUSABLE = [
|
|
1783
1524
|
"a[href]",
|
|
1784
1525
|
"area[href]",
|
|
@@ -1896,7 +1637,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1896
1637
|
};
|
|
1897
1638
|
};
|
|
1898
1639
|
|
|
1899
|
-
// src/core/lifecycle/
|
|
1640
|
+
// src/core/lifecycle/scroll-lock.ts
|
|
1900
1641
|
var lockCount = 0;
|
|
1901
1642
|
var savedStyles = null;
|
|
1902
1643
|
var lockBodyScroll = () => {
|
|
@@ -2078,30 +1819,44 @@ var SampleRing = class {
|
|
|
2078
1819
|
this.size = 0;
|
|
2079
1820
|
}
|
|
2080
1821
|
};
|
|
2081
|
-
var installGestures = (handle, mode, callbacks) => {
|
|
1822
|
+
var installGestures = (handle, mode, callbacks, options = {}) => {
|
|
2082
1823
|
let activePointerId = null;
|
|
2083
1824
|
let activePointerType = "touch";
|
|
2084
1825
|
let startCoord = 0;
|
|
2085
1826
|
let lastCoord = 0;
|
|
1827
|
+
let pendingStart = false;
|
|
2086
1828
|
const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
|
|
2087
1829
|
const MAX_SAMPLES = 32;
|
|
2088
1830
|
const samples = new SampleRing(MAX_SAMPLES);
|
|
2089
1831
|
const axis = isAxisVertical(mode) ? "Y" : "X";
|
|
2090
1832
|
const sign = mode === "bottom" || mode === "right" ? -1 : 1;
|
|
2091
1833
|
const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
|
|
1834
|
+
const capture = (pointerId) => {
|
|
1835
|
+
try {
|
|
1836
|
+
handle.setPointerCapture(pointerId);
|
|
1837
|
+
} catch {
|
|
1838
|
+
}
|
|
1839
|
+
};
|
|
1840
|
+
const releaseTracking = () => {
|
|
1841
|
+
activePointerId = null;
|
|
1842
|
+
pendingStart = false;
|
|
1843
|
+
samples.reset();
|
|
1844
|
+
};
|
|
2092
1845
|
const onPointerDown = (e) => {
|
|
2093
1846
|
if (activePointerId !== null) return;
|
|
2094
1847
|
if (e.button !== void 0 && e.button !== 0) return;
|
|
1848
|
+
if (options.shouldStart && !options.shouldStart(e)) return;
|
|
2095
1849
|
activePointerId = e.pointerId;
|
|
2096
1850
|
activePointerType = e.pointerType || "touch";
|
|
2097
1851
|
startCoord = coordOf(e);
|
|
2098
1852
|
lastCoord = startCoord;
|
|
2099
1853
|
samples.reset();
|
|
2100
1854
|
samples.push(e.timeStamp, startCoord);
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
1855
|
+
if (options.deferStart) {
|
|
1856
|
+
pendingStart = true;
|
|
1857
|
+
return;
|
|
2104
1858
|
}
|
|
1859
|
+
capture(e.pointerId);
|
|
2105
1860
|
callbacks.onStart(startCoord, activePointerType);
|
|
2106
1861
|
};
|
|
2107
1862
|
const onPointerMove = (e) => {
|
|
@@ -2109,6 +1864,22 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2109
1864
|
const coord = coordOf(e);
|
|
2110
1865
|
const rawDelta = coord - startCoord;
|
|
2111
1866
|
const delta = rawDelta * sign;
|
|
1867
|
+
if (pendingStart) {
|
|
1868
|
+
const verdict = options.deferStart(e, delta);
|
|
1869
|
+
if (verdict === false) {
|
|
1870
|
+
releaseTracking();
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
if (verdict !== true) return;
|
|
1874
|
+
pendingStart = false;
|
|
1875
|
+
startCoord = coord;
|
|
1876
|
+
lastCoord = coord;
|
|
1877
|
+
samples.reset();
|
|
1878
|
+
samples.push(e.timeStamp, coord);
|
|
1879
|
+
capture(e.pointerId);
|
|
1880
|
+
callbacks.onStart(startCoord, activePointerType);
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
2112
1883
|
lastCoord = coord;
|
|
2113
1884
|
samples.push(e.timeStamp, coord);
|
|
2114
1885
|
const cutoff = e.timeStamp - VELOCITY_WINDOW_MS(activePointerType);
|
|
@@ -2117,6 +1888,10 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2117
1888
|
};
|
|
2118
1889
|
const finishGesture = (e) => {
|
|
2119
1890
|
if (e.pointerId !== activePointerId) return;
|
|
1891
|
+
if (pendingStart) {
|
|
1892
|
+
releaseTracking();
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
2120
1895
|
const rawDelta = lastCoord - startCoord;
|
|
2121
1896
|
const delta = rawDelta * sign;
|
|
2122
1897
|
let velocity = 0;
|
|
@@ -2139,22 +1914,26 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
2139
1914
|
};
|
|
2140
1915
|
const onPointerCancel = (e) => {
|
|
2141
1916
|
if (e.pointerId !== activePointerId) return;
|
|
2142
|
-
|
|
2143
|
-
|
|
1917
|
+
const wasPending = pendingStart;
|
|
1918
|
+
releaseTracking();
|
|
1919
|
+
if (wasPending) return;
|
|
2144
1920
|
callbacks.onCancel?.();
|
|
2145
1921
|
};
|
|
2146
1922
|
handle.addEventListener("pointerdown", onPointerDown);
|
|
2147
1923
|
handle.addEventListener("pointermove", onPointerMove);
|
|
2148
1924
|
handle.addEventListener("pointerup", finishGesture);
|
|
2149
1925
|
handle.addEventListener("pointercancel", onPointerCancel);
|
|
1926
|
+
const managesTouchAction = options.manageTouchAction !== false;
|
|
2150
1927
|
const prevTouchAction = handle.style.touchAction;
|
|
2151
|
-
|
|
1928
|
+
if (managesTouchAction) {
|
|
1929
|
+
handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
|
|
1930
|
+
}
|
|
2152
1931
|
return () => {
|
|
2153
1932
|
handle.removeEventListener("pointerdown", onPointerDown);
|
|
2154
1933
|
handle.removeEventListener("pointermove", onPointerMove);
|
|
2155
1934
|
handle.removeEventListener("pointerup", finishGesture);
|
|
2156
1935
|
handle.removeEventListener("pointercancel", onPointerCancel);
|
|
2157
|
-
handle.style.touchAction = prevTouchAction;
|
|
1936
|
+
if (managesTouchAction) handle.style.touchAction = prevTouchAction;
|
|
2158
1937
|
if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
|
|
2159
1938
|
handle.releasePointerCapture(activePointerId);
|
|
2160
1939
|
}
|
|
@@ -2273,7 +2052,7 @@ var GestureController = class {
|
|
|
2273
2052
|
const restoreTo = this.dragStartSize;
|
|
2274
2053
|
void this.deps.animateTo(restoreTo, 0);
|
|
2275
2054
|
}
|
|
2276
|
-
});
|
|
2055
|
+
}, this.deps.gestureOptions);
|
|
2277
2056
|
return this.detach;
|
|
2278
2057
|
}
|
|
2279
2058
|
forceClearDragState() {
|
|
@@ -2285,6 +2064,41 @@ var GestureController = class {
|
|
|
2285
2064
|
}
|
|
2286
2065
|
};
|
|
2287
2066
|
|
|
2067
|
+
// src/core/primitives/drag-zones.ts
|
|
2068
|
+
var DRAG_ZONE_SELECTOR = "[data-bs-drag]";
|
|
2069
|
+
var NO_DRAG_SELECTOR = "[data-bs-no-drag]";
|
|
2070
|
+
var asElement = (target) => {
|
|
2071
|
+
const candidate = target;
|
|
2072
|
+
return candidate && typeof candidate.closest === "function" ? candidate : null;
|
|
2073
|
+
};
|
|
2074
|
+
function isDragAllowedFrom(target, mode) {
|
|
2075
|
+
const el = asElement(target);
|
|
2076
|
+
if (!el) return mode !== "zones";
|
|
2077
|
+
if (el.closest(NO_DRAG_SELECTOR)) return false;
|
|
2078
|
+
if (mode === "zones") return el.closest(DRAG_ZONE_SELECTOR) !== null;
|
|
2079
|
+
return true;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
// src/core/primitives/content-gesture.ts
|
|
2083
|
+
var CONTENT_DRAG_SLOP = 6;
|
|
2084
|
+
function decideContentGesture(input) {
|
|
2085
|
+
const slop = input.slop ?? CONTENT_DRAG_SLOP;
|
|
2086
|
+
if (Math.abs(input.delta) < slop) return "pending";
|
|
2087
|
+
if (input.scrollTop > 0) return "scroll";
|
|
2088
|
+
if (input.delta > 0 && input.atMaxSnap) return "scroll";
|
|
2089
|
+
return "drag";
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
// src/core/primitives/touch-scroll-guard.ts
|
|
2093
|
+
function installTouchScrollGuard(surface, isDragging) {
|
|
2094
|
+
const onTouchMove = (e) => {
|
|
2095
|
+
if (!isDragging()) return;
|
|
2096
|
+
if (e.cancelable) e.preventDefault();
|
|
2097
|
+
};
|
|
2098
|
+
surface.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
2099
|
+
return () => surface.removeEventListener("touchmove", onTouchMove);
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2288
2102
|
// src/core/primitives/aria-slider-writer.ts
|
|
2289
2103
|
var AriaSliderWriter = class {
|
|
2290
2104
|
constructor(handle, mode) {
|
|
@@ -2631,7 +2445,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2631
2445
|
const initialAllowed = opts.allowed ?? opts.snapPoints.map((p) => p.id);
|
|
2632
2446
|
let initialId = opts.initial ?? initialAllowed[0] ?? opts.snapPoints[0]?.id ?? "default";
|
|
2633
2447
|
if (opts.persistKey) {
|
|
2634
|
-
const restored =
|
|
2448
|
+
const restored = readPersistedIdSafe(opts.persistKey);
|
|
2635
2449
|
if (restored && initialAllowed.includes(restored)) {
|
|
2636
2450
|
initialId = restored;
|
|
2637
2451
|
}
|
|
@@ -2640,6 +2454,8 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2640
2454
|
mode: opts.mode ?? "bottom",
|
|
2641
2455
|
flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
|
|
2642
2456
|
dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
|
|
2457
|
+
dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
|
|
2458
|
+
dragFromContent: opts.dragFromContent ?? true,
|
|
2643
2459
|
rubberBandEnabled: opts.rubberBand ?? true,
|
|
2644
2460
|
closeOnBack: opts.closeOnBack ?? false,
|
|
2645
2461
|
persistent: opts.persistent ?? false,
|
|
@@ -2662,6 +2478,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2662
2478
|
},
|
|
2663
2479
|
animation: {
|
|
2664
2480
|
animation: opts.animation,
|
|
2481
|
+
settleAnimation: opts.settleAnimation,
|
|
2665
2482
|
duration: opts.duration,
|
|
2666
2483
|
easing: opts.easing,
|
|
2667
2484
|
spring: opts.spring,
|
|
@@ -2679,6 +2496,15 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2679
2496
|
}
|
|
2680
2497
|
};
|
|
2681
2498
|
}
|
|
2499
|
+
var readPersistedIdSafe = (key) => {
|
|
2500
|
+
if (typeof window === "undefined") return null;
|
|
2501
|
+
if (typeof localStorage === "undefined") return null;
|
|
2502
|
+
try {
|
|
2503
|
+
return localStorage.getItem(key);
|
|
2504
|
+
} catch {
|
|
2505
|
+
return null;
|
|
2506
|
+
}
|
|
2507
|
+
};
|
|
2682
2508
|
|
|
2683
2509
|
// src/core/primitives/teardown-stack.ts
|
|
2684
2510
|
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
|
constructor(opts) {
|
|
2708
2534
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
2709
2535
|
__publicField(this, "element");
|
|
@@ -2715,6 +2541,8 @@ var BottomSheetEngine = class {
|
|
|
2715
2541
|
__publicField(this, "mode");
|
|
2716
2542
|
__publicField(this, "flickVelocity");
|
|
2717
2543
|
__publicField(this, "dragThreshold");
|
|
2544
|
+
__publicField(this, "dragFromMode");
|
|
2545
|
+
__publicField(this, "dragFromContentDefault");
|
|
2718
2546
|
__publicField(this, "rubberBandEnabled");
|
|
2719
2547
|
__publicField(this, "scrim");
|
|
2720
2548
|
__publicField(this, "aria");
|
|
@@ -2732,8 +2560,11 @@ var BottomSheetEngine = class {
|
|
|
2732
2560
|
__publicField(this, "activeId");
|
|
2733
2561
|
__publicField(this, "size", 0);
|
|
2734
2562
|
__publicField(this, "gesture");
|
|
2563
|
+
__publicField(this, "contentGesture");
|
|
2564
|
+
__publicField(this, "detachSheetGesture", null);
|
|
2735
2565
|
__publicField(this, "rootEl", null);
|
|
2736
2566
|
__publicField(this, "destroyed", false);
|
|
2567
|
+
__publicField(this, "restClosed", false);
|
|
2737
2568
|
__publicField(this, "currentViewTransition", null);
|
|
2738
2569
|
__publicField(this, "currentAbort", new AbortController());
|
|
2739
2570
|
__publicField(this, "sizeWriteSentinel", new WriteSentinel());
|
|
@@ -2764,6 +2595,8 @@ var BottomSheetEngine = class {
|
|
|
2764
2595
|
__publicField(this, "stackEffectPrimed", false);
|
|
2765
2596
|
__publicField(this, "fitDeps");
|
|
2766
2597
|
__publicField(this, "transformTemplate");
|
|
2598
|
+
__publicField(this, "featureList", []);
|
|
2599
|
+
__publicField(this, "featureCtx");
|
|
2767
2600
|
const resolved = resolveEngineOptions(opts, {
|
|
2768
2601
|
shouldApplyInertSiblings: () => {
|
|
2769
2602
|
if (typeof document === "undefined") return false;
|
|
@@ -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
|
|
|
@@ -3796,6 +4220,8 @@ var BottomSheet = qwik.component$((props) => {
|
|
|
3796
4220
|
persistent: props.persistent,
|
|
3797
4221
|
disableClose: props.disableClose,
|
|
3798
4222
|
disableDrag: props.disableDrag,
|
|
4223
|
+
dragFrom: props.dragFrom,
|
|
4224
|
+
dragFromContent: props.dragFromContent,
|
|
3799
4225
|
closeOnRouteChange: props.closeOnRouteChange,
|
|
3800
4226
|
stackEffect: props.stackEffect,
|
|
3801
4227
|
returnFocusTo: props.returnFocusTo,
|
|
@@ -3905,11 +4331,17 @@ var BottomSheet = qwik.component$((props) => {
|
|
|
3905
4331
|
const persistent = track(() => props.persistent);
|
|
3906
4332
|
const disableClose = track(() => props.disableClose);
|
|
3907
4333
|
const disableDrag = track(() => props.disableDrag);
|
|
4334
|
+
const dragFromContent = track(() => props.dragFromContent);
|
|
4335
|
+
const dragFrom = track(() => props.dragFrom);
|
|
3908
4336
|
const engine = engineStore.engine;
|
|
3909
4337
|
if (!engine) return;
|
|
3910
4338
|
if (persistent !== void 0) engine.setPersistent(persistent);
|
|
3911
4339
|
if (disableClose !== void 0) engine.setDisableClose(disableClose);
|
|
3912
4340
|
if (disableDrag !== void 0) engine.setDisableDrag(disableDrag);
|
|
4341
|
+
if (dragFromContent !== void 0) {
|
|
4342
|
+
engine.setDragFromContent(dragFromContent);
|
|
4343
|
+
}
|
|
4344
|
+
if (dragFrom !== void 0) engine.setDragFrom(dragFrom);
|
|
3913
4345
|
});
|
|
3914
4346
|
const showBackdrop = props.backdrop !== false;
|
|
3915
4347
|
const mode = props.mode ?? "bottom";
|