@surdeddd/bottom-sheet 0.2.0 → 0.4.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 +51 -21
- package/dist/{BottomSheetEngine-CIT9Htti.d.cts → BottomSheetEngine-BJrH7qY3.d.cts} +105 -3
- package/dist/{BottomSheetEngine-Df9MwBbm.d.ts → BottomSheetEngine-L05jGZvU.d.ts} +105 -3
- package/dist/element.cjs +1170 -196
- package/dist/element.d.cts +29 -5
- package/dist/element.d.ts +29 -5
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +1170 -196
- package/dist/index.cjs +1051 -220
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +1049 -221
- 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 +181 -37
- package/dist/overlay.d.cts +13 -0
- package/dist/overlay.d.ts +13 -0
- package/dist/overlay.js +181 -37
- package/dist/preact.d.cts +1 -1
- package/dist/preact.d.ts +1 -1
- package/dist/qwik.cjs +966 -195
- package/dist/qwik.d.cts +4 -2
- package/dist/qwik.d.ts +4 -2
- package/dist/qwik.js +967 -196
- package/dist/react.cjs +1242 -272
- package/dist/react.d.cts +47 -5
- package/dist/react.d.ts +47 -5
- package/dist/react.js +1242 -272
- package/dist/solid.cjs +992 -236
- package/dist/solid.d.cts +299 -4
- package/dist/solid.d.ts +299 -4
- package/dist/solid.js +993 -237
- package/dist/solid.source.jsx +3476 -0
- package/dist/styles.css +67 -66
- package/dist/svelte-core.cjs +3415 -0
- package/dist/svelte-core.js +3413 -0
- package/dist/svelte-src/BottomSheet.svelte +308 -0
- package/dist/svelte-src/index.js +2 -0
- package/dist/svelte.cjs +1034 -207
- package/dist/svelte.d.cts +121 -0
- package/dist/svelte.d.ts +28 -3
- package/dist/svelte.js +1035 -208
- package/dist/vue.cjs +1191 -205
- package/dist/vue.d.cts +127 -0
- package/dist/vue.d.ts +57 -4
- package/dist/vue.js +1192 -206
- package/package.json +105 -45
package/dist/vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref, reactive, onMounted, onBeforeUnmount, openBlock,
|
|
1
|
+
import { ref, reactive, onMounted, onBeforeUnmount, openBlock, createBlock, Teleport, createElementVNode, createElementBlock, createCommentVNode, renderSlot, normalizeClass, toDisplayString, Fragment, renderList, defineComponent, watch, shallowRef, computed, readonly } from 'vue';
|
|
2
2
|
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -22,16 +22,52 @@ var SheetStack = class {
|
|
|
22
22
|
this.entries.splice(idx, 1);
|
|
23
23
|
this.recompute();
|
|
24
24
|
}
|
|
25
|
+
promote(id) {
|
|
26
|
+
const idx = this.entries.findIndex((e) => e.id === id);
|
|
27
|
+
if (idx === -1) return;
|
|
28
|
+
if (idx !== this.entries.length - 1) {
|
|
29
|
+
const [entry] = this.entries.splice(idx, 1);
|
|
30
|
+
this.entries.push(entry);
|
|
31
|
+
}
|
|
32
|
+
this.recompute();
|
|
33
|
+
}
|
|
34
|
+
update() {
|
|
35
|
+
this.recompute();
|
|
36
|
+
}
|
|
25
37
|
size() {
|
|
26
38
|
return this.entries.length;
|
|
27
39
|
}
|
|
40
|
+
depthOf(id) {
|
|
41
|
+
const open = [];
|
|
42
|
+
for (const entry of this.entries) {
|
|
43
|
+
if (!entry.isOpen || entry.isOpen()) open.push(entry);
|
|
44
|
+
}
|
|
45
|
+
const idx = open.findIndex((e) => e.id === id);
|
|
46
|
+
if (idx === -1) return 0;
|
|
47
|
+
return open.length - 1 - idx;
|
|
48
|
+
}
|
|
28
49
|
clear() {
|
|
29
50
|
this.entries = [];
|
|
30
51
|
}
|
|
31
52
|
recompute() {
|
|
53
|
+
let top = null;
|
|
54
|
+
const open = [];
|
|
55
|
+
for (const entry of this.entries) {
|
|
56
|
+
if (!entry.isOpen || entry.isOpen()) {
|
|
57
|
+
top = entry;
|
|
58
|
+
open.push(entry);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!top && this.entries.length > 0) {
|
|
62
|
+
top = this.entries[this.entries.length - 1];
|
|
63
|
+
}
|
|
32
64
|
this.entries.forEach((entry, i) => {
|
|
33
65
|
entry.setZIndex(BASE_Z + i * STEP);
|
|
34
|
-
entry.setIsTop(
|
|
66
|
+
entry.setIsTop(entry === top);
|
|
67
|
+
if (entry.setDepth) {
|
|
68
|
+
const openIdx = open.indexOf(entry);
|
|
69
|
+
entry.setDepth(openIdx === -1 ? 0 : open.length - 1 - openIdx);
|
|
70
|
+
}
|
|
35
71
|
});
|
|
36
72
|
}
|
|
37
73
|
};
|
|
@@ -128,7 +164,9 @@ var PERCENT = /^(-?\d+(?:\.\d+)?)%$/;
|
|
|
128
164
|
var resolveSnap = (point, mode, measureFit) => {
|
|
129
165
|
if (typeof point === "number") return Math.max(0, point);
|
|
130
166
|
if (point === "full") return viewportSize(mode);
|
|
131
|
-
if (point === "fit"
|
|
167
|
+
if (point === "fit" || point === "content") {
|
|
168
|
+
return Math.max(0, measureFit?.() ?? 0);
|
|
169
|
+
}
|
|
132
170
|
const pctMatch = point.match(PERCENT);
|
|
133
171
|
if (pctMatch) {
|
|
134
172
|
const pct = parseFloat(pctMatch[1]) / 100;
|
|
@@ -316,14 +354,17 @@ function installAutoCollapse(deps) {
|
|
|
316
354
|
const fire = () => {
|
|
317
355
|
if (deps.isDestroyed()) return;
|
|
318
356
|
if (deps.isDragging()) return;
|
|
319
|
-
const
|
|
320
|
-
|
|
357
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
358
|
+
if (!active || active.size === 0) return;
|
|
359
|
+
let target = null;
|
|
360
|
+
for (const id of deps.getAllowedIds()) {
|
|
321
361
|
const snap = deps.resolveSnap(id);
|
|
322
|
-
|
|
323
|
-
|
|
362
|
+
if (!snap || snap.size <= 0) continue;
|
|
363
|
+
if (!target || snap.size < target.size) target = snap;
|
|
364
|
+
}
|
|
324
365
|
if (!target) return;
|
|
325
|
-
if (target ===
|
|
326
|
-
deps.snapTo(target);
|
|
366
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
367
|
+
deps.snapTo(target.id);
|
|
327
368
|
};
|
|
328
369
|
const reset = () => {
|
|
329
370
|
clearTimer();
|
|
@@ -334,6 +375,7 @@ function installAutoCollapse(deps) {
|
|
|
334
375
|
}, ms);
|
|
335
376
|
};
|
|
336
377
|
const unsubscribe = deps.on("snap", () => reset());
|
|
378
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
337
379
|
return () => {
|
|
338
380
|
clearTimer();
|
|
339
381
|
unsubscribe();
|
|
@@ -346,6 +388,7 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
346
388
|
for (const linked of sheets) {
|
|
347
389
|
if (linked === self) continue;
|
|
348
390
|
try {
|
|
391
|
+
if (linked.state.size === 0) continue;
|
|
349
392
|
const ids = linked.getAllowedIds();
|
|
350
393
|
const target = ids.find((id) => id !== "closed");
|
|
351
394
|
if (target && target !== linked.state.activeId) {
|
|
@@ -360,6 +403,42 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
360
403
|
}
|
|
361
404
|
|
|
362
405
|
// src/core/features/route.ts
|
|
406
|
+
var closers = [];
|
|
407
|
+
var handlerInstalled = false;
|
|
408
|
+
var suppress = 0;
|
|
409
|
+
var ensureHandler = () => {
|
|
410
|
+
if (handlerInstalled || typeof window === "undefined") return;
|
|
411
|
+
handlerInstalled = true;
|
|
412
|
+
window.addEventListener("popstate", () => {
|
|
413
|
+
if (suppress > 0) {
|
|
414
|
+
suppress -= 1;
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
let target = null;
|
|
418
|
+
for (let i = closers.length - 1; i >= 0; i -= 1) {
|
|
419
|
+
const c = closers[i];
|
|
420
|
+
if (!c.isOpen()) continue;
|
|
421
|
+
if (!target) target = c;
|
|
422
|
+
if (c.isTop()) {
|
|
423
|
+
target = c;
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (!target) return;
|
|
428
|
+
target.consumed = true;
|
|
429
|
+
const idx = closers.indexOf(target);
|
|
430
|
+
if (idx !== -1) closers.splice(idx, 1);
|
|
431
|
+
target.close();
|
|
432
|
+
});
|
|
433
|
+
};
|
|
434
|
+
var programmaticBack = () => {
|
|
435
|
+
suppress += 1;
|
|
436
|
+
try {
|
|
437
|
+
history.back();
|
|
438
|
+
} catch {
|
|
439
|
+
suppress = Math.max(0, suppress - 1);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
363
442
|
function installRoute(deps) {
|
|
364
443
|
if (typeof window === "undefined") {
|
|
365
444
|
return () => {
|
|
@@ -369,82 +448,81 @@ function installRoute(deps) {
|
|
|
369
448
|
return () => {
|
|
370
449
|
};
|
|
371
450
|
}
|
|
372
|
-
let
|
|
373
|
-
let
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
451
|
+
let pushed = false;
|
|
452
|
+
let closer = null;
|
|
453
|
+
const teardownEntry = () => {
|
|
454
|
+
if (closer) {
|
|
455
|
+
const idx = closers.indexOf(closer);
|
|
456
|
+
if (idx !== -1) closers.splice(idx, 1);
|
|
457
|
+
}
|
|
458
|
+
const wasConsumed = closer?.consumed ?? false;
|
|
459
|
+
closer = null;
|
|
460
|
+
if (pushed && !wasConsumed) {
|
|
461
|
+
pushed = false;
|
|
462
|
+
programmaticBack();
|
|
463
|
+
} else {
|
|
464
|
+
pushed = false;
|
|
382
465
|
}
|
|
383
466
|
};
|
|
384
467
|
const onOpen = () => {
|
|
385
|
-
if (
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
window.addEventListener("popstate", onPop);
|
|
401
|
-
detachPopstate = () => window.removeEventListener("popstate", onPop);
|
|
402
|
-
} else if (deps.closeOnBack && !detachPopstate) {
|
|
403
|
-
try {
|
|
468
|
+
if (closer) return;
|
|
469
|
+
closer = {
|
|
470
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
471
|
+
isTop: () => deps.isTopSheet(),
|
|
472
|
+
close: () => void deps.close(),
|
|
473
|
+
consumed: false
|
|
474
|
+
};
|
|
475
|
+
ensureHandler();
|
|
476
|
+
closers.push(closer);
|
|
477
|
+
try {
|
|
478
|
+
if (deps.routedTo !== void 0) {
|
|
479
|
+
history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
|
|
480
|
+
} else {
|
|
404
481
|
history.pushState({ __bsSheet: deps.sheetId }, "");
|
|
405
|
-
closeOnBackPushed = true;
|
|
406
|
-
} catch {
|
|
407
482
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const state = history.state;
|
|
412
|
-
if (state?.__bsSheet !== deps.sheetId) closeOnBackPushed = false;
|
|
413
|
-
void deps.close();
|
|
414
|
-
}
|
|
415
|
-
};
|
|
416
|
-
window.addEventListener("popstate", onPop);
|
|
417
|
-
detachPopstate = () => window.removeEventListener("popstate", onPop);
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
const onClose = () => {
|
|
421
|
-
detachPopstate?.();
|
|
422
|
-
detachPopstate = null;
|
|
423
|
-
if (routePushed) {
|
|
424
|
-
routePushed = false;
|
|
425
|
-
if (deps.routedTo !== void 0) popOurMarker("__bsRouted", deps.routedTo);
|
|
426
|
-
}
|
|
427
|
-
if (closeOnBackPushed) {
|
|
428
|
-
closeOnBackPushed = false;
|
|
429
|
-
popOurMarker("__bsSheet", deps.sheetId);
|
|
483
|
+
pushed = true;
|
|
484
|
+
} catch {
|
|
485
|
+
pushed = false;
|
|
430
486
|
}
|
|
431
487
|
};
|
|
432
488
|
const unsubscribeOpen = deps.on("open", onOpen);
|
|
433
|
-
const unsubscribeClose = deps.on("close",
|
|
489
|
+
const unsubscribeClose = deps.on("close", teardownEntry);
|
|
434
490
|
if (deps.getSize() > 0) onOpen();
|
|
435
491
|
return () => {
|
|
436
492
|
unsubscribeOpen();
|
|
437
493
|
unsubscribeClose();
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
494
|
+
teardownEntry();
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function installRouteChange(deps) {
|
|
498
|
+
if (typeof window === "undefined" || typeof history === "undefined") {
|
|
499
|
+
return () => {
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
const onChange = () => {
|
|
503
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
504
|
+
void deps.close();
|
|
505
|
+
};
|
|
506
|
+
const wrap = (key) => {
|
|
507
|
+
const original = history[key];
|
|
508
|
+
const patched = function(...args) {
|
|
509
|
+
original.apply(this, args);
|
|
510
|
+
onChange();
|
|
511
|
+
};
|
|
512
|
+
history[key] = patched;
|
|
513
|
+
return () => {
|
|
514
|
+
if (history[key] === patched) {
|
|
515
|
+
history[key] = original;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
};
|
|
519
|
+
window.addEventListener("popstate", onChange);
|
|
520
|
+
const restorePush = wrap("pushState");
|
|
521
|
+
const restoreReplace = wrap("replaceState");
|
|
522
|
+
return () => {
|
|
523
|
+
window.removeEventListener("popstate", onChange);
|
|
524
|
+
restorePush();
|
|
525
|
+
restoreReplace();
|
|
448
526
|
};
|
|
449
527
|
}
|
|
450
528
|
|
|
@@ -546,13 +624,17 @@ function installResizeObserver(deps) {
|
|
|
546
624
|
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
547
625
|
deps.setMaxAxisSize(viewportSize2);
|
|
548
626
|
}
|
|
627
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
549
628
|
deps.cancelInFlight();
|
|
550
629
|
deps.newCycle();
|
|
551
630
|
const current = deps.resolveActiveSnap();
|
|
552
631
|
const newMax = deps.getMaxAxisSize();
|
|
553
632
|
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
554
633
|
deps.setSize(targetSize);
|
|
555
|
-
if (current && !deps.isDragging())
|
|
634
|
+
if (current && !deps.isDragging()) {
|
|
635
|
+
deps.applySize(targetSize);
|
|
636
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
637
|
+
}
|
|
556
638
|
};
|
|
557
639
|
let resizeObserver = null;
|
|
558
640
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -667,8 +749,88 @@ function devWarn(...args) {
|
|
|
667
749
|
}
|
|
668
750
|
}
|
|
669
751
|
|
|
752
|
+
// src/core/primitives/overlay-position.ts
|
|
753
|
+
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
754
|
+
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
755
|
+
switch (mode) {
|
|
756
|
+
case "bottom":
|
|
757
|
+
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
758
|
+
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
759
|
+
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
760
|
+
case "top":
|
|
761
|
+
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
762
|
+
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
763
|
+
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
764
|
+
case "left":
|
|
765
|
+
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
766
|
+
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
767
|
+
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
768
|
+
case "right":
|
|
769
|
+
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
770
|
+
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
771
|
+
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
function applyOverlayPosition(ws, mode, position, inset) {
|
|
775
|
+
switch (position) {
|
|
776
|
+
case "top-left":
|
|
777
|
+
ws.top = inset;
|
|
778
|
+
ws.left = inset;
|
|
779
|
+
break;
|
|
780
|
+
case "top-center":
|
|
781
|
+
ws.top = inset;
|
|
782
|
+
ws.left = "50%";
|
|
783
|
+
ws.transform = "translateX(-50%)";
|
|
784
|
+
break;
|
|
785
|
+
case "top-right":
|
|
786
|
+
ws.top = inset;
|
|
787
|
+
ws.right = inset;
|
|
788
|
+
break;
|
|
789
|
+
case "center-left":
|
|
790
|
+
ws.top = "50%";
|
|
791
|
+
ws.left = inset;
|
|
792
|
+
ws.transform = "translateY(-50%)";
|
|
793
|
+
break;
|
|
794
|
+
case "center":
|
|
795
|
+
ws.top = "50%";
|
|
796
|
+
ws.left = "50%";
|
|
797
|
+
ws.transform = "translate(-50%, -50%)";
|
|
798
|
+
break;
|
|
799
|
+
case "center-right":
|
|
800
|
+
ws.top = "50%";
|
|
801
|
+
ws.right = inset;
|
|
802
|
+
ws.transform = "translateY(-50%)";
|
|
803
|
+
break;
|
|
804
|
+
case "bottom-left":
|
|
805
|
+
ws.bottom = inset;
|
|
806
|
+
ws.left = inset;
|
|
807
|
+
break;
|
|
808
|
+
case "bottom-center":
|
|
809
|
+
ws.bottom = inset;
|
|
810
|
+
ws.left = "50%";
|
|
811
|
+
ws.transform = "translateX(-50%)";
|
|
812
|
+
break;
|
|
813
|
+
case "bottom-right":
|
|
814
|
+
ws.bottom = inset;
|
|
815
|
+
ws.right = inset;
|
|
816
|
+
break;
|
|
817
|
+
case "sheet-top-left":
|
|
818
|
+
case "sheet-top-center":
|
|
819
|
+
case "sheet-top-right": {
|
|
820
|
+
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
821
|
+
if (style.top !== void 0) ws.top = style.top;
|
|
822
|
+
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
823
|
+
if (style.left !== void 0) ws.left = style.left;
|
|
824
|
+
if (style.right !== void 0) ws.right = style.right;
|
|
825
|
+
if (style.transform !== void 0) ws.transform = style.transform;
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
670
831
|
// src/core/controllers/scrim-controller.ts
|
|
671
832
|
var VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
|
|
833
|
+
var DEFAULT_SCRIM_DIM = "rgba(0, 0, 0, 0.4)";
|
|
672
834
|
var ScrimController = class {
|
|
673
835
|
constructor(deps, opts) {
|
|
674
836
|
__publicField(this, "screenComponent");
|
|
@@ -679,6 +841,8 @@ var ScrimController = class {
|
|
|
679
841
|
__publicField(this, "getAllowedIds");
|
|
680
842
|
__publicField(this, "getResolvedSnaps");
|
|
681
843
|
__publicField(this, "snapToFn");
|
|
844
|
+
__publicField(this, "closeFn");
|
|
845
|
+
__publicField(this, "scrimInteractive", false);
|
|
682
846
|
__publicField(this, "scrimMode");
|
|
683
847
|
__publicField(this, "backdropRange");
|
|
684
848
|
__publicField(this, "screenRange");
|
|
@@ -699,14 +863,17 @@ var ScrimController = class {
|
|
|
699
863
|
this.getAllowedIds = deps.getAllowedIds;
|
|
700
864
|
this.getResolvedSnaps = deps.getResolvedSnaps;
|
|
701
865
|
this.snapToFn = deps.snapTo;
|
|
866
|
+
this.closeFn = deps.close;
|
|
702
867
|
this.scrimMode = opts.scrimMode ?? "full";
|
|
703
868
|
const preset = opts.scrimPreset ? SCRIM_PRESETS[opts.scrimPreset] : null;
|
|
704
869
|
this.backdropRange = opts.backdropRange ?? preset?.range ?? [0, 1];
|
|
705
870
|
this.screenRange = opts.screenRange ?? preset?.range ?? [0, 1];
|
|
706
871
|
this.scrimTapToCloseEnabled = opts.scrimTapToClose ?? false;
|
|
872
|
+
const explicitColor = opts.scrimColor ?? preset?.color;
|
|
873
|
+
const effectiveColor = explicitColor ?? (this.scrimMode !== "off" && !this.backdrop ? DEFAULT_SCRIM_DIM : void 0);
|
|
707
874
|
if (this.screenComponent) {
|
|
708
875
|
this.applyScrimStyles({
|
|
709
|
-
color:
|
|
876
|
+
color: effectiveColor,
|
|
710
877
|
blur: opts.scrimBlur ?? preset?.blur,
|
|
711
878
|
interactive: opts.scrimInteractive ?? preset?.interactive ?? false
|
|
712
879
|
});
|
|
@@ -840,11 +1007,15 @@ var ScrimController = class {
|
|
|
840
1007
|
}
|
|
841
1008
|
const onClick = () => {
|
|
842
1009
|
if (this.isDestroyed()) return;
|
|
1010
|
+
if (this.closeFn) {
|
|
1011
|
+
this.closeFn();
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
843
1014
|
const allowed = this.getAllowedIds();
|
|
844
1015
|
const snaps = this.getResolvedSnaps();
|
|
845
1016
|
const fallback = allowed.find((id) => {
|
|
846
1017
|
const snap = findById(id, snaps);
|
|
847
|
-
return snap !== null && snap.size
|
|
1018
|
+
return snap !== null && snap.size === 0;
|
|
848
1019
|
});
|
|
849
1020
|
if (fallback) this.snapToFn(fallback);
|
|
850
1021
|
};
|
|
@@ -861,6 +1032,7 @@ var ScrimController = class {
|
|
|
861
1032
|
if (this.isDestroyed()) return;
|
|
862
1033
|
if (enabled === this.scrimEnabled) return;
|
|
863
1034
|
this.scrimEnabled = enabled;
|
|
1035
|
+
this.invalidateOpacityCache();
|
|
864
1036
|
if (!enabled) {
|
|
865
1037
|
this.savedScrimRanges = {
|
|
866
1038
|
screen: this.screenRange,
|
|
@@ -884,7 +1056,12 @@ var ScrimController = class {
|
|
|
884
1056
|
blur: cfg.blur ?? null,
|
|
885
1057
|
interactive: cfg.interactive
|
|
886
1058
|
});
|
|
887
|
-
this.
|
|
1059
|
+
if (!this.scrimEnabled && this.savedScrimRanges) {
|
|
1060
|
+
this.savedScrimRanges = { screen: cfg.range, backdrop: cfg.range };
|
|
1061
|
+
} else {
|
|
1062
|
+
this.screenRange = cfg.range;
|
|
1063
|
+
this.backdropRange = cfg.range;
|
|
1064
|
+
}
|
|
888
1065
|
}
|
|
889
1066
|
const noop = () => {
|
|
890
1067
|
};
|
|
@@ -934,59 +1111,7 @@ var ScrimController = class {
|
|
|
934
1111
|
wrapper.className = "bs-scrim-overlay";
|
|
935
1112
|
const ws = wrapper.style;
|
|
936
1113
|
ws.position = "absolute";
|
|
937
|
-
|
|
938
|
-
case "top-left":
|
|
939
|
-
ws.top = inset;
|
|
940
|
-
ws.left = inset;
|
|
941
|
-
break;
|
|
942
|
-
case "top-center":
|
|
943
|
-
ws.top = inset;
|
|
944
|
-
ws.left = "50%";
|
|
945
|
-
ws.transform = "translateX(-50%)";
|
|
946
|
-
break;
|
|
947
|
-
case "top-right":
|
|
948
|
-
ws.top = inset;
|
|
949
|
-
ws.right = inset;
|
|
950
|
-
break;
|
|
951
|
-
case "center-left":
|
|
952
|
-
ws.top = "50%";
|
|
953
|
-
ws.left = inset;
|
|
954
|
-
ws.transform = "translateY(-50%)";
|
|
955
|
-
break;
|
|
956
|
-
case "center":
|
|
957
|
-
ws.top = "50%";
|
|
958
|
-
ws.left = "50%";
|
|
959
|
-
ws.transform = "translate(-50%, -50%)";
|
|
960
|
-
break;
|
|
961
|
-
case "center-right":
|
|
962
|
-
ws.top = "50%";
|
|
963
|
-
ws.right = inset;
|
|
964
|
-
ws.transform = "translateY(-50%)";
|
|
965
|
-
break;
|
|
966
|
-
case "bottom-left":
|
|
967
|
-
ws.bottom = inset;
|
|
968
|
-
ws.left = inset;
|
|
969
|
-
break;
|
|
970
|
-
case "bottom-center":
|
|
971
|
-
ws.bottom = inset;
|
|
972
|
-
ws.left = "50%";
|
|
973
|
-
ws.transform = "translateX(-50%)";
|
|
974
|
-
break;
|
|
975
|
-
case "bottom-right":
|
|
976
|
-
ws.bottom = inset;
|
|
977
|
-
ws.right = inset;
|
|
978
|
-
break;
|
|
979
|
-
case "sheet-top-left":
|
|
980
|
-
case "sheet-top-center":
|
|
981
|
-
case "sheet-top-right":
|
|
982
|
-
applySheetAnchoredPosition(
|
|
983
|
-
ws,
|
|
984
|
-
this.mode,
|
|
985
|
-
position,
|
|
986
|
-
inset
|
|
987
|
-
);
|
|
988
|
-
break;
|
|
989
|
-
}
|
|
1114
|
+
applyOverlayPosition(ws, this.mode, position, inset);
|
|
990
1115
|
if (interactive) {
|
|
991
1116
|
ws.pointerEvents = "auto";
|
|
992
1117
|
}
|
|
@@ -1045,6 +1170,7 @@ var ScrimController = class {
|
|
|
1045
1170
|
}
|
|
1046
1171
|
}
|
|
1047
1172
|
if (opts.interactive !== void 0) {
|
|
1173
|
+
this.scrimInteractive = opts.interactive;
|
|
1048
1174
|
s.pointerEvents = opts.interactive ? "auto" : "none";
|
|
1049
1175
|
}
|
|
1050
1176
|
}
|
|
@@ -1059,38 +1185,9 @@ var ScrimController = class {
|
|
|
1059
1185
|
const s = this.screenComponent.style;
|
|
1060
1186
|
s.position = "fixed";
|
|
1061
1187
|
s.inset = insetByMode[this.mode];
|
|
1062
|
-
s.pointerEvents = "none";
|
|
1188
|
+
s.pointerEvents = this.scrimInteractive || this.scrimTapToCloseEnabled ? "auto" : "none";
|
|
1063
1189
|
}
|
|
1064
1190
|
};
|
|
1065
|
-
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
1066
|
-
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
1067
|
-
switch (mode) {
|
|
1068
|
-
case "bottom":
|
|
1069
|
-
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
1070
|
-
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
1071
|
-
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1072
|
-
case "top":
|
|
1073
|
-
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
1074
|
-
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
1075
|
-
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1076
|
-
case "left":
|
|
1077
|
-
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
1078
|
-
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
1079
|
-
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1080
|
-
case "right":
|
|
1081
|
-
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
1082
|
-
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
1083
|
-
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
function applySheetAnchoredPosition(ws, mode, position, inset) {
|
|
1087
|
-
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
1088
|
-
if (style.top !== void 0) ws.top = style.top;
|
|
1089
|
-
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
1090
|
-
if (style.left !== void 0) ws.left = style.left;
|
|
1091
|
-
if (style.right !== void 0) ws.right = style.right;
|
|
1092
|
-
if (style.transform !== void 0) ws.transform = style.transform;
|
|
1093
|
-
}
|
|
1094
1191
|
|
|
1095
1192
|
// src/core/animation/animation.ts
|
|
1096
1193
|
var easeOutBack = (t) => {
|
|
@@ -1142,6 +1239,10 @@ var tween = ({
|
|
|
1142
1239
|
promise
|
|
1143
1240
|
};
|
|
1144
1241
|
};
|
|
1242
|
+
var prefersReducedMotion = () => {
|
|
1243
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1244
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1245
|
+
};
|
|
1145
1246
|
|
|
1146
1247
|
// src/core/animation/spring.ts
|
|
1147
1248
|
var DEFAULT_SPRING = {
|
|
@@ -1172,14 +1273,20 @@ var runSpring = ({
|
|
|
1172
1273
|
if (cancelled) return;
|
|
1173
1274
|
const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
|
|
1174
1275
|
lastTime = now;
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1276
|
+
const steps = Math.max(1, Math.ceil(dt * 240));
|
|
1277
|
+
const subDt = dt / steps;
|
|
1278
|
+
let stepsLeft = steps;
|
|
1177
1279
|
while (stepsLeft-- > 0) {
|
|
1178
1280
|
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1179
1281
|
const accel = force / cfg.mass;
|
|
1180
1282
|
v += accel * subDt;
|
|
1181
1283
|
x += v * subDt;
|
|
1182
1284
|
}
|
|
1285
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1286
|
+
onUpdate(to, 0);
|
|
1287
|
+
resolve();
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1183
1290
|
onUpdate(x, v);
|
|
1184
1291
|
const isAtRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1185
1292
|
if (isAtRest) {
|
|
@@ -1354,9 +1461,13 @@ var isVisible = (el) => {
|
|
|
1354
1461
|
var focusables = (root) => Array.from(root.querySelectorAll(FOCUSABLE)).filter(
|
|
1355
1462
|
(el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
|
|
1356
1463
|
);
|
|
1464
|
+
var trapStack = [];
|
|
1357
1465
|
var installFocusTrap = (container, options = {}) => {
|
|
1358
1466
|
if (typeof document === "undefined") return () => {
|
|
1359
1467
|
};
|
|
1468
|
+
const token = {};
|
|
1469
|
+
trapStack.push(token);
|
|
1470
|
+
const isActive = () => trapStack[trapStack.length - 1] === token;
|
|
1360
1471
|
const previouslyFocused = document.activeElement;
|
|
1361
1472
|
const focusInitial = () => {
|
|
1362
1473
|
const initial = typeof options.initialFocus === "string" ? container.querySelector(options.initialFocus) : options.initialFocus ?? focusables(container)[0] ?? container;
|
|
@@ -1364,6 +1475,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1364
1475
|
};
|
|
1365
1476
|
focusInitial();
|
|
1366
1477
|
const handleKey = (e) => {
|
|
1478
|
+
if (!isActive()) return;
|
|
1367
1479
|
if (e.key === "Escape" && options.onEscape) {
|
|
1368
1480
|
options.onEscape();
|
|
1369
1481
|
return;
|
|
@@ -1386,6 +1498,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1386
1498
|
}
|
|
1387
1499
|
};
|
|
1388
1500
|
const handleFocusIn = (e) => {
|
|
1501
|
+
if (!isActive()) return;
|
|
1389
1502
|
const target = e.target;
|
|
1390
1503
|
if (target && !container.contains(target)) {
|
|
1391
1504
|
const list = focusables(container);
|
|
@@ -1398,6 +1511,8 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1398
1511
|
return () => {
|
|
1399
1512
|
if (released) return;
|
|
1400
1513
|
released = true;
|
|
1514
|
+
const idx = trapStack.indexOf(token);
|
|
1515
|
+
if (idx !== -1) trapStack.splice(idx, 1);
|
|
1401
1516
|
document.removeEventListener("keydown", handleKey, true);
|
|
1402
1517
|
document.removeEventListener("focusin", handleFocusIn, true);
|
|
1403
1518
|
if (previouslyFocused && document.contains(previouslyFocused)) {
|
|
@@ -1453,11 +1568,17 @@ function createInertSiblings(rootProvider) {
|
|
|
1453
1568
|
return {
|
|
1454
1569
|
apply() {
|
|
1455
1570
|
if (typeof document === "undefined") return;
|
|
1456
|
-
|
|
1457
|
-
|
|
1571
|
+
let top = rootProvider();
|
|
1572
|
+
while (top.parentElement && top.parentElement !== document.body) {
|
|
1573
|
+
top = top.parentElement;
|
|
1574
|
+
}
|
|
1575
|
+
const parent = top.parentElement ?? document.body;
|
|
1458
1576
|
for (const child of Array.from(parent.children)) {
|
|
1459
|
-
if (child ===
|
|
1577
|
+
if (child === top) continue;
|
|
1460
1578
|
if (child.hasAttribute("inert")) continue;
|
|
1579
|
+
if (child.classList.contains("bs-backdrop") || child.classList.contains("bs-screen") || child.classList.contains("bs-root")) {
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1461
1582
|
child.setAttribute("inert", "");
|
|
1462
1583
|
tracked.push(child);
|
|
1463
1584
|
}
|
|
@@ -1473,7 +1594,6 @@ function createInertSiblings(rootProvider) {
|
|
|
1473
1594
|
var LifecycleController = class {
|
|
1474
1595
|
constructor(deps, opts) {
|
|
1475
1596
|
__publicField(this, "element");
|
|
1476
|
-
__publicField(this, "closeFn");
|
|
1477
1597
|
__publicField(this, "focusTrapEnabled");
|
|
1478
1598
|
__publicField(this, "initialFocus");
|
|
1479
1599
|
__publicField(this, "closeOnEscape");
|
|
@@ -1487,7 +1607,6 @@ var LifecycleController = class {
|
|
|
1487
1607
|
__publicField(this, "installed", false);
|
|
1488
1608
|
__publicField(this, "destroyed", false);
|
|
1489
1609
|
this.element = deps.element;
|
|
1490
|
-
this.closeFn = deps.close;
|
|
1491
1610
|
this.focusTrapEnabled = opts.focusTrap ?? false;
|
|
1492
1611
|
this.initialFocus = opts.initialFocus;
|
|
1493
1612
|
this.closeOnEscape = opts.closeOnEscape ?? true;
|
|
@@ -1497,6 +1616,9 @@ var LifecycleController = class {
|
|
|
1497
1616
|
this.returnFocus = opts.returnFocus;
|
|
1498
1617
|
this.inertSiblings = createInertSiblings(() => this.element);
|
|
1499
1618
|
}
|
|
1619
|
+
get isInstalled() {
|
|
1620
|
+
return this.installed;
|
|
1621
|
+
}
|
|
1500
1622
|
install() {
|
|
1501
1623
|
if (this.destroyed) return;
|
|
1502
1624
|
this.installed = true;
|
|
@@ -1505,8 +1627,7 @@ var LifecycleController = class {
|
|
|
1505
1627
|
}
|
|
1506
1628
|
if (this.focusTrapEnabled && !this.releaseFocusTrap) {
|
|
1507
1629
|
this.releaseFocusTrap = installFocusTrap(this.element, {
|
|
1508
|
-
initialFocus: this.initialFocus
|
|
1509
|
-
onEscape: this.closeOnEscape ? () => void this.closeFn() : void 0
|
|
1630
|
+
initialFocus: this.initialFocus
|
|
1510
1631
|
});
|
|
1511
1632
|
}
|
|
1512
1633
|
if (this.inertSiblingsEnabled && this.shouldApplyInertSiblings()) {
|
|
@@ -1526,7 +1647,7 @@ var LifecycleController = class {
|
|
|
1526
1647
|
this.releaseScrollLock = null;
|
|
1527
1648
|
this.inertSiblings.remove();
|
|
1528
1649
|
if (this.returnFocus) {
|
|
1529
|
-
const target = typeof this.returnFocus === "function" ? this.returnFocus() : this.returnFocus;
|
|
1650
|
+
const target = typeof this.returnFocus === "function" ? this.returnFocus() : typeof this.returnFocus === "string" ? typeof document !== "undefined" ? document.querySelector(this.returnFocus) : null : this.returnFocus;
|
|
1530
1651
|
target?.focus?.();
|
|
1531
1652
|
}
|
|
1532
1653
|
}
|
|
@@ -1660,10 +1781,11 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
1660
1781
|
};
|
|
1661
1782
|
|
|
1662
1783
|
// src/core/primitives/rubber-band.ts
|
|
1663
|
-
var RUBBER_BAND_FACTOR = 0.55;
|
|
1664
1784
|
function rubberBand(overshoot, maxAxisSize) {
|
|
1665
1785
|
const cap = Math.min(maxAxisSize * 0.15, 80);
|
|
1666
|
-
|
|
1786
|
+
if (cap <= 0) return 0;
|
|
1787
|
+
const abs = Math.abs(overshoot);
|
|
1788
|
+
return Math.sign(overshoot) * (cap * abs / (abs + cap));
|
|
1667
1789
|
}
|
|
1668
1790
|
|
|
1669
1791
|
// src/core/features/soft-keyboard.ts
|
|
@@ -1692,6 +1814,7 @@ var GestureController = class {
|
|
|
1692
1814
|
__publicField(this, "dragStartSize", 0);
|
|
1693
1815
|
__publicField(this, "currentPointerKind", "touch");
|
|
1694
1816
|
__publicField(this, "keyboardDismissed", false);
|
|
1817
|
+
__publicField(this, "dragSuppressed", false);
|
|
1695
1818
|
__publicField(this, "dragPayload", { size: 0, delta: 0 });
|
|
1696
1819
|
this.deps = deps;
|
|
1697
1820
|
}
|
|
@@ -1702,6 +1825,11 @@ var GestureController = class {
|
|
|
1702
1825
|
if (this.detach) return this.detach;
|
|
1703
1826
|
this.detach = installGestures(this.deps.handle, this.deps.mode, {
|
|
1704
1827
|
onStart: (_coord, kind) => {
|
|
1828
|
+
if (this.deps.getDisableDrag?.()) {
|
|
1829
|
+
this.dragSuppressed = true;
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
this.dragSuppressed = false;
|
|
1705
1833
|
this.deps.cancelAnimation();
|
|
1706
1834
|
this.isDragging_ = true;
|
|
1707
1835
|
this.dragStartSize = this.deps.getDragContext().size;
|
|
@@ -1712,6 +1840,7 @@ var GestureController = class {
|
|
|
1712
1840
|
this.deps.emit("dragstart", { size: this.dragStartSize });
|
|
1713
1841
|
},
|
|
1714
1842
|
onMove: (delta) => {
|
|
1843
|
+
if (this.dragSuppressed) return;
|
|
1715
1844
|
const ctx = this.deps.getDragContext();
|
|
1716
1845
|
const { min, max } = ctx.range;
|
|
1717
1846
|
const maxAxis = ctx.maxAxisSize;
|
|
@@ -1735,6 +1864,10 @@ var GestureController = class {
|
|
|
1735
1864
|
}
|
|
1736
1865
|
},
|
|
1737
1866
|
onEnd: (delta, velocity, kind) => {
|
|
1867
|
+
if (this.dragSuppressed) {
|
|
1868
|
+
this.dragSuppressed = false;
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1738
1871
|
this.isDragging_ = false;
|
|
1739
1872
|
this.keyboardDismissed = false;
|
|
1740
1873
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
@@ -1745,9 +1878,17 @@ var GestureController = class {
|
|
|
1745
1878
|
this.deps.settleAfterDrag(delta, velocity, kind);
|
|
1746
1879
|
},
|
|
1747
1880
|
onCancel: () => {
|
|
1881
|
+
if (this.dragSuppressed) {
|
|
1882
|
+
this.dragSuppressed = false;
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1748
1885
|
this.isDragging_ = false;
|
|
1749
1886
|
this.keyboardDismissed = false;
|
|
1750
1887
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1888
|
+
this.deps.emit("dragend", {
|
|
1889
|
+
size: this.deps.getDragContext().size,
|
|
1890
|
+
velocity: 0
|
|
1891
|
+
});
|
|
1751
1892
|
const restoreTo = this.dragStartSize;
|
|
1752
1893
|
void this.deps.animateTo(restoreTo, 0);
|
|
1753
1894
|
}
|
|
@@ -1821,6 +1962,287 @@ function createScrollCache(deps) {
|
|
|
1821
1962
|
};
|
|
1822
1963
|
}
|
|
1823
1964
|
|
|
1965
|
+
// src/core/primitives/anchor-animations.ts
|
|
1966
|
+
var DEFAULT_DURATION3 = 200;
|
|
1967
|
+
var DEFAULT_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
1968
|
+
var PRESET_FRAMES = {
|
|
1969
|
+
fade: {
|
|
1970
|
+
enter: [{ opacity: 0 }, { opacity: 1 }],
|
|
1971
|
+
exit: [{ opacity: 1 }, { opacity: 0 }]
|
|
1972
|
+
},
|
|
1973
|
+
scale: {
|
|
1974
|
+
enter: [
|
|
1975
|
+
{ opacity: 0, transform: "scale(0.85)" },
|
|
1976
|
+
{ opacity: 1, transform: "scale(1)" }
|
|
1977
|
+
],
|
|
1978
|
+
exit: [
|
|
1979
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
1980
|
+
{ opacity: 0, transform: "scale(0.85)" }
|
|
1981
|
+
]
|
|
1982
|
+
},
|
|
1983
|
+
slide: {
|
|
1984
|
+
enter: [
|
|
1985
|
+
{ opacity: 0, transform: "translateY(10px)" },
|
|
1986
|
+
{ opacity: 1, transform: "translateY(0)" }
|
|
1987
|
+
],
|
|
1988
|
+
exit: [
|
|
1989
|
+
{ opacity: 1, transform: "translateY(0)" },
|
|
1990
|
+
{ opacity: 0, transform: "translateY(10px)" }
|
|
1991
|
+
]
|
|
1992
|
+
},
|
|
1993
|
+
pop: {
|
|
1994
|
+
enter: [
|
|
1995
|
+
{ opacity: 0, transform: "scale(0.6)", offset: 0 },
|
|
1996
|
+
{ opacity: 1, transform: "scale(1.06)", offset: 0.7 },
|
|
1997
|
+
{ opacity: 1, transform: "scale(1)", offset: 1 }
|
|
1998
|
+
],
|
|
1999
|
+
exit: [
|
|
2000
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
2001
|
+
{ opacity: 0, transform: "scale(0.6)" }
|
|
2002
|
+
]
|
|
2003
|
+
}
|
|
2004
|
+
};
|
|
2005
|
+
var INSTANT = {
|
|
2006
|
+
finished: Promise.resolve(),
|
|
2007
|
+
cancel: () => {
|
|
2008
|
+
}
|
|
2009
|
+
};
|
|
2010
|
+
function resolveTransitionFrames(spec, phase) {
|
|
2011
|
+
const fallback = { frames: null, duration: 0, easing: DEFAULT_EASING };
|
|
2012
|
+
if (spec === "none") return fallback;
|
|
2013
|
+
if (spec === void 0 || typeof spec === "string") {
|
|
2014
|
+
const preset2 = PRESET_FRAMES[spec ?? "fade"];
|
|
2015
|
+
return {
|
|
2016
|
+
frames: preset2[phase],
|
|
2017
|
+
duration: DEFAULT_DURATION3,
|
|
2018
|
+
easing: DEFAULT_EASING
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
const custom = phase === "enter" ? spec.enter : spec.exit;
|
|
2022
|
+
if (custom) {
|
|
2023
|
+
return {
|
|
2024
|
+
frames: custom,
|
|
2025
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
2026
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
if (spec.preset === "none") return fallback;
|
|
2030
|
+
const preset = PRESET_FRAMES[spec.preset ?? "fade"];
|
|
2031
|
+
return {
|
|
2032
|
+
frames: preset[phase],
|
|
2033
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
2034
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
function runAnchorTransition(el, spec, phase) {
|
|
2038
|
+
const respectReduced = typeof spec === "object" ? spec.respectReducedMotion !== false : true;
|
|
2039
|
+
if (respectReduced && prefersReducedMotion()) return INSTANT;
|
|
2040
|
+
const { frames, duration, easing } = resolveTransitionFrames(spec, phase);
|
|
2041
|
+
if (!frames || duration <= 0) return INSTANT;
|
|
2042
|
+
if (typeof el.animate !== "function") return INSTANT;
|
|
2043
|
+
const animation = el.animate(frames, {
|
|
2044
|
+
duration,
|
|
2045
|
+
easing,
|
|
2046
|
+
fill: "both"
|
|
2047
|
+
});
|
|
2048
|
+
const finished = animation.finished.then(() => void 0).catch(() => void 0);
|
|
2049
|
+
return {
|
|
2050
|
+
finished,
|
|
2051
|
+
cancel: () => {
|
|
2052
|
+
try {
|
|
2053
|
+
animation.cancel();
|
|
2054
|
+
} catch {
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
// src/core/features/sheet-anchors.ts
|
|
2062
|
+
function attachAnchor(deps, opts) {
|
|
2063
|
+
const doc = deps.host.ownerDocument;
|
|
2064
|
+
const wrapper = doc.createElement("div");
|
|
2065
|
+
wrapper.className = "bs-anchor";
|
|
2066
|
+
const interactive = opts.interactive ?? true;
|
|
2067
|
+
const position = opts.position ?? "sheet-top-right";
|
|
2068
|
+
const isDock = position === "dock-bottom" || position === "dock-top";
|
|
2069
|
+
const ws = wrapper.style;
|
|
2070
|
+
ws.position = "fixed";
|
|
2071
|
+
if (isDock) {
|
|
2072
|
+
ws.left = "0";
|
|
2073
|
+
ws.right = "0";
|
|
2074
|
+
if (position === "dock-bottom") {
|
|
2075
|
+
ws.bottom = "0";
|
|
2076
|
+
} else {
|
|
2077
|
+
ws.top = "0";
|
|
2078
|
+
}
|
|
2079
|
+
} else {
|
|
2080
|
+
applyOverlayPosition(ws, deps.mode, position, opts.inset ?? "16px");
|
|
2081
|
+
}
|
|
2082
|
+
if (opts.fadeRange) {
|
|
2083
|
+
const [r0, r1] = opts.fadeRange;
|
|
2084
|
+
const span = Math.max(r1 - r0, 1e-4);
|
|
2085
|
+
ws.opacity = `clamp(0, calc((var(--bs-progress, 0) - ${r0}) / ${span}), 1)`;
|
|
2086
|
+
}
|
|
2087
|
+
wrapper.appendChild(opts.element);
|
|
2088
|
+
deps.host.appendChild(wrapper);
|
|
2089
|
+
let visible = null;
|
|
2090
|
+
let inFlight = null;
|
|
2091
|
+
const shouldShow = (state) => {
|
|
2092
|
+
if (typeof opts.showOn === "function") return opts.showOn(state);
|
|
2093
|
+
if (Array.isArray(opts.showOn)) return opts.showOn.includes(state.activeId);
|
|
2094
|
+
return isDock || state.size > 0;
|
|
2095
|
+
};
|
|
2096
|
+
const applyVisibility = (next, animate) => {
|
|
2097
|
+
if (next === visible) return;
|
|
2098
|
+
visible = next;
|
|
2099
|
+
inFlight?.cancel();
|
|
2100
|
+
inFlight = null;
|
|
2101
|
+
wrapper.style.pointerEvents = next && interactive ? "auto" : "none";
|
|
2102
|
+
if (next) {
|
|
2103
|
+
wrapper.style.visibility = "";
|
|
2104
|
+
if (animate) {
|
|
2105
|
+
inFlight = runAnchorTransition(opts.element, opts.animation, "enter");
|
|
2106
|
+
}
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
if (!animate) {
|
|
2110
|
+
wrapper.style.visibility = "hidden";
|
|
2111
|
+
return;
|
|
2112
|
+
}
|
|
2113
|
+
const handle = runAnchorTransition(opts.element, opts.animation, "exit");
|
|
2114
|
+
inFlight = handle;
|
|
2115
|
+
void handle.finished.then(() => {
|
|
2116
|
+
if (inFlight === handle && visible === false) {
|
|
2117
|
+
wrapper.style.visibility = "hidden";
|
|
2118
|
+
}
|
|
2119
|
+
});
|
|
2120
|
+
};
|
|
2121
|
+
const evaluate = (animate) => {
|
|
2122
|
+
if (deps.isDestroyed()) return;
|
|
2123
|
+
applyVisibility(shouldShow(deps.getState()), animate);
|
|
2124
|
+
};
|
|
2125
|
+
const offs = [
|
|
2126
|
+
deps.on("snap", () => evaluate(true)),
|
|
2127
|
+
deps.on("open", () => evaluate(true)),
|
|
2128
|
+
deps.on("close", () => evaluate(true))
|
|
2129
|
+
];
|
|
2130
|
+
evaluate(false);
|
|
2131
|
+
return {
|
|
2132
|
+
wrapper,
|
|
2133
|
+
detach: () => {
|
|
2134
|
+
offs.forEach((off) => off());
|
|
2135
|
+
inFlight?.cancel();
|
|
2136
|
+
inFlight = null;
|
|
2137
|
+
if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);
|
|
2138
|
+
},
|
|
2139
|
+
syncZ: (z) => {
|
|
2140
|
+
wrapper.style.zIndex = String(z);
|
|
2141
|
+
}
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
// src/core/features/scrim-stages.ts
|
|
2146
|
+
var matchesId = (def, activeId) => {
|
|
2147
|
+
if (def.for === void 0) return false;
|
|
2148
|
+
return Array.isArray(def.for) ? def.for.includes(activeId) : def.for === activeId;
|
|
2149
|
+
};
|
|
2150
|
+
var matchesRange = (def, progress) => {
|
|
2151
|
+
if (!def.forRange) return false;
|
|
2152
|
+
const [from, to] = def.forRange;
|
|
2153
|
+
return progress >= from && progress <= to;
|
|
2154
|
+
};
|
|
2155
|
+
function installScrimStages(deps, opts) {
|
|
2156
|
+
const doc = deps.host.ownerDocument;
|
|
2157
|
+
const entries = opts.stages.map((def) => {
|
|
2158
|
+
const wrapper = doc.createElement("div");
|
|
2159
|
+
wrapper.className = "bs-scrim-stage";
|
|
2160
|
+
const ws = wrapper.style;
|
|
2161
|
+
ws.position = "absolute";
|
|
2162
|
+
applyOverlayPosition(
|
|
2163
|
+
ws,
|
|
2164
|
+
deps.mode,
|
|
2165
|
+
def.position ?? opts.position ?? "center",
|
|
2166
|
+
def.inset ?? opts.inset ?? "16px"
|
|
2167
|
+
);
|
|
2168
|
+
ws.visibility = "hidden";
|
|
2169
|
+
ws.pointerEvents = "none";
|
|
2170
|
+
wrapper.appendChild(def.element);
|
|
2171
|
+
deps.host.appendChild(wrapper);
|
|
2172
|
+
return { def, wrapper, inFlight: null };
|
|
2173
|
+
});
|
|
2174
|
+
let active = null;
|
|
2175
|
+
const resolveActive = () => {
|
|
2176
|
+
const state = deps.getState();
|
|
2177
|
+
if (state.size === 0) {
|
|
2178
|
+
return entries.find((e) => matchesId(e.def, state.activeId)) ?? null;
|
|
2179
|
+
}
|
|
2180
|
+
return entries.find((e) => matchesId(e.def, state.activeId)) ?? entries.find((e) => matchesRange(e.def, state.progress)) ?? null;
|
|
2181
|
+
};
|
|
2182
|
+
const hide = (entry, animate) => {
|
|
2183
|
+
entry.inFlight?.cancel();
|
|
2184
|
+
entry.wrapper.style.pointerEvents = "none";
|
|
2185
|
+
if (!animate) {
|
|
2186
|
+
entry.inFlight = null;
|
|
2187
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
const handle = runAnchorTransition(
|
|
2191
|
+
entry.def.element,
|
|
2192
|
+
entry.def.animation ?? opts.animation,
|
|
2193
|
+
"exit"
|
|
2194
|
+
);
|
|
2195
|
+
entry.inFlight = handle;
|
|
2196
|
+
void handle.finished.then(() => {
|
|
2197
|
+
if (entry.inFlight === handle && active !== entry) {
|
|
2198
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
};
|
|
2202
|
+
const show = (entry, animate) => {
|
|
2203
|
+
entry.inFlight?.cancel();
|
|
2204
|
+
entry.inFlight = null;
|
|
2205
|
+
entry.wrapper.style.visibility = "";
|
|
2206
|
+
entry.wrapper.style.pointerEvents = entry.def.interactive ?? opts.interactive ?? false ? "auto" : "none";
|
|
2207
|
+
if (animate) {
|
|
2208
|
+
entry.inFlight = runAnchorTransition(
|
|
2209
|
+
entry.def.element,
|
|
2210
|
+
entry.def.animation ?? opts.animation,
|
|
2211
|
+
"enter"
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2215
|
+
const update = (animate) => {
|
|
2216
|
+
if (deps.isDestroyed()) return;
|
|
2217
|
+
const next = resolveActive();
|
|
2218
|
+
if (next === active) return;
|
|
2219
|
+
const prev = active;
|
|
2220
|
+
active = next;
|
|
2221
|
+
if (prev) hide(prev, animate);
|
|
2222
|
+
if (next) show(next, animate);
|
|
2223
|
+
};
|
|
2224
|
+
const offs = [
|
|
2225
|
+
deps.on("snap", () => update(true)),
|
|
2226
|
+
deps.on("open", () => update(true)),
|
|
2227
|
+
deps.on("close", () => update(true))
|
|
2228
|
+
];
|
|
2229
|
+
if (entries.some((e) => e.def.forRange)) {
|
|
2230
|
+
offs.push(deps.on("progress", () => update(true)));
|
|
2231
|
+
}
|
|
2232
|
+
update(false);
|
|
2233
|
+
return () => {
|
|
2234
|
+
offs.forEach((off) => off());
|
|
2235
|
+
for (const entry of entries) {
|
|
2236
|
+
entry.inFlight?.cancel();
|
|
2237
|
+
entry.inFlight = null;
|
|
2238
|
+
if (entry.wrapper.parentNode) {
|
|
2239
|
+
entry.wrapper.parentNode.removeChild(entry.wrapper);
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
active = null;
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
|
|
1824
2246
|
// src/core/primitives/engine-options.ts
|
|
1825
2247
|
var DEFAULT_FLICK_VELOCITY = 0.65;
|
|
1826
2248
|
var DEFAULT_DRAG_THRESHOLD = 18;
|
|
@@ -1839,6 +2261,12 @@ function resolveEngineOptions(opts, extras) {
|
|
|
1839
2261
|
dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
|
|
1840
2262
|
rubberBandEnabled: opts.rubberBand ?? true,
|
|
1841
2263
|
closeOnBack: opts.closeOnBack ?? false,
|
|
2264
|
+
persistent: opts.persistent ?? false,
|
|
2265
|
+
disableClose: opts.disableClose ?? false,
|
|
2266
|
+
disableDrag: opts.disableDrag ?? false,
|
|
2267
|
+
closeOnRouteChange: opts.closeOnRouteChange ?? false,
|
|
2268
|
+
radius: opts.radius,
|
|
2269
|
+
maxHeight: opts.maxHeight,
|
|
1842
2270
|
initialAllowed,
|
|
1843
2271
|
initialId,
|
|
1844
2272
|
scrim: {
|
|
@@ -1865,7 +2293,8 @@ function resolveEngineOptions(opts, extras) {
|
|
|
1865
2293
|
closeOnEscape: opts.closeOnEscape,
|
|
1866
2294
|
lockBodyScroll: opts.lockBodyScroll,
|
|
1867
2295
|
inertSiblings: opts.inertSiblings,
|
|
1868
|
-
shouldApplyInertSiblings: extras?.shouldApplyInertSiblings
|
|
2296
|
+
shouldApplyInertSiblings: extras?.shouldApplyInertSiblings,
|
|
2297
|
+
returnFocus: opts.returnFocusTo
|
|
1869
2298
|
}
|
|
1870
2299
|
};
|
|
1871
2300
|
}
|
|
@@ -1910,6 +2339,11 @@ var BottomSheetEngine = class {
|
|
|
1910
2339
|
__publicField(this, "lifecycle");
|
|
1911
2340
|
__publicField(this, "closeOnBack");
|
|
1912
2341
|
__publicField(this, "routedTo");
|
|
2342
|
+
__publicField(this, "persistent");
|
|
2343
|
+
__publicField(this, "disableCloseFlag");
|
|
2344
|
+
__publicField(this, "disableDragFlag");
|
|
2345
|
+
__publicField(this, "closeOnRouteChange");
|
|
2346
|
+
__publicField(this, "maxHeightCap");
|
|
1913
2347
|
__publicField(this, "snapPointsRaw");
|
|
1914
2348
|
__publicField(this, "snaps");
|
|
1915
2349
|
__publicField(this, "activeId");
|
|
@@ -1922,6 +2356,7 @@ var BottomSheetEngine = class {
|
|
|
1922
2356
|
__publicField(this, "sizeWriteSentinel", new WriteSentinel());
|
|
1923
2357
|
__publicField(this, "progressWriteSentinel", new WriteSentinel());
|
|
1924
2358
|
__publicField(this, "isTopSheet", true);
|
|
2359
|
+
__publicField(this, "opening", false);
|
|
1925
2360
|
__publicField(this, "progressPayload", {
|
|
1926
2361
|
value: 0,
|
|
1927
2362
|
size: 0
|
|
@@ -1937,6 +2372,12 @@ var BottomSheetEngine = class {
|
|
|
1937
2372
|
__publicField(this, "linkedSheets", []);
|
|
1938
2373
|
__publicField(this, "scrollCache");
|
|
1939
2374
|
__publicField(this, "teardowns", new TeardownStack());
|
|
2375
|
+
__publicField(this, "anchors", []);
|
|
2376
|
+
__publicField(this, "anchorHost", null);
|
|
2377
|
+
__publicField(this, "stackZ", 100);
|
|
2378
|
+
__publicField(this, "detachScrimStages", null);
|
|
2379
|
+
__publicField(this, "stackEffectEnabled", false);
|
|
2380
|
+
__publicField(this, "stackEffectPrimed", false);
|
|
1940
2381
|
__publicField(this, "transformTemplate");
|
|
1941
2382
|
const resolved = resolveEngineOptions(opts, {
|
|
1942
2383
|
shouldApplyInertSiblings: () => {
|
|
@@ -1970,6 +2411,10 @@ var BottomSheetEngine = class {
|
|
|
1970
2411
|
getResolvedSnaps: () => this.snaps.getResolvedSnaps().slice(),
|
|
1971
2412
|
snapTo: (id) => {
|
|
1972
2413
|
void this.snapTo(id);
|
|
2414
|
+
},
|
|
2415
|
+
close: () => {
|
|
2416
|
+
if (!this.canDismiss()) return;
|
|
2417
|
+
void this.close("backdrop");
|
|
1973
2418
|
}
|
|
1974
2419
|
},
|
|
1975
2420
|
resolved.scrim
|
|
@@ -1993,6 +2438,11 @@ var BottomSheetEngine = class {
|
|
|
1993
2438
|
);
|
|
1994
2439
|
this.closeOnBack = resolved.closeOnBack;
|
|
1995
2440
|
this.routedTo = opts.routedTo;
|
|
2441
|
+
this.persistent = resolved.persistent;
|
|
2442
|
+
this.disableCloseFlag = resolved.disableClose;
|
|
2443
|
+
this.disableDragFlag = resolved.disableDrag;
|
|
2444
|
+
this.closeOnRouteChange = resolved.closeOnRouteChange;
|
|
2445
|
+
this.stackEffectEnabled = opts.stackEffect ?? false;
|
|
1996
2446
|
this.snapPointsRaw = opts.snapPoints;
|
|
1997
2447
|
this.persistKey = opts.persistKey;
|
|
1998
2448
|
if (opts.linkedSheets) {
|
|
@@ -2005,7 +2455,7 @@ var BottomSheetEngine = class {
|
|
|
2005
2455
|
this.snapPointsRaw,
|
|
2006
2456
|
resolved.initialAllowed,
|
|
2007
2457
|
this.mode,
|
|
2008
|
-
() => this.
|
|
2458
|
+
() => this.measureFitSize(),
|
|
2009
2459
|
(maxAxisSize) => {
|
|
2010
2460
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2011
2461
|
}
|
|
@@ -2039,6 +2489,19 @@ var BottomSheetEngine = class {
|
|
|
2039
2489
|
io.observe(this.element);
|
|
2040
2490
|
this.teardowns.add(() => io.disconnect());
|
|
2041
2491
|
}
|
|
2492
|
+
this.installFitObserver();
|
|
2493
|
+
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2494
|
+
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2495
|
+
this.applyAutoAriaLabelledBy();
|
|
2496
|
+
if (this.closeOnRouteChange) {
|
|
2497
|
+
this.teardowns.add(
|
|
2498
|
+
installRouteChange({
|
|
2499
|
+
isDestroyed: () => this.destroyed,
|
|
2500
|
+
getSize: () => this.size,
|
|
2501
|
+
close: () => this.close()
|
|
2502
|
+
})
|
|
2503
|
+
);
|
|
2504
|
+
}
|
|
2042
2505
|
if (this.persistKey) {
|
|
2043
2506
|
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2044
2507
|
}
|
|
@@ -2063,7 +2526,7 @@ var BottomSheetEngine = class {
|
|
|
2063
2526
|
isTopSheet: () => this.isTopSheet,
|
|
2064
2527
|
getSize: () => this.size,
|
|
2065
2528
|
isDestroyed: () => this.destroyed,
|
|
2066
|
-
close: () => this.close(),
|
|
2529
|
+
close: () => this.close("back"),
|
|
2067
2530
|
on: (event, fn) => this.on(event, fn),
|
|
2068
2531
|
sheetId: this.id
|
|
2069
2532
|
})
|
|
@@ -2157,6 +2620,10 @@ var BottomSheetEngine = class {
|
|
|
2157
2620
|
const previousSize = this.size;
|
|
2158
2621
|
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
2159
2622
|
this.activeId = id;
|
|
2623
|
+
if (wasClosed && target.size > 0) {
|
|
2624
|
+
this.opening = true;
|
|
2625
|
+
sheetStack.promote(this.id);
|
|
2626
|
+
}
|
|
2160
2627
|
if (this.animation.viewTransitionsAvailable) {
|
|
2161
2628
|
this.currentViewTransition?.skipTransition?.();
|
|
2162
2629
|
const vt = document.startViewTransition(() => {
|
|
@@ -2171,19 +2638,26 @@ var BottomSheetEngine = class {
|
|
|
2171
2638
|
} else {
|
|
2172
2639
|
await this.animation.animateTo(target.size, velocityPxPerMs);
|
|
2173
2640
|
}
|
|
2641
|
+
this.opening = false;
|
|
2174
2642
|
externalSignal?.removeEventListener("abort", onExternalAbort);
|
|
2175
2643
|
if (signal.aborted) return;
|
|
2176
2644
|
this.scrollCache.restore(id, previousSize, target.size);
|
|
2177
2645
|
this.updateAriaSlider();
|
|
2178
|
-
this.emit("snap", {
|
|
2646
|
+
this.emit("snap", {
|
|
2647
|
+
id,
|
|
2648
|
+
size: target.size,
|
|
2649
|
+
progress: this.computeProgress(target.size)
|
|
2650
|
+
});
|
|
2179
2651
|
if (wasClosed && target.size > 0) {
|
|
2180
2652
|
this.emit("open", { id });
|
|
2181
2653
|
this.handleOpen();
|
|
2182
2654
|
notifyLinkedSheets(this.linkedSheets, this);
|
|
2655
|
+
this.emit("opened", { id });
|
|
2183
2656
|
}
|
|
2184
2657
|
if (target.size === 0) {
|
|
2185
2658
|
this.emit("close", void 0);
|
|
2186
2659
|
this.handleClose();
|
|
2660
|
+
this.emit("closed", void 0);
|
|
2187
2661
|
}
|
|
2188
2662
|
}
|
|
2189
2663
|
async dragTo(targetSize, velocityOrOpts = 0) {
|
|
@@ -2208,18 +2682,76 @@ var BottomSheetEngine = class {
|
|
|
2208
2682
|
const target = id ?? this.snaps.getAllowedIds().find((a) => a !== "closed") ?? this.activeId;
|
|
2209
2683
|
return this.snapTo(target);
|
|
2210
2684
|
}
|
|
2211
|
-
close() {
|
|
2685
|
+
close(reason = "programmatic") {
|
|
2212
2686
|
if (this.destroyed) return Promise.resolve();
|
|
2687
|
+
if (this.disableCloseFlag) return Promise.resolve();
|
|
2688
|
+
if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
|
|
2213
2689
|
const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
|
|
2214
2690
|
return this.snapTo(closedId ?? this.activeId);
|
|
2215
2691
|
}
|
|
2216
|
-
|
|
2692
|
+
canDismiss() {
|
|
2693
|
+
return !this.persistent && !this.disableCloseFlag && !this.destroyed;
|
|
2694
|
+
}
|
|
2695
|
+
isTop() {
|
|
2696
|
+
return this.isTopSheet;
|
|
2697
|
+
}
|
|
2698
|
+
depth() {
|
|
2699
|
+
return sheetStack.depthOf(this.id);
|
|
2700
|
+
}
|
|
2701
|
+
expand() {
|
|
2702
|
+
if (this.destroyed) return Promise.resolve();
|
|
2703
|
+
const ids = this.allowedIdsBySize();
|
|
2704
|
+
const target = ids[ids.length - 1];
|
|
2705
|
+
if (!target) return Promise.resolve();
|
|
2706
|
+
return this.snapTo(target);
|
|
2707
|
+
}
|
|
2708
|
+
collapse() {
|
|
2709
|
+
if (this.destroyed) return Promise.resolve();
|
|
2710
|
+
const ids = this.allowedIdsBySize();
|
|
2711
|
+
const nonZero = ids.find((id) => (this.snaps.findById(id)?.size ?? 0) > 0);
|
|
2712
|
+
const target = nonZero ?? ids[0];
|
|
2713
|
+
if (!target) return Promise.resolve();
|
|
2714
|
+
return this.snapTo(target);
|
|
2715
|
+
}
|
|
2716
|
+
setRadius(r) {
|
|
2217
2717
|
if (this.destroyed) return;
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2718
|
+
this.element.style.setProperty(
|
|
2719
|
+
"--bs-radius",
|
|
2720
|
+
typeof r === "number" ? `${r}px` : r
|
|
2721
|
+
);
|
|
2722
|
+
}
|
|
2723
|
+
setMaxHeight(h) {
|
|
2724
|
+
if (this.destroyed) return;
|
|
2725
|
+
const value = typeof h === "number" ? `${h}px` : h;
|
|
2726
|
+
const axis = layoutAxis(this.mode);
|
|
2727
|
+
this.element.style.setProperty(
|
|
2728
|
+
axis === "height" ? "maxHeight" : "maxWidth",
|
|
2729
|
+
value
|
|
2730
|
+
);
|
|
2731
|
+
if (typeof h === "number") {
|
|
2732
|
+
this.maxHeightCap = h;
|
|
2733
|
+
this.clampToMaxHeight();
|
|
2734
|
+
} else if (typeof window !== "undefined") {
|
|
2735
|
+
const probe2 = document.createElement("div");
|
|
2736
|
+
probe2.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;${axis === "height" ? "height" : "width"}:${value};`;
|
|
2737
|
+
document.body.appendChild(probe2);
|
|
2738
|
+
const measured = axis === "height" ? probe2.offsetHeight : probe2.offsetWidth;
|
|
2739
|
+
probe2.remove();
|
|
2740
|
+
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2741
|
+
this.clampToMaxHeight();
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
clampToMaxHeight() {
|
|
2745
|
+
if (this.maxHeightCap === void 0) return;
|
|
2746
|
+
if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
|
|
2747
|
+
this.snaps.setMaxAxisSize(this.maxHeightCap);
|
|
2222
2748
|
}
|
|
2749
|
+
if (this.size > this.maxHeightCap && !this.gesture?.isDragging) {
|
|
2750
|
+
this.applySize(this.maxHeightCap);
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
setAllowed(ids, snap) {
|
|
2754
|
+
if (this.destroyed) return;
|
|
2223
2755
|
this.snaps.setAllowedIds(ids);
|
|
2224
2756
|
this.updateAriaSlider();
|
|
2225
2757
|
if (snap && ids.includes(snap)) {
|
|
@@ -2259,6 +2791,79 @@ var BottomSheetEngine = class {
|
|
|
2259
2791
|
setScrimOverlay(opts) {
|
|
2260
2792
|
return this.scrim.setScrimOverlay(opts);
|
|
2261
2793
|
}
|
|
2794
|
+
addAnchor(opts) {
|
|
2795
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2796
|
+
};
|
|
2797
|
+
if (!this.anchorHost) {
|
|
2798
|
+
this.anchorHost = this.rootEl ?? this.element.parentElement ?? document.body;
|
|
2799
|
+
this.anchorHost.style.setProperty("--bs-size", `${this.size}px`);
|
|
2800
|
+
this.anchorHost.style.setProperty(
|
|
2801
|
+
"--bs-progress",
|
|
2802
|
+
String(this.computeProgress(this.size))
|
|
2803
|
+
);
|
|
2804
|
+
}
|
|
2805
|
+
const handle = attachAnchor(
|
|
2806
|
+
{
|
|
2807
|
+
mode: this.mode,
|
|
2808
|
+
host: this.anchorHost,
|
|
2809
|
+
getState: () => ({
|
|
2810
|
+
activeId: this.activeId,
|
|
2811
|
+
size: this.size,
|
|
2812
|
+
progress: this.computeProgress(this.size)
|
|
2813
|
+
}),
|
|
2814
|
+
on: (event, fn) => this.on(event, fn),
|
|
2815
|
+
isDestroyed: () => this.destroyed
|
|
2816
|
+
},
|
|
2817
|
+
opts
|
|
2818
|
+
);
|
|
2819
|
+
handle.syncZ(this.stackZ + 1);
|
|
2820
|
+
this.anchors.push(handle);
|
|
2821
|
+
const detach = () => {
|
|
2822
|
+
const idx = this.anchors.indexOf(handle);
|
|
2823
|
+
if (idx === -1) return;
|
|
2824
|
+
this.anchors.splice(idx, 1);
|
|
2825
|
+
handle.detach();
|
|
2826
|
+
};
|
|
2827
|
+
this.teardowns.add(detach);
|
|
2828
|
+
return detach;
|
|
2829
|
+
}
|
|
2830
|
+
setScrimStages(opts) {
|
|
2831
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2832
|
+
};
|
|
2833
|
+
this.detachScrimStages?.();
|
|
2834
|
+
this.detachScrimStages = null;
|
|
2835
|
+
if (!opts) return () => {
|
|
2836
|
+
};
|
|
2837
|
+
const host = this.screenComponent?.parentElement;
|
|
2838
|
+
if (!host) {
|
|
2839
|
+
console.warn(
|
|
2840
|
+
"[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
|
|
2841
|
+
);
|
|
2842
|
+
return () => {
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
const detachInstalled = installScrimStages(
|
|
2846
|
+
{
|
|
2847
|
+
mode: this.mode,
|
|
2848
|
+
host,
|
|
2849
|
+
getState: () => ({
|
|
2850
|
+
activeId: this.activeId,
|
|
2851
|
+
size: this.size,
|
|
2852
|
+
progress: this.computeProgress(this.size)
|
|
2853
|
+
}),
|
|
2854
|
+
on: (event, fn) => this.on(event, fn),
|
|
2855
|
+
isDestroyed: () => this.destroyed
|
|
2856
|
+
},
|
|
2857
|
+
opts
|
|
2858
|
+
);
|
|
2859
|
+
const detach = () => {
|
|
2860
|
+
if (this.detachScrimStages === detach) this.detachScrimStages = null;
|
|
2861
|
+
detachInstalled();
|
|
2862
|
+
};
|
|
2863
|
+
this.detachScrimStages = detach;
|
|
2864
|
+
this.teardowns.add(() => this.detachScrimStages?.());
|
|
2865
|
+
return detach;
|
|
2866
|
+
}
|
|
2262
2867
|
getScrimState() {
|
|
2263
2868
|
return { mode: this.scrim.scrimMode, enabled: this.scrim.scrimEnabled };
|
|
2264
2869
|
}
|
|
@@ -2278,8 +2883,53 @@ var BottomSheetEngine = class {
|
|
|
2278
2883
|
}
|
|
2279
2884
|
this.updateAriaSlider();
|
|
2280
2885
|
}
|
|
2886
|
+
recompute() {
|
|
2887
|
+
if (this.destroyed) return;
|
|
2888
|
+
this.snaps.recompute();
|
|
2889
|
+
this.scrim.invalidateOpacityCache();
|
|
2890
|
+
if (this.gesture?.isDragging) return;
|
|
2891
|
+
const current = this.snaps.findById(this.activeId);
|
|
2892
|
+
if (current) {
|
|
2893
|
+
this.size = current.size;
|
|
2894
|
+
this.applySize(this.size);
|
|
2895
|
+
this.updateAriaSlider();
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
measureFitSize() {
|
|
2899
|
+
const vertical = layoutAxis(this.mode) === "height";
|
|
2900
|
+
const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
|
|
2901
|
+
const content = this.scrollContainer;
|
|
2902
|
+
const natural = content ? handleSize + (vertical ? content.scrollHeight : content.scrollWidth) : handleSize;
|
|
2903
|
+
if (typeof window === "undefined") return natural;
|
|
2904
|
+
const viewport = vertical ? window.innerHeight : window.innerWidth;
|
|
2905
|
+
return viewport > 0 ? Math.min(natural, viewport) : natural;
|
|
2906
|
+
}
|
|
2907
|
+
installFitObserver() {
|
|
2908
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
2909
|
+
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2910
|
+
return;
|
|
2911
|
+
const targets = [this.handle];
|
|
2912
|
+
if (this.scrollContainer && this.scrollContainer !== this.handle) {
|
|
2913
|
+
targets.push(this.scrollContainer);
|
|
2914
|
+
}
|
|
2915
|
+
let raf = 0;
|
|
2916
|
+
const ro = new ResizeObserver(() => {
|
|
2917
|
+
if (raf) return;
|
|
2918
|
+
raf = requestAnimationFrame(() => {
|
|
2919
|
+
raf = 0;
|
|
2920
|
+
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2921
|
+
this.recompute();
|
|
2922
|
+
});
|
|
2923
|
+
});
|
|
2924
|
+
for (const t of targets) ro.observe(t);
|
|
2925
|
+
this.teardowns.add(() => {
|
|
2926
|
+
ro.disconnect();
|
|
2927
|
+
if (raf) cancelAnimationFrame(raf);
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2281
2930
|
destroy() {
|
|
2282
2931
|
this.destroyed = true;
|
|
2932
|
+
this.opening = false;
|
|
2283
2933
|
this.currentAbort.abort();
|
|
2284
2934
|
this.currentViewTransition?.skipTransition?.();
|
|
2285
2935
|
this.currentViewTransition = null;
|
|
@@ -2329,6 +2979,36 @@ var BottomSheetEngine = class {
|
|
|
2329
2979
|
frozen = true;
|
|
2330
2980
|
return cancelled;
|
|
2331
2981
|
}
|
|
2982
|
+
emitBeforeClose(reason) {
|
|
2983
|
+
let cancelled = false;
|
|
2984
|
+
let frozen = false;
|
|
2985
|
+
this.emit("before-close", {
|
|
2986
|
+
reason,
|
|
2987
|
+
cancel: () => {
|
|
2988
|
+
if (frozen) {
|
|
2989
|
+
console.warn(
|
|
2990
|
+
"[BottomSheet] before-close.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
|
|
2991
|
+
);
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
cancelled = true;
|
|
2995
|
+
}
|
|
2996
|
+
});
|
|
2997
|
+
frozen = true;
|
|
2998
|
+
return cancelled;
|
|
2999
|
+
}
|
|
3000
|
+
applyAutoAriaLabelledBy() {
|
|
3001
|
+
if (typeof document === "undefined") return;
|
|
3002
|
+
if (!this.lifecycle.focusTrapEnabled) return;
|
|
3003
|
+
if (this.element.getAttribute("aria-labelledby")) return;
|
|
3004
|
+
const scope = this.handle ?? this.element;
|
|
3005
|
+
const titled = scope.querySelector("[data-bs-title]") ?? scope.querySelector("h1,h2,h3,h4,h5,h6");
|
|
3006
|
+
if (!titled) return;
|
|
3007
|
+
if (!titled.id) {
|
|
3008
|
+
titled.id = nextInstanceId("bs-title");
|
|
3009
|
+
}
|
|
3010
|
+
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3011
|
+
}
|
|
2332
3012
|
recomputeSnaps() {
|
|
2333
3013
|
const seen = /* @__PURE__ */ new Set();
|
|
2334
3014
|
for (const p of this.snapPointsRaw) {
|
|
@@ -2345,24 +3025,42 @@ var BottomSheetEngine = class {
|
|
|
2345
3025
|
getAllowedRange() {
|
|
2346
3026
|
return this.snaps.getAllowedRange();
|
|
2347
3027
|
}
|
|
3028
|
+
allowedIdsBySize() {
|
|
3029
|
+
return this.snaps.getAllowedIds().slice().sort(
|
|
3030
|
+
(a, b) => (this.snaps.findById(a)?.size ?? 0) - (this.snaps.findById(b)?.size ?? 0)
|
|
3031
|
+
);
|
|
3032
|
+
}
|
|
2348
3033
|
updateAriaSlider() {
|
|
2349
|
-
this.aria.setValue(this.
|
|
3034
|
+
this.aria.setValue(this.allowedIdsBySize(), this.activeId);
|
|
2350
3035
|
}
|
|
2351
3036
|
registerInStack() {
|
|
2352
3037
|
this.teardowns.add(sheetStack.push({
|
|
2353
3038
|
id: this.id,
|
|
2354
3039
|
setZIndex: (z) => {
|
|
3040
|
+
this.stackZ = z;
|
|
2355
3041
|
this.element.style.zIndex = String(z);
|
|
2356
3042
|
if (this.backdrop) this.backdrop.style.zIndex = String(z - 1);
|
|
3043
|
+
for (const anchor of this.anchors) anchor.syncZ(z + 1);
|
|
2357
3044
|
},
|
|
2358
3045
|
setIsTop: (isTop) => {
|
|
2359
3046
|
this.isTopSheet = isTop;
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
}
|
|
3047
|
+
},
|
|
3048
|
+
isOpen: () => this.size > 0 || this.opening,
|
|
3049
|
+
setDepth: (depth) => this.applyStackDepth(depth)
|
|
2364
3050
|
}));
|
|
2365
3051
|
}
|
|
3052
|
+
applyStackDepth(depth) {
|
|
3053
|
+
if (!this.stackEffectEnabled) return;
|
|
3054
|
+
this.element.setAttribute("data-stack-depth", String(depth));
|
|
3055
|
+
if (!this.stackEffectPrimed) {
|
|
3056
|
+
this.stackEffectPrimed = true;
|
|
3057
|
+
const isVertical = this.mode === "bottom" || this.mode === "top";
|
|
3058
|
+
this.element.style.transformOrigin = isVertical ? "50% 100%" : "0% 50%";
|
|
3059
|
+
this.element.style.transition = "scale 320ms cubic-bezier(0.29, 1.04, 0.84, 0.99)";
|
|
3060
|
+
}
|
|
3061
|
+
const scale = Math.max(1 - depth * 0.04, 0.86);
|
|
3062
|
+
this.element.style.scale = scale === 1 ? "" : String(scale);
|
|
3063
|
+
}
|
|
2366
3064
|
attach() {
|
|
2367
3065
|
this.gesture = new GestureController({
|
|
2368
3066
|
handle: this.handle,
|
|
@@ -2379,6 +3077,7 @@ var BottomSheetEngine = class {
|
|
|
2379
3077
|
buf.rubberBandEnabled = this.rubberBandEnabled;
|
|
2380
3078
|
return buf;
|
|
2381
3079
|
},
|
|
3080
|
+
getDisableDrag: () => this.disableDragFlag,
|
|
2382
3081
|
cancelAnimation: () => this.animation.cancel(),
|
|
2383
3082
|
applySize: (size) => this.applySize(size),
|
|
2384
3083
|
animateTo: (size, velocity) => this.animation.animateTo(size, velocity),
|
|
@@ -2422,7 +3121,7 @@ var BottomSheetEngine = class {
|
|
|
2422
3121
|
container: this.scrollContainer,
|
|
2423
3122
|
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2424
3123
|
isAnimating: () => this.animation.isAnimating,
|
|
2425
|
-
getAllowedIds: () => this.
|
|
3124
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2426
3125
|
getActiveId: () => this.activeId,
|
|
2427
3126
|
snapTo: (id) => {
|
|
2428
3127
|
void this.snapTo(id);
|
|
@@ -2451,13 +3150,16 @@ var BottomSheetEngine = class {
|
|
|
2451
3150
|
},
|
|
2452
3151
|
newCycle: () => {
|
|
2453
3152
|
this.newCycle();
|
|
2454
|
-
}
|
|
3153
|
+
},
|
|
3154
|
+
isAnimating: () => this.animation.isAnimating,
|
|
3155
|
+
resyncAfterCancel: () => this.resyncAfterResize()
|
|
2455
3156
|
}));
|
|
2456
3157
|
if (this.lifecycle.closeOnEscape) {
|
|
2457
3158
|
const onKey = (e) => {
|
|
2458
|
-
if (this.destroyed) return;
|
|
3159
|
+
if (this.destroyed || e.defaultPrevented) return;
|
|
3160
|
+
if (!this.canDismiss()) return;
|
|
2459
3161
|
if (e.key === "Escape" && this.isTopSheet && this.size > 0) {
|
|
2460
|
-
void this.close();
|
|
3162
|
+
void this.close("escape");
|
|
2461
3163
|
}
|
|
2462
3164
|
};
|
|
2463
3165
|
document.addEventListener("keydown", onKey);
|
|
@@ -2487,7 +3189,7 @@ var BottomSheetEngine = class {
|
|
|
2487
3189
|
handle: this.handle,
|
|
2488
3190
|
mode: this.mode,
|
|
2489
3191
|
isDestroyed: () => this.destroyed,
|
|
2490
|
-
getAllowedIds: () => this.
|
|
3192
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2491
3193
|
getActiveId: () => this.activeId,
|
|
2492
3194
|
snapTo: (id) => {
|
|
2493
3195
|
void this.snapTo(id);
|
|
@@ -2508,6 +3210,7 @@ var BottomSheetEngine = class {
|
|
|
2508
3210
|
});
|
|
2509
3211
|
if (!target) return;
|
|
2510
3212
|
const previousId = this.activeId;
|
|
3213
|
+
if (target.id === previousId && target.size === this.size) return;
|
|
2511
3214
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
2512
3215
|
const restore = this.snaps.findById(previousId);
|
|
2513
3216
|
if (restore) {
|
|
@@ -2516,21 +3219,34 @@ var BottomSheetEngine = class {
|
|
|
2516
3219
|
return;
|
|
2517
3220
|
}
|
|
2518
3221
|
const previousSize = this.size;
|
|
3222
|
+
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
2519
3223
|
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
2520
3224
|
this.activeId = target.id;
|
|
3225
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
3226
|
+
this.opening = true;
|
|
3227
|
+
sheetStack.promote(this.id);
|
|
3228
|
+
}
|
|
2521
3229
|
void this.animation.animateTo(target.size, velocity).then(() => {
|
|
3230
|
+
this.opening = false;
|
|
2522
3231
|
if (signal.aborted) return;
|
|
2523
3232
|
this.scrollCache.restore(target.id, previousSize, target.size);
|
|
2524
3233
|
this.updateAriaSlider();
|
|
2525
|
-
this.emit("snap", {
|
|
3234
|
+
this.emit("snap", {
|
|
3235
|
+
id: target.id,
|
|
3236
|
+
size: target.size,
|
|
3237
|
+
progress: this.computeProgress(target.size)
|
|
3238
|
+
});
|
|
2526
3239
|
this.haptic();
|
|
2527
|
-
if (
|
|
3240
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
2528
3241
|
this.emit("open", { id: target.id });
|
|
2529
3242
|
this.handleOpen();
|
|
3243
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
3244
|
+
this.emit("opened", { id: target.id });
|
|
2530
3245
|
}
|
|
2531
3246
|
if (target.size === 0) {
|
|
2532
3247
|
this.emit("close", void 0);
|
|
2533
3248
|
this.handleClose();
|
|
3249
|
+
this.emit("closed", void 0);
|
|
2534
3250
|
}
|
|
2535
3251
|
});
|
|
2536
3252
|
}
|
|
@@ -2552,6 +3268,9 @@ var BottomSheetEngine = class {
|
|
|
2552
3268
|
if (this.scrimParent) {
|
|
2553
3269
|
this.scrimParent.style.setProperty("--bs-size", `${size}px`);
|
|
2554
3270
|
}
|
|
3271
|
+
if (this.anchorHost && this.anchorHost !== this.scrimParent) {
|
|
3272
|
+
this.anchorHost.style.setProperty("--bs-size", `${size}px`);
|
|
3273
|
+
}
|
|
2555
3274
|
}
|
|
2556
3275
|
const progress = this.computeProgress(size);
|
|
2557
3276
|
const progressChanged = this.progressWriteSentinel.shouldWrite(
|
|
@@ -2560,6 +3279,9 @@ var BottomSheetEngine = class {
|
|
|
2560
3279
|
);
|
|
2561
3280
|
if (progressChanged) {
|
|
2562
3281
|
style.setProperty("--bs-progress", String(progress));
|
|
3282
|
+
if (this.anchorHost) {
|
|
3283
|
+
this.anchorHost.style.setProperty("--bs-progress", String(progress));
|
|
3284
|
+
}
|
|
2563
3285
|
}
|
|
2564
3286
|
this.scrim.applyOpacity(progress, progressChanged);
|
|
2565
3287
|
if (progressChanged && this.bus.listenerCount("progress") > 0) {
|
|
@@ -2574,6 +3296,7 @@ var BottomSheetEngine = class {
|
|
|
2574
3296
|
return Math.min(Math.max((size - min) / (max - min), 0), 1);
|
|
2575
3297
|
}
|
|
2576
3298
|
handleOpen() {
|
|
3299
|
+
sheetStack.promote(this.id);
|
|
2577
3300
|
try {
|
|
2578
3301
|
this.lifecycle.install();
|
|
2579
3302
|
} catch (err) {
|
|
@@ -2587,8 +3310,31 @@ var BottomSheetEngine = class {
|
|
|
2587
3310
|
});
|
|
2588
3311
|
}
|
|
2589
3312
|
}
|
|
3313
|
+
resyncAfterResize() {
|
|
3314
|
+
if (this.destroyed) return;
|
|
3315
|
+
const target = this.snaps.findById(this.activeId);
|
|
3316
|
+
if (!target) return;
|
|
3317
|
+
this.updateAriaSlider();
|
|
3318
|
+
this.emit("snap", {
|
|
3319
|
+
id: target.id,
|
|
3320
|
+
size: target.size,
|
|
3321
|
+
progress: this.computeProgress(target.size)
|
|
3322
|
+
});
|
|
3323
|
+
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3324
|
+
this.emit("open", { id: target.id });
|
|
3325
|
+
this.handleOpen();
|
|
3326
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
3327
|
+
this.emit("opened", { id: target.id });
|
|
3328
|
+
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3329
|
+
this.emit("close", void 0);
|
|
3330
|
+
this.handleClose();
|
|
3331
|
+
this.emit("closed", void 0);
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
2590
3334
|
handleClose() {
|
|
3335
|
+
this.opening = false;
|
|
2591
3336
|
this.lifecycle.release();
|
|
3337
|
+
sheetStack.update();
|
|
2592
3338
|
}
|
|
2593
3339
|
};
|
|
2594
3340
|
|
|
@@ -2651,12 +3397,26 @@ function useBottomSheet(opts) {
|
|
|
2651
3397
|
state,
|
|
2652
3398
|
snapTo: (id) => engine?.snapTo(id) ?? Promise.resolve(),
|
|
2653
3399
|
open: (id) => engine?.open(id) ?? Promise.resolve(),
|
|
2654
|
-
close: () => engine?.close() ?? Promise.resolve(),
|
|
3400
|
+
close: (reason) => engine?.close(reason) ?? Promise.resolve(),
|
|
2655
3401
|
setAllowed: (ids, snap) => engine?.setAllowed(ids, snap),
|
|
2656
3402
|
setSnapPoints: (points, allowed) => engine?.setSnapPoints(points, allowed),
|
|
2657
3403
|
setScrim: (opts2) => engine?.setScrim(opts2),
|
|
2658
3404
|
setScrimOverlay: (opts2) => engine?.setScrimOverlay(opts2) ?? (() => {
|
|
2659
3405
|
}),
|
|
3406
|
+
addAnchor: (opts2) => engine?.addAnchor(opts2) ?? (() => {
|
|
3407
|
+
}),
|
|
3408
|
+
setScrimStages: (opts2) => engine?.setScrimStages(opts2) ?? (() => {
|
|
3409
|
+
}),
|
|
3410
|
+
recompute: () => engine?.recompute(),
|
|
3411
|
+
setScrimColor: (color) => engine?.setScrimColor(color),
|
|
3412
|
+
setBackdropRange: (range) => engine?.setBackdropRange(range),
|
|
3413
|
+
setRadius: (r) => engine?.setRadius(r),
|
|
3414
|
+
setMaxHeight: (h) => engine?.setMaxHeight(h),
|
|
3415
|
+
expand: () => engine?.expand() ?? Promise.resolve(),
|
|
3416
|
+
collapse: () => engine?.collapse() ?? Promise.resolve(),
|
|
3417
|
+
isTop: () => engine?.isTop() ?? false,
|
|
3418
|
+
depth: () => engine?.depth() ?? 0,
|
|
3419
|
+
canDismiss: () => engine?.canDismiss() ?? false,
|
|
2660
3420
|
on: (event, fn) => {
|
|
2661
3421
|
if (engine) return engine.on(event, fn);
|
|
2662
3422
|
const entry = {
|
|
@@ -2792,6 +3552,35 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2792
3552
|
type: Boolean,
|
|
2793
3553
|
required: false
|
|
2794
3554
|
},
|
|
3555
|
+
persistent: {
|
|
3556
|
+
type: Boolean,
|
|
3557
|
+
required: false
|
|
3558
|
+
},
|
|
3559
|
+
disableClose: {
|
|
3560
|
+
type: Boolean,
|
|
3561
|
+
required: false
|
|
3562
|
+
},
|
|
3563
|
+
disableDrag: {
|
|
3564
|
+
type: Boolean,
|
|
3565
|
+
required: false
|
|
3566
|
+
},
|
|
3567
|
+
closeOnRouteChange: {
|
|
3568
|
+
type: Boolean,
|
|
3569
|
+
required: false
|
|
3570
|
+
},
|
|
3571
|
+
radius: {
|
|
3572
|
+
type: [String, Number],
|
|
3573
|
+
required: false
|
|
3574
|
+
},
|
|
3575
|
+
maxHeight: {
|
|
3576
|
+
type: [String, Number],
|
|
3577
|
+
required: false
|
|
3578
|
+
},
|
|
3579
|
+
returnFocusTo: {
|
|
3580
|
+
type: [String, Function],
|
|
3581
|
+
required: false,
|
|
3582
|
+
skipCheck: true
|
|
3583
|
+
},
|
|
2795
3584
|
persistKey: {
|
|
2796
3585
|
type: String,
|
|
2797
3586
|
required: false
|
|
@@ -2808,6 +3597,10 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2808
3597
|
type: Boolean,
|
|
2809
3598
|
required: false
|
|
2810
3599
|
},
|
|
3600
|
+
stackEffect: {
|
|
3601
|
+
type: Boolean,
|
|
3602
|
+
required: false
|
|
3603
|
+
},
|
|
2811
3604
|
snapPoints: {
|
|
2812
3605
|
type: Array,
|
|
2813
3606
|
required: true
|
|
@@ -2838,22 +3631,159 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2838
3631
|
type: String,
|
|
2839
3632
|
required: false,
|
|
2840
3633
|
default: "Bottom sheet"
|
|
3634
|
+
},
|
|
3635
|
+
open: {
|
|
3636
|
+
type: Boolean,
|
|
3637
|
+
required: false
|
|
3638
|
+
},
|
|
3639
|
+
snap: {
|
|
3640
|
+
type: null,
|
|
3641
|
+
required: false
|
|
3642
|
+
},
|
|
3643
|
+
teleport: {
|
|
3644
|
+
type: Boolean,
|
|
3645
|
+
required: false,
|
|
3646
|
+
default: true
|
|
3647
|
+
},
|
|
3648
|
+
teleportTo: {
|
|
3649
|
+
type: null,
|
|
3650
|
+
required: false,
|
|
3651
|
+
default: "body"
|
|
3652
|
+
},
|
|
3653
|
+
anchors: {
|
|
3654
|
+
type: Array,
|
|
3655
|
+
required: false
|
|
3656
|
+
},
|
|
3657
|
+
scrimStages: {
|
|
3658
|
+
type: [Object, null],
|
|
3659
|
+
required: false
|
|
3660
|
+
},
|
|
3661
|
+
backdropColor: {
|
|
3662
|
+
type: String,
|
|
3663
|
+
required: false
|
|
3664
|
+
},
|
|
3665
|
+
backdropOpacity: {
|
|
3666
|
+
type: Number,
|
|
3667
|
+
required: false
|
|
2841
3668
|
}
|
|
2842
3669
|
},
|
|
2843
3670
|
emits: [
|
|
2844
3671
|
"change",
|
|
2845
3672
|
"snap",
|
|
2846
3673
|
"open",
|
|
2847
|
-
"close"
|
|
3674
|
+
"close",
|
|
3675
|
+
"opened",
|
|
3676
|
+
"closed",
|
|
3677
|
+
"before-close",
|
|
3678
|
+
"drag-start",
|
|
3679
|
+
"drag-end",
|
|
3680
|
+
"update:open",
|
|
3681
|
+
"update:snap"
|
|
2848
3682
|
],
|
|
2849
3683
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
2850
3684
|
const props = __props;
|
|
2851
3685
|
const emit = __emit;
|
|
2852
|
-
const { sheetRef, handleRef, contentRef, backdropRef, screenRef, state, snapTo, open, close, setAllowed, setSnapPoints, setScrim, setScrimOverlay, on, getEngine } = useBottomSheet(props);
|
|
3686
|
+
const { sheetRef, handleRef, contentRef, backdropRef, screenRef, state, snapTo, open, close, setAllowed, setSnapPoints, setScrim, setScrimOverlay, addAnchor, setScrimStages, recompute, setScrimColor, setBackdropRange, setRadius, setMaxHeight, expand, collapse, isTop, depth, canDismiss, on, getEngine } = useBottomSheet(props);
|
|
2853
3687
|
watch(() => ({ ...state }), (next) => emit("change", next), { deep: false });
|
|
2854
|
-
on("snap", (payload) =>
|
|
2855
|
-
|
|
2856
|
-
|
|
3688
|
+
on("snap", (payload) => {
|
|
3689
|
+
emit("snap", payload.id);
|
|
3690
|
+
emit("update:snap", payload.id);
|
|
3691
|
+
});
|
|
3692
|
+
on("open", (payload) => {
|
|
3693
|
+
emit("open", payload.id);
|
|
3694
|
+
emit("update:open", true);
|
|
3695
|
+
});
|
|
3696
|
+
on("close", () => {
|
|
3697
|
+
emit("close");
|
|
3698
|
+
emit("update:open", false);
|
|
3699
|
+
});
|
|
3700
|
+
on("opened", (payload) => emit("opened", payload.id));
|
|
3701
|
+
on("closed", () => emit("closed"));
|
|
3702
|
+
on("before-close", (payload) => emit("before-close", payload));
|
|
3703
|
+
on("dragstart", (payload) => emit("drag-start", payload));
|
|
3704
|
+
on("dragend", (payload) => emit("drag-end", payload));
|
|
3705
|
+
watch(() => props.open, (next) => {
|
|
3706
|
+
if (next === void 0) return;
|
|
3707
|
+
const isOpen = state.size > 0;
|
|
3708
|
+
if (next && !isOpen) void open();
|
|
3709
|
+
else if (!next && isOpen) void close();
|
|
3710
|
+
});
|
|
3711
|
+
watch(() => props.snap, (next) => {
|
|
3712
|
+
if (next === void 0 || next === state.activeId) return;
|
|
3713
|
+
void snapTo(next);
|
|
3714
|
+
});
|
|
3715
|
+
watch(() => props.backdropColor, (next) => {
|
|
3716
|
+
if (next === void 0) return;
|
|
3717
|
+
setScrimColor(next);
|
|
3718
|
+
});
|
|
3719
|
+
watch(() => props.backdropOpacity, (next) => {
|
|
3720
|
+
if (next === void 0) return;
|
|
3721
|
+
setBackdropRange([0, next]);
|
|
3722
|
+
});
|
|
3723
|
+
watch(() => props.radius, (next) => {
|
|
3724
|
+
if (next === void 0) return;
|
|
3725
|
+
setRadius(next);
|
|
3726
|
+
});
|
|
3727
|
+
watch(() => props.maxHeight, (next) => {
|
|
3728
|
+
if (next === void 0) return;
|
|
3729
|
+
setMaxHeight(next);
|
|
3730
|
+
});
|
|
3731
|
+
const mounted = ref(false);
|
|
3732
|
+
const anchorHosts = shallowRef({});
|
|
3733
|
+
const anchorDetachers = ref([]);
|
|
3734
|
+
let stagesDetach = null;
|
|
3735
|
+
const teardownAnchors = () => {
|
|
3736
|
+
anchorDetachers.value.forEach((d) => d());
|
|
3737
|
+
anchorDetachers.value = [];
|
|
3738
|
+
anchorHosts.value = {};
|
|
3739
|
+
};
|
|
3740
|
+
const buildAnchors = () => {
|
|
3741
|
+
teardownAnchors();
|
|
3742
|
+
const engine = getEngine();
|
|
3743
|
+
if (!engine || !props.anchors?.length) return;
|
|
3744
|
+
const hosts = {};
|
|
3745
|
+
const detachers = [];
|
|
3746
|
+
for (const a of props.anchors) {
|
|
3747
|
+
const host = document.createElement("div");
|
|
3748
|
+
hosts[a.id] = host;
|
|
3749
|
+
const { id: _id, ...rest } = a;
|
|
3750
|
+
detachers.push(engine.addAnchor({
|
|
3751
|
+
...rest,
|
|
3752
|
+
element: host
|
|
3753
|
+
}));
|
|
3754
|
+
}
|
|
3755
|
+
anchorHosts.value = hosts;
|
|
3756
|
+
anchorDetachers.value = detachers;
|
|
3757
|
+
};
|
|
3758
|
+
const anchorsKey = computed(() => JSON.stringify((props.anchors ?? []).map((a) => [
|
|
3759
|
+
a.id,
|
|
3760
|
+
a.position,
|
|
3761
|
+
a.inset,
|
|
3762
|
+
Array.isArray(a.showOn) ? a.showOn : a.showOn ? "fn" : null,
|
|
3763
|
+
a.fadeRange,
|
|
3764
|
+
a.interactive,
|
|
3765
|
+
typeof a.animation === "string" ? a.animation : a.animation ? "x" : null
|
|
3766
|
+
])));
|
|
3767
|
+
const applyStages = () => {
|
|
3768
|
+
stagesDetach?.();
|
|
3769
|
+
stagesDetach = null;
|
|
3770
|
+
const engine = getEngine();
|
|
3771
|
+
if (!engine || !props.scrimStages) return;
|
|
3772
|
+
stagesDetach = engine.setScrimStages(props.scrimStages);
|
|
3773
|
+
};
|
|
3774
|
+
onMounted(() => {
|
|
3775
|
+
mounted.value = true;
|
|
3776
|
+
buildAnchors();
|
|
3777
|
+
applyStages();
|
|
3778
|
+
watch(anchorsKey, buildAnchors);
|
|
3779
|
+
watch(() => props.scrimStages, applyStages, { deep: true });
|
|
3780
|
+
if (props.open && state.size === 0) void open();
|
|
3781
|
+
});
|
|
3782
|
+
onBeforeUnmount(() => {
|
|
3783
|
+
teardownAnchors();
|
|
3784
|
+
stagesDetach?.();
|
|
3785
|
+
stagesDetach = null;
|
|
3786
|
+
});
|
|
2857
3787
|
const isVerticalAxis = computed(() => {
|
|
2858
3788
|
const mode = props.mode ?? "bottom";
|
|
2859
3789
|
return mode === "bottom" || mode === "top";
|
|
@@ -2872,6 +3802,18 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2872
3802
|
setSnapPoints,
|
|
2873
3803
|
setScrim,
|
|
2874
3804
|
setScrimOverlay,
|
|
3805
|
+
addAnchor,
|
|
3806
|
+
setScrimStages,
|
|
3807
|
+
recompute,
|
|
3808
|
+
setScrimColor,
|
|
3809
|
+
setBackdropRange,
|
|
3810
|
+
setRadius,
|
|
3811
|
+
setMaxHeight,
|
|
3812
|
+
expand,
|
|
3813
|
+
collapse,
|
|
3814
|
+
isTop,
|
|
3815
|
+
depth,
|
|
3816
|
+
canDismiss,
|
|
2875
3817
|
on,
|
|
2876
3818
|
getEngine,
|
|
2877
3819
|
state: readonly(state)
|
|
@@ -2892,8 +3834,33 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2892
3834
|
setSnapPoints,
|
|
2893
3835
|
setScrim,
|
|
2894
3836
|
setScrimOverlay,
|
|
3837
|
+
addAnchor,
|
|
3838
|
+
setScrimStages,
|
|
3839
|
+
recompute,
|
|
3840
|
+
setScrimColor,
|
|
3841
|
+
setBackdropRange,
|
|
3842
|
+
setRadius,
|
|
3843
|
+
setMaxHeight,
|
|
3844
|
+
expand,
|
|
3845
|
+
collapse,
|
|
3846
|
+
isTop,
|
|
3847
|
+
depth,
|
|
3848
|
+
canDismiss,
|
|
2895
3849
|
on,
|
|
2896
3850
|
getEngine,
|
|
3851
|
+
mounted,
|
|
3852
|
+
anchorHosts,
|
|
3853
|
+
anchorDetachers,
|
|
3854
|
+
get stagesDetach() {
|
|
3855
|
+
return stagesDetach;
|
|
3856
|
+
},
|
|
3857
|
+
set stagesDetach(v) {
|
|
3858
|
+
stagesDetach = v;
|
|
3859
|
+
},
|
|
3860
|
+
teardownAnchors,
|
|
3861
|
+
buildAnchors,
|
|
3862
|
+
anchorsKey,
|
|
3863
|
+
applyStages,
|
|
2897
3864
|
isVerticalAxis,
|
|
2898
3865
|
allowedIds,
|
|
2899
3866
|
activeIdx,
|
|
@@ -2942,12 +3909,19 @@ var _hoisted_7 = {
|
|
|
2942
3909
|
"aria-label": "Sheet content"
|
|
2943
3910
|
};
|
|
2944
3911
|
var _hoisted_8 = {
|
|
3912
|
+
key: 2,
|
|
3913
|
+
class: "bs-footer"
|
|
3914
|
+
};
|
|
3915
|
+
var _hoisted_9 = {
|
|
2945
3916
|
class: "bs-sr-only",
|
|
2946
3917
|
role: "status",
|
|
2947
3918
|
"aria-live": "polite"
|
|
2948
3919
|
};
|
|
2949
3920
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
2950
|
-
return openBlock(),
|
|
3921
|
+
return openBlock(), createBlock(Teleport, {
|
|
3922
|
+
to: $props.teleportTo,
|
|
3923
|
+
disabled: !$props.teleport || !$setup.mounted
|
|
3924
|
+
}, [createElementVNode("div", _hoisted_1, [
|
|
2951
3925
|
$props.backdrop ? (openBlock(), createElementBlock(
|
|
2952
3926
|
"div",
|
|
2953
3927
|
{
|
|
@@ -2955,13 +3929,12 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
2955
3929
|
ref: "backdropRef",
|
|
2956
3930
|
class: "bs-backdrop",
|
|
2957
3931
|
"aria-hidden": "true",
|
|
2958
|
-
onClick: _cache[0] || (_cache[0] = ($event) => $props.closeOnBackdrop ? $setup.close() : void 0)
|
|
3932
|
+
onClick: _cache[0] || (_cache[0] = ($event) => $props.closeOnBackdrop && $setup.canDismiss() ? $setup.close("backdrop") : void 0)
|
|
2959
3933
|
},
|
|
2960
3934
|
null,
|
|
2961
3935
|
512
|
|
2962
3936
|
/* NEED_PATCH */
|
|
2963
3937
|
)) : createCommentVNode("v-if", true),
|
|
2964
|
-
createCommentVNode("\n Scrim surface always renders so the engine can host scrim presets\n (color/blur via setScrim), overlay injections (setScrimOverlay),\n and progress-driven opacity. The `screen` slot, when used, renders\n inside as user content. Without a slot it stays an empty positioning\n context.\n "),
|
|
2965
3938
|
createElementVNode(
|
|
2966
3939
|
"div",
|
|
2967
3940
|
_hoisted_2,
|
|
@@ -2999,17 +3972,30 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
2999
3972
|
512
|
|
3000
3973
|
/* NEED_PATCH */
|
|
3001
3974
|
),
|
|
3975
|
+
_ctx.$slots.footer ? (openBlock(), createElementBlock("div", _hoisted_8, [renderSlot(_ctx.$slots, "footer", { state: $setup.state })])) : createCommentVNode("v-if", true),
|
|
3002
3976
|
createElementVNode(
|
|
3003
3977
|
"span",
|
|
3004
|
-
|
|
3978
|
+
_hoisted_9,
|
|
3005
3979
|
toDisplayString($setup.state.activeId),
|
|
3006
3980
|
1
|
|
3007
3981
|
/* TEXT */
|
|
3008
3982
|
)
|
|
3009
3983
|
], 8, _hoisted_3)
|
|
3010
|
-
])
|
|
3984
|
+
]), (openBlock(true), createElementBlock(
|
|
3985
|
+
Fragment,
|
|
3986
|
+
null,
|
|
3987
|
+
renderList($setup.props.anchors ?? [], (a) => {
|
|
3988
|
+
return openBlock(), createBlock(Teleport, {
|
|
3989
|
+
key: a.id,
|
|
3990
|
+
to: $setup.anchorHosts[a.id],
|
|
3991
|
+
disabled: !$setup.anchorHosts[a.id]
|
|
3992
|
+
}, [renderSlot(_ctx.$slots, `anchor-${a.id}`, { state: $setup.state })], 8, ["to", "disabled"]);
|
|
3993
|
+
}),
|
|
3994
|
+
128
|
|
3995
|
+
/* KEYED_FRAGMENT */
|
|
3996
|
+
))], 8, ["to", "disabled"]);
|
|
3011
3997
|
}
|
|
3012
|
-
var BottomSheet_default = /* @__PURE__ */ export_helper_default(_sfc_main, [["render", _sfc_render], ["__file", "/
|
|
3998
|
+
var BottomSheet_default = /* @__PURE__ */ export_helper_default(_sfc_main, [["render", _sfc_render], ["__file", "/home/runner/work/BottomSheet/BottomSheet/src/vue/BottomSheet.vue"]]);
|
|
3013
3999
|
|
|
3014
4000
|
export { BottomSheet_default as BottomSheet, useBottomSheet };
|
|
3015
4001
|
//# sourceMappingURL=vue.js.map
|