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