@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/react.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { forwardRef, useRef, useState, useEffect, useImperativeHandle, useMemo, useCallback, useSyncExternalStore, useLayoutEffect } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
2
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
4
|
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
@@ -23,16 +24,52 @@ var SheetStack = class {
|
|
|
23
24
|
this.entries.splice(idx, 1);
|
|
24
25
|
this.recompute();
|
|
25
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
|
+
}
|
|
26
39
|
size() {
|
|
27
40
|
return this.entries.length;
|
|
28
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
|
+
}
|
|
29
51
|
clear() {
|
|
30
52
|
this.entries = [];
|
|
31
53
|
}
|
|
32
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
|
+
}
|
|
33
66
|
this.entries.forEach((entry, i) => {
|
|
34
67
|
entry.setZIndex(BASE_Z + i * STEP);
|
|
35
|
-
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
|
+
}
|
|
36
73
|
});
|
|
37
74
|
}
|
|
38
75
|
};
|
|
@@ -135,7 +172,9 @@ var PERCENT = /^(-?\d+(?:\.\d+)?)%$/;
|
|
|
135
172
|
var resolveSnap = (point, mode, measureFit) => {
|
|
136
173
|
if (typeof point === "number") return Math.max(0, point);
|
|
137
174
|
if (point === "full") return viewportSize(mode);
|
|
138
|
-
if (point === "fit"
|
|
175
|
+
if (point === "fit" || point === "content") {
|
|
176
|
+
return Math.max(0, measureFit?.() ?? 0);
|
|
177
|
+
}
|
|
139
178
|
const pctMatch = point.match(PERCENT);
|
|
140
179
|
if (pctMatch) {
|
|
141
180
|
const pct = parseFloat(pctMatch[1]) / 100;
|
|
@@ -323,14 +362,17 @@ function installAutoCollapse(deps) {
|
|
|
323
362
|
const fire = () => {
|
|
324
363
|
if (deps.isDestroyed()) return;
|
|
325
364
|
if (deps.isDragging()) return;
|
|
326
|
-
const
|
|
327
|
-
|
|
365
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
366
|
+
if (!active || active.size === 0) return;
|
|
367
|
+
let target = null;
|
|
368
|
+
for (const id of deps.getAllowedIds()) {
|
|
328
369
|
const snap = deps.resolveSnap(id);
|
|
329
|
-
|
|
330
|
-
|
|
370
|
+
if (!snap || snap.size <= 0) continue;
|
|
371
|
+
if (!target || snap.size < target.size) target = snap;
|
|
372
|
+
}
|
|
331
373
|
if (!target) return;
|
|
332
|
-
if (target ===
|
|
333
|
-
deps.snapTo(target);
|
|
374
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
375
|
+
deps.snapTo(target.id);
|
|
334
376
|
};
|
|
335
377
|
const reset = () => {
|
|
336
378
|
clearTimer();
|
|
@@ -341,6 +383,7 @@ function installAutoCollapse(deps) {
|
|
|
341
383
|
}, ms);
|
|
342
384
|
};
|
|
343
385
|
const unsubscribe = deps.on("snap", () => reset());
|
|
386
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
344
387
|
return () => {
|
|
345
388
|
clearTimer();
|
|
346
389
|
unsubscribe();
|
|
@@ -353,6 +396,7 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
353
396
|
for (const linked of sheets) {
|
|
354
397
|
if (linked === self) continue;
|
|
355
398
|
try {
|
|
399
|
+
if (linked.state.size === 0) continue;
|
|
356
400
|
const ids = linked.getAllowedIds();
|
|
357
401
|
const target = ids.find((id) => id !== "closed");
|
|
358
402
|
if (target && target !== linked.state.activeId) {
|
|
@@ -367,6 +411,42 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
367
411
|
}
|
|
368
412
|
|
|
369
413
|
// src/core/features/route.ts
|
|
414
|
+
var closers = [];
|
|
415
|
+
var handlerInstalled = false;
|
|
416
|
+
var suppress = 0;
|
|
417
|
+
var ensureHandler = () => {
|
|
418
|
+
if (handlerInstalled || typeof window === "undefined") return;
|
|
419
|
+
handlerInstalled = true;
|
|
420
|
+
window.addEventListener("popstate", () => {
|
|
421
|
+
if (suppress > 0) {
|
|
422
|
+
suppress -= 1;
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
let target = null;
|
|
426
|
+
for (let i = closers.length - 1; i >= 0; i -= 1) {
|
|
427
|
+
const c = closers[i];
|
|
428
|
+
if (!c.isOpen()) continue;
|
|
429
|
+
if (!target) target = c;
|
|
430
|
+
if (c.isTop()) {
|
|
431
|
+
target = c;
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (!target) return;
|
|
436
|
+
target.consumed = true;
|
|
437
|
+
const idx = closers.indexOf(target);
|
|
438
|
+
if (idx !== -1) closers.splice(idx, 1);
|
|
439
|
+
target.close();
|
|
440
|
+
});
|
|
441
|
+
};
|
|
442
|
+
var programmaticBack = () => {
|
|
443
|
+
suppress += 1;
|
|
444
|
+
try {
|
|
445
|
+
history.back();
|
|
446
|
+
} catch {
|
|
447
|
+
suppress = Math.max(0, suppress - 1);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
370
450
|
function installRoute(deps) {
|
|
371
451
|
if (typeof window === "undefined") {
|
|
372
452
|
return () => {
|
|
@@ -376,82 +456,81 @@ function installRoute(deps) {
|
|
|
376
456
|
return () => {
|
|
377
457
|
};
|
|
378
458
|
}
|
|
379
|
-
let
|
|
380
|
-
let
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
459
|
+
let pushed = false;
|
|
460
|
+
let closer = null;
|
|
461
|
+
const teardownEntry = () => {
|
|
462
|
+
if (closer) {
|
|
463
|
+
const idx = closers.indexOf(closer);
|
|
464
|
+
if (idx !== -1) closers.splice(idx, 1);
|
|
465
|
+
}
|
|
466
|
+
const wasConsumed = closer?.consumed ?? false;
|
|
467
|
+
closer = null;
|
|
468
|
+
if (pushed && !wasConsumed) {
|
|
469
|
+
pushed = false;
|
|
470
|
+
programmaticBack();
|
|
471
|
+
} else {
|
|
472
|
+
pushed = false;
|
|
389
473
|
}
|
|
390
474
|
};
|
|
391
475
|
const onOpen = () => {
|
|
392
|
-
if (
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
window.addEventListener("popstate", onPop);
|
|
408
|
-
detachPopstate = () => window.removeEventListener("popstate", onPop);
|
|
409
|
-
} else if (deps.closeOnBack && !detachPopstate) {
|
|
410
|
-
try {
|
|
476
|
+
if (closer) return;
|
|
477
|
+
closer = {
|
|
478
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
479
|
+
isTop: () => deps.isTopSheet(),
|
|
480
|
+
close: () => void deps.close(),
|
|
481
|
+
consumed: false
|
|
482
|
+
};
|
|
483
|
+
ensureHandler();
|
|
484
|
+
closers.push(closer);
|
|
485
|
+
try {
|
|
486
|
+
if (deps.routedTo !== void 0) {
|
|
487
|
+
history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
|
|
488
|
+
} else {
|
|
411
489
|
history.pushState({ __bsSheet: deps.sheetId }, "");
|
|
412
|
-
closeOnBackPushed = true;
|
|
413
|
-
} catch {
|
|
414
490
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const state = history.state;
|
|
419
|
-
if (state?.__bsSheet !== deps.sheetId) closeOnBackPushed = false;
|
|
420
|
-
void deps.close();
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
window.addEventListener("popstate", onPop);
|
|
424
|
-
detachPopstate = () => window.removeEventListener("popstate", onPop);
|
|
425
|
-
}
|
|
426
|
-
};
|
|
427
|
-
const onClose = () => {
|
|
428
|
-
detachPopstate?.();
|
|
429
|
-
detachPopstate = null;
|
|
430
|
-
if (routePushed) {
|
|
431
|
-
routePushed = false;
|
|
432
|
-
if (deps.routedTo !== void 0) popOurMarker("__bsRouted", deps.routedTo);
|
|
433
|
-
}
|
|
434
|
-
if (closeOnBackPushed) {
|
|
435
|
-
closeOnBackPushed = false;
|
|
436
|
-
popOurMarker("__bsSheet", deps.sheetId);
|
|
491
|
+
pushed = true;
|
|
492
|
+
} catch {
|
|
493
|
+
pushed = false;
|
|
437
494
|
}
|
|
438
495
|
};
|
|
439
496
|
const unsubscribeOpen = deps.on("open", onOpen);
|
|
440
|
-
const unsubscribeClose = deps.on("close",
|
|
497
|
+
const unsubscribeClose = deps.on("close", teardownEntry);
|
|
441
498
|
if (deps.getSize() > 0) onOpen();
|
|
442
499
|
return () => {
|
|
443
500
|
unsubscribeOpen();
|
|
444
501
|
unsubscribeClose();
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
502
|
+
teardownEntry();
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
function installRouteChange(deps) {
|
|
506
|
+
if (typeof window === "undefined" || typeof history === "undefined") {
|
|
507
|
+
return () => {
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
const onChange = () => {
|
|
511
|
+
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
512
|
+
void deps.close();
|
|
513
|
+
};
|
|
514
|
+
const wrap = (key) => {
|
|
515
|
+
const original = history[key];
|
|
516
|
+
const patched = function(...args) {
|
|
517
|
+
original.apply(this, args);
|
|
518
|
+
onChange();
|
|
519
|
+
};
|
|
520
|
+
history[key] = patched;
|
|
521
|
+
return () => {
|
|
522
|
+
if (history[key] === patched) {
|
|
523
|
+
history[key] = original;
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
};
|
|
527
|
+
window.addEventListener("popstate", onChange);
|
|
528
|
+
const restorePush = wrap("pushState");
|
|
529
|
+
const restoreReplace = wrap("replaceState");
|
|
530
|
+
return () => {
|
|
531
|
+
window.removeEventListener("popstate", onChange);
|
|
532
|
+
restorePush();
|
|
533
|
+
restoreReplace();
|
|
455
534
|
};
|
|
456
535
|
}
|
|
457
536
|
|
|
@@ -553,13 +632,17 @@ function installResizeObserver(deps) {
|
|
|
553
632
|
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
554
633
|
deps.setMaxAxisSize(viewportSize2);
|
|
555
634
|
}
|
|
635
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
556
636
|
deps.cancelInFlight();
|
|
557
637
|
deps.newCycle();
|
|
558
638
|
const current = deps.resolveActiveSnap();
|
|
559
639
|
const newMax = deps.getMaxAxisSize();
|
|
560
640
|
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
561
641
|
deps.setSize(targetSize);
|
|
562
|
-
if (current && !deps.isDragging())
|
|
642
|
+
if (current && !deps.isDragging()) {
|
|
643
|
+
deps.applySize(targetSize);
|
|
644
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
645
|
+
}
|
|
563
646
|
};
|
|
564
647
|
let resizeObserver = null;
|
|
565
648
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -674,8 +757,88 @@ function devWarn(...args) {
|
|
|
674
757
|
}
|
|
675
758
|
}
|
|
676
759
|
|
|
760
|
+
// src/core/primitives/overlay-position.ts
|
|
761
|
+
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
762
|
+
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
763
|
+
switch (mode) {
|
|
764
|
+
case "bottom":
|
|
765
|
+
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
766
|
+
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
767
|
+
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
768
|
+
case "top":
|
|
769
|
+
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
770
|
+
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
771
|
+
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
772
|
+
case "left":
|
|
773
|
+
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
774
|
+
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
775
|
+
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
776
|
+
case "right":
|
|
777
|
+
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
778
|
+
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
779
|
+
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
function applyOverlayPosition(ws, mode, position, inset) {
|
|
783
|
+
switch (position) {
|
|
784
|
+
case "top-left":
|
|
785
|
+
ws.top = inset;
|
|
786
|
+
ws.left = inset;
|
|
787
|
+
break;
|
|
788
|
+
case "top-center":
|
|
789
|
+
ws.top = inset;
|
|
790
|
+
ws.left = "50%";
|
|
791
|
+
ws.transform = "translateX(-50%)";
|
|
792
|
+
break;
|
|
793
|
+
case "top-right":
|
|
794
|
+
ws.top = inset;
|
|
795
|
+
ws.right = inset;
|
|
796
|
+
break;
|
|
797
|
+
case "center-left":
|
|
798
|
+
ws.top = "50%";
|
|
799
|
+
ws.left = inset;
|
|
800
|
+
ws.transform = "translateY(-50%)";
|
|
801
|
+
break;
|
|
802
|
+
case "center":
|
|
803
|
+
ws.top = "50%";
|
|
804
|
+
ws.left = "50%";
|
|
805
|
+
ws.transform = "translate(-50%, -50%)";
|
|
806
|
+
break;
|
|
807
|
+
case "center-right":
|
|
808
|
+
ws.top = "50%";
|
|
809
|
+
ws.right = inset;
|
|
810
|
+
ws.transform = "translateY(-50%)";
|
|
811
|
+
break;
|
|
812
|
+
case "bottom-left":
|
|
813
|
+
ws.bottom = inset;
|
|
814
|
+
ws.left = inset;
|
|
815
|
+
break;
|
|
816
|
+
case "bottom-center":
|
|
817
|
+
ws.bottom = inset;
|
|
818
|
+
ws.left = "50%";
|
|
819
|
+
ws.transform = "translateX(-50%)";
|
|
820
|
+
break;
|
|
821
|
+
case "bottom-right":
|
|
822
|
+
ws.bottom = inset;
|
|
823
|
+
ws.right = inset;
|
|
824
|
+
break;
|
|
825
|
+
case "sheet-top-left":
|
|
826
|
+
case "sheet-top-center":
|
|
827
|
+
case "sheet-top-right": {
|
|
828
|
+
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
829
|
+
if (style.top !== void 0) ws.top = style.top;
|
|
830
|
+
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
831
|
+
if (style.left !== void 0) ws.left = style.left;
|
|
832
|
+
if (style.right !== void 0) ws.right = style.right;
|
|
833
|
+
if (style.transform !== void 0) ws.transform = style.transform;
|
|
834
|
+
break;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
677
839
|
// src/core/controllers/scrim-controller.ts
|
|
678
840
|
var VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
|
|
841
|
+
var DEFAULT_SCRIM_DIM = "rgba(0, 0, 0, 0.4)";
|
|
679
842
|
var ScrimController = class {
|
|
680
843
|
constructor(deps, opts) {
|
|
681
844
|
__publicField(this, "screenComponent");
|
|
@@ -686,6 +849,8 @@ var ScrimController = class {
|
|
|
686
849
|
__publicField(this, "getAllowedIds");
|
|
687
850
|
__publicField(this, "getResolvedSnaps");
|
|
688
851
|
__publicField(this, "snapToFn");
|
|
852
|
+
__publicField(this, "closeFn");
|
|
853
|
+
__publicField(this, "scrimInteractive", false);
|
|
689
854
|
__publicField(this, "scrimMode");
|
|
690
855
|
__publicField(this, "backdropRange");
|
|
691
856
|
__publicField(this, "screenRange");
|
|
@@ -706,14 +871,17 @@ var ScrimController = class {
|
|
|
706
871
|
this.getAllowedIds = deps.getAllowedIds;
|
|
707
872
|
this.getResolvedSnaps = deps.getResolvedSnaps;
|
|
708
873
|
this.snapToFn = deps.snapTo;
|
|
874
|
+
this.closeFn = deps.close;
|
|
709
875
|
this.scrimMode = opts.scrimMode ?? "full";
|
|
710
876
|
const preset = opts.scrimPreset ? SCRIM_PRESETS[opts.scrimPreset] : null;
|
|
711
877
|
this.backdropRange = opts.backdropRange ?? preset?.range ?? [0, 1];
|
|
712
878
|
this.screenRange = opts.screenRange ?? preset?.range ?? [0, 1];
|
|
713
879
|
this.scrimTapToCloseEnabled = opts.scrimTapToClose ?? false;
|
|
880
|
+
const explicitColor = opts.scrimColor ?? preset?.color;
|
|
881
|
+
const effectiveColor = explicitColor ?? (this.scrimMode !== "off" && !this.backdrop ? DEFAULT_SCRIM_DIM : void 0);
|
|
714
882
|
if (this.screenComponent) {
|
|
715
883
|
this.applyScrimStyles({
|
|
716
|
-
color:
|
|
884
|
+
color: effectiveColor,
|
|
717
885
|
blur: opts.scrimBlur ?? preset?.blur,
|
|
718
886
|
interactive: opts.scrimInteractive ?? preset?.interactive ?? false
|
|
719
887
|
});
|
|
@@ -847,11 +1015,15 @@ var ScrimController = class {
|
|
|
847
1015
|
}
|
|
848
1016
|
const onClick = () => {
|
|
849
1017
|
if (this.isDestroyed()) return;
|
|
1018
|
+
if (this.closeFn) {
|
|
1019
|
+
this.closeFn();
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
850
1022
|
const allowed = this.getAllowedIds();
|
|
851
1023
|
const snaps = this.getResolvedSnaps();
|
|
852
1024
|
const fallback = allowed.find((id) => {
|
|
853
1025
|
const snap = findById(id, snaps);
|
|
854
|
-
return snap !== null && snap.size
|
|
1026
|
+
return snap !== null && snap.size === 0;
|
|
855
1027
|
});
|
|
856
1028
|
if (fallback) this.snapToFn(fallback);
|
|
857
1029
|
};
|
|
@@ -868,6 +1040,7 @@ var ScrimController = class {
|
|
|
868
1040
|
if (this.isDestroyed()) return;
|
|
869
1041
|
if (enabled === this.scrimEnabled) return;
|
|
870
1042
|
this.scrimEnabled = enabled;
|
|
1043
|
+
this.invalidateOpacityCache();
|
|
871
1044
|
if (!enabled) {
|
|
872
1045
|
this.savedScrimRanges = {
|
|
873
1046
|
screen: this.screenRange,
|
|
@@ -891,7 +1064,12 @@ var ScrimController = class {
|
|
|
891
1064
|
blur: cfg.blur ?? null,
|
|
892
1065
|
interactive: cfg.interactive
|
|
893
1066
|
});
|
|
894
|
-
this.
|
|
1067
|
+
if (!this.scrimEnabled && this.savedScrimRanges) {
|
|
1068
|
+
this.savedScrimRanges = { screen: cfg.range, backdrop: cfg.range };
|
|
1069
|
+
} else {
|
|
1070
|
+
this.screenRange = cfg.range;
|
|
1071
|
+
this.backdropRange = cfg.range;
|
|
1072
|
+
}
|
|
895
1073
|
}
|
|
896
1074
|
const noop = () => {
|
|
897
1075
|
};
|
|
@@ -941,59 +1119,7 @@ var ScrimController = class {
|
|
|
941
1119
|
wrapper.className = "bs-scrim-overlay";
|
|
942
1120
|
const ws = wrapper.style;
|
|
943
1121
|
ws.position = "absolute";
|
|
944
|
-
|
|
945
|
-
case "top-left":
|
|
946
|
-
ws.top = inset;
|
|
947
|
-
ws.left = inset;
|
|
948
|
-
break;
|
|
949
|
-
case "top-center":
|
|
950
|
-
ws.top = inset;
|
|
951
|
-
ws.left = "50%";
|
|
952
|
-
ws.transform = "translateX(-50%)";
|
|
953
|
-
break;
|
|
954
|
-
case "top-right":
|
|
955
|
-
ws.top = inset;
|
|
956
|
-
ws.right = inset;
|
|
957
|
-
break;
|
|
958
|
-
case "center-left":
|
|
959
|
-
ws.top = "50%";
|
|
960
|
-
ws.left = inset;
|
|
961
|
-
ws.transform = "translateY(-50%)";
|
|
962
|
-
break;
|
|
963
|
-
case "center":
|
|
964
|
-
ws.top = "50%";
|
|
965
|
-
ws.left = "50%";
|
|
966
|
-
ws.transform = "translate(-50%, -50%)";
|
|
967
|
-
break;
|
|
968
|
-
case "center-right":
|
|
969
|
-
ws.top = "50%";
|
|
970
|
-
ws.right = inset;
|
|
971
|
-
ws.transform = "translateY(-50%)";
|
|
972
|
-
break;
|
|
973
|
-
case "bottom-left":
|
|
974
|
-
ws.bottom = inset;
|
|
975
|
-
ws.left = inset;
|
|
976
|
-
break;
|
|
977
|
-
case "bottom-center":
|
|
978
|
-
ws.bottom = inset;
|
|
979
|
-
ws.left = "50%";
|
|
980
|
-
ws.transform = "translateX(-50%)";
|
|
981
|
-
break;
|
|
982
|
-
case "bottom-right":
|
|
983
|
-
ws.bottom = inset;
|
|
984
|
-
ws.right = inset;
|
|
985
|
-
break;
|
|
986
|
-
case "sheet-top-left":
|
|
987
|
-
case "sheet-top-center":
|
|
988
|
-
case "sheet-top-right":
|
|
989
|
-
applySheetAnchoredPosition(
|
|
990
|
-
ws,
|
|
991
|
-
this.mode,
|
|
992
|
-
position,
|
|
993
|
-
inset
|
|
994
|
-
);
|
|
995
|
-
break;
|
|
996
|
-
}
|
|
1122
|
+
applyOverlayPosition(ws, this.mode, position, inset);
|
|
997
1123
|
if (interactive) {
|
|
998
1124
|
ws.pointerEvents = "auto";
|
|
999
1125
|
}
|
|
@@ -1052,6 +1178,7 @@ var ScrimController = class {
|
|
|
1052
1178
|
}
|
|
1053
1179
|
}
|
|
1054
1180
|
if (opts.interactive !== void 0) {
|
|
1181
|
+
this.scrimInteractive = opts.interactive;
|
|
1055
1182
|
s.pointerEvents = opts.interactive ? "auto" : "none";
|
|
1056
1183
|
}
|
|
1057
1184
|
}
|
|
@@ -1066,38 +1193,9 @@ var ScrimController = class {
|
|
|
1066
1193
|
const s = this.screenComponent.style;
|
|
1067
1194
|
s.position = "fixed";
|
|
1068
1195
|
s.inset = insetByMode[this.mode];
|
|
1069
|
-
s.pointerEvents = "none";
|
|
1196
|
+
s.pointerEvents = this.scrimInteractive || this.scrimTapToCloseEnabled ? "auto" : "none";
|
|
1070
1197
|
}
|
|
1071
1198
|
};
|
|
1072
|
-
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
1073
|
-
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
1074
|
-
switch (mode) {
|
|
1075
|
-
case "bottom":
|
|
1076
|
-
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
1077
|
-
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
1078
|
-
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1079
|
-
case "top":
|
|
1080
|
-
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
1081
|
-
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
1082
|
-
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1083
|
-
case "left":
|
|
1084
|
-
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
1085
|
-
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
1086
|
-
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1087
|
-
case "right":
|
|
1088
|
-
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
1089
|
-
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
1090
|
-
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
function applySheetAnchoredPosition(ws, mode, position, inset) {
|
|
1094
|
-
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
1095
|
-
if (style.top !== void 0) ws.top = style.top;
|
|
1096
|
-
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
1097
|
-
if (style.left !== void 0) ws.left = style.left;
|
|
1098
|
-
if (style.right !== void 0) ws.right = style.right;
|
|
1099
|
-
if (style.transform !== void 0) ws.transform = style.transform;
|
|
1100
|
-
}
|
|
1101
1199
|
|
|
1102
1200
|
// src/core/animation/animation.ts
|
|
1103
1201
|
var easeOutBack = (t) => {
|
|
@@ -1149,6 +1247,10 @@ var tween = ({
|
|
|
1149
1247
|
promise
|
|
1150
1248
|
};
|
|
1151
1249
|
};
|
|
1250
|
+
var prefersReducedMotion = () => {
|
|
1251
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1252
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1253
|
+
};
|
|
1152
1254
|
|
|
1153
1255
|
// src/core/animation/spring.ts
|
|
1154
1256
|
var DEFAULT_SPRING = {
|
|
@@ -1179,14 +1281,20 @@ var runSpring = ({
|
|
|
1179
1281
|
if (cancelled) return;
|
|
1180
1282
|
const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
|
|
1181
1283
|
lastTime = now;
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1284
|
+
const steps = Math.max(1, Math.ceil(dt * 240));
|
|
1285
|
+
const subDt = dt / steps;
|
|
1286
|
+
let stepsLeft = steps;
|
|
1184
1287
|
while (stepsLeft-- > 0) {
|
|
1185
1288
|
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1186
1289
|
const accel = force / cfg.mass;
|
|
1187
1290
|
v += accel * subDt;
|
|
1188
1291
|
x += v * subDt;
|
|
1189
1292
|
}
|
|
1293
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1294
|
+
onUpdate(to, 0);
|
|
1295
|
+
resolve();
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1190
1298
|
onUpdate(x, v);
|
|
1191
1299
|
const isAtRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1192
1300
|
if (isAtRest) {
|
|
@@ -1361,9 +1469,13 @@ var isVisible = (el) => {
|
|
|
1361
1469
|
var focusables = (root) => Array.from(root.querySelectorAll(FOCUSABLE)).filter(
|
|
1362
1470
|
(el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
|
|
1363
1471
|
);
|
|
1472
|
+
var trapStack = [];
|
|
1364
1473
|
var installFocusTrap = (container, options = {}) => {
|
|
1365
1474
|
if (typeof document === "undefined") return () => {
|
|
1366
1475
|
};
|
|
1476
|
+
const token = {};
|
|
1477
|
+
trapStack.push(token);
|
|
1478
|
+
const isActive = () => trapStack[trapStack.length - 1] === token;
|
|
1367
1479
|
const previouslyFocused = document.activeElement;
|
|
1368
1480
|
const focusInitial = () => {
|
|
1369
1481
|
const initial = typeof options.initialFocus === "string" ? container.querySelector(options.initialFocus) : options.initialFocus ?? focusables(container)[0] ?? container;
|
|
@@ -1371,6 +1483,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1371
1483
|
};
|
|
1372
1484
|
focusInitial();
|
|
1373
1485
|
const handleKey = (e) => {
|
|
1486
|
+
if (!isActive()) return;
|
|
1374
1487
|
if (e.key === "Escape" && options.onEscape) {
|
|
1375
1488
|
options.onEscape();
|
|
1376
1489
|
return;
|
|
@@ -1393,6 +1506,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1393
1506
|
}
|
|
1394
1507
|
};
|
|
1395
1508
|
const handleFocusIn = (e) => {
|
|
1509
|
+
if (!isActive()) return;
|
|
1396
1510
|
const target = e.target;
|
|
1397
1511
|
if (target && !container.contains(target)) {
|
|
1398
1512
|
const list = focusables(container);
|
|
@@ -1405,6 +1519,8 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1405
1519
|
return () => {
|
|
1406
1520
|
if (released) return;
|
|
1407
1521
|
released = true;
|
|
1522
|
+
const idx = trapStack.indexOf(token);
|
|
1523
|
+
if (idx !== -1) trapStack.splice(idx, 1);
|
|
1408
1524
|
document.removeEventListener("keydown", handleKey, true);
|
|
1409
1525
|
document.removeEventListener("focusin", handleFocusIn, true);
|
|
1410
1526
|
if (previouslyFocused && document.contains(previouslyFocused)) {
|
|
@@ -1460,11 +1576,17 @@ function createInertSiblings(rootProvider) {
|
|
|
1460
1576
|
return {
|
|
1461
1577
|
apply() {
|
|
1462
1578
|
if (typeof document === "undefined") return;
|
|
1463
|
-
|
|
1464
|
-
|
|
1579
|
+
let top = rootProvider();
|
|
1580
|
+
while (top.parentElement && top.parentElement !== document.body) {
|
|
1581
|
+
top = top.parentElement;
|
|
1582
|
+
}
|
|
1583
|
+
const parent = top.parentElement ?? document.body;
|
|
1465
1584
|
for (const child of Array.from(parent.children)) {
|
|
1466
|
-
if (child ===
|
|
1585
|
+
if (child === top) continue;
|
|
1467
1586
|
if (child.hasAttribute("inert")) continue;
|
|
1587
|
+
if (child.classList.contains("bs-backdrop") || child.classList.contains("bs-screen") || child.classList.contains("bs-root")) {
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1468
1590
|
child.setAttribute("inert", "");
|
|
1469
1591
|
tracked.push(child);
|
|
1470
1592
|
}
|
|
@@ -1480,7 +1602,6 @@ function createInertSiblings(rootProvider) {
|
|
|
1480
1602
|
var LifecycleController = class {
|
|
1481
1603
|
constructor(deps, opts) {
|
|
1482
1604
|
__publicField(this, "element");
|
|
1483
|
-
__publicField(this, "closeFn");
|
|
1484
1605
|
__publicField(this, "focusTrapEnabled");
|
|
1485
1606
|
__publicField(this, "initialFocus");
|
|
1486
1607
|
__publicField(this, "closeOnEscape");
|
|
@@ -1494,7 +1615,6 @@ var LifecycleController = class {
|
|
|
1494
1615
|
__publicField(this, "installed", false);
|
|
1495
1616
|
__publicField(this, "destroyed", false);
|
|
1496
1617
|
this.element = deps.element;
|
|
1497
|
-
this.closeFn = deps.close;
|
|
1498
1618
|
this.focusTrapEnabled = opts.focusTrap ?? false;
|
|
1499
1619
|
this.initialFocus = opts.initialFocus;
|
|
1500
1620
|
this.closeOnEscape = opts.closeOnEscape ?? true;
|
|
@@ -1504,6 +1624,9 @@ var LifecycleController = class {
|
|
|
1504
1624
|
this.returnFocus = opts.returnFocus;
|
|
1505
1625
|
this.inertSiblings = createInertSiblings(() => this.element);
|
|
1506
1626
|
}
|
|
1627
|
+
get isInstalled() {
|
|
1628
|
+
return this.installed;
|
|
1629
|
+
}
|
|
1507
1630
|
install() {
|
|
1508
1631
|
if (this.destroyed) return;
|
|
1509
1632
|
this.installed = true;
|
|
@@ -1512,8 +1635,7 @@ var LifecycleController = class {
|
|
|
1512
1635
|
}
|
|
1513
1636
|
if (this.focusTrapEnabled && !this.releaseFocusTrap) {
|
|
1514
1637
|
this.releaseFocusTrap = installFocusTrap(this.element, {
|
|
1515
|
-
initialFocus: this.initialFocus
|
|
1516
|
-
onEscape: this.closeOnEscape ? () => void this.closeFn() : void 0
|
|
1638
|
+
initialFocus: this.initialFocus
|
|
1517
1639
|
});
|
|
1518
1640
|
}
|
|
1519
1641
|
if (this.inertSiblingsEnabled && this.shouldApplyInertSiblings()) {
|
|
@@ -1533,7 +1655,7 @@ var LifecycleController = class {
|
|
|
1533
1655
|
this.releaseScrollLock = null;
|
|
1534
1656
|
this.inertSiblings.remove();
|
|
1535
1657
|
if (this.returnFocus) {
|
|
1536
|
-
const target = typeof this.returnFocus === "function" ? this.returnFocus() : this.returnFocus;
|
|
1658
|
+
const target = typeof this.returnFocus === "function" ? this.returnFocus() : typeof this.returnFocus === "string" ? typeof document !== "undefined" ? document.querySelector(this.returnFocus) : null : this.returnFocus;
|
|
1537
1659
|
target?.focus?.();
|
|
1538
1660
|
}
|
|
1539
1661
|
}
|
|
@@ -1667,10 +1789,11 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
1667
1789
|
};
|
|
1668
1790
|
|
|
1669
1791
|
// src/core/primitives/rubber-band.ts
|
|
1670
|
-
var RUBBER_BAND_FACTOR = 0.55;
|
|
1671
1792
|
function rubberBand(overshoot, maxAxisSize) {
|
|
1672
1793
|
const cap = Math.min(maxAxisSize * 0.15, 80);
|
|
1673
|
-
|
|
1794
|
+
if (cap <= 0) return 0;
|
|
1795
|
+
const abs = Math.abs(overshoot);
|
|
1796
|
+
return Math.sign(overshoot) * (cap * abs / (abs + cap));
|
|
1674
1797
|
}
|
|
1675
1798
|
|
|
1676
1799
|
// src/core/features/soft-keyboard.ts
|
|
@@ -1699,6 +1822,7 @@ var GestureController = class {
|
|
|
1699
1822
|
__publicField(this, "dragStartSize", 0);
|
|
1700
1823
|
__publicField(this, "currentPointerKind", "touch");
|
|
1701
1824
|
__publicField(this, "keyboardDismissed", false);
|
|
1825
|
+
__publicField(this, "dragSuppressed", false);
|
|
1702
1826
|
__publicField(this, "dragPayload", { size: 0, delta: 0 });
|
|
1703
1827
|
this.deps = deps;
|
|
1704
1828
|
}
|
|
@@ -1709,6 +1833,11 @@ var GestureController = class {
|
|
|
1709
1833
|
if (this.detach) return this.detach;
|
|
1710
1834
|
this.detach = installGestures(this.deps.handle, this.deps.mode, {
|
|
1711
1835
|
onStart: (_coord, kind) => {
|
|
1836
|
+
if (this.deps.getDisableDrag?.()) {
|
|
1837
|
+
this.dragSuppressed = true;
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
this.dragSuppressed = false;
|
|
1712
1841
|
this.deps.cancelAnimation();
|
|
1713
1842
|
this.isDragging_ = true;
|
|
1714
1843
|
this.dragStartSize = this.deps.getDragContext().size;
|
|
@@ -1719,6 +1848,7 @@ var GestureController = class {
|
|
|
1719
1848
|
this.deps.emit("dragstart", { size: this.dragStartSize });
|
|
1720
1849
|
},
|
|
1721
1850
|
onMove: (delta) => {
|
|
1851
|
+
if (this.dragSuppressed) return;
|
|
1722
1852
|
const ctx = this.deps.getDragContext();
|
|
1723
1853
|
const { min, max } = ctx.range;
|
|
1724
1854
|
const maxAxis = ctx.maxAxisSize;
|
|
@@ -1742,6 +1872,10 @@ var GestureController = class {
|
|
|
1742
1872
|
}
|
|
1743
1873
|
},
|
|
1744
1874
|
onEnd: (delta, velocity, kind) => {
|
|
1875
|
+
if (this.dragSuppressed) {
|
|
1876
|
+
this.dragSuppressed = false;
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1745
1879
|
this.isDragging_ = false;
|
|
1746
1880
|
this.keyboardDismissed = false;
|
|
1747
1881
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
@@ -1752,9 +1886,17 @@ var GestureController = class {
|
|
|
1752
1886
|
this.deps.settleAfterDrag(delta, velocity, kind);
|
|
1753
1887
|
},
|
|
1754
1888
|
onCancel: () => {
|
|
1889
|
+
if (this.dragSuppressed) {
|
|
1890
|
+
this.dragSuppressed = false;
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1755
1893
|
this.isDragging_ = false;
|
|
1756
1894
|
this.keyboardDismissed = false;
|
|
1757
1895
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1896
|
+
this.deps.emit("dragend", {
|
|
1897
|
+
size: this.deps.getDragContext().size,
|
|
1898
|
+
velocity: 0
|
|
1899
|
+
});
|
|
1758
1900
|
const restoreTo = this.dragStartSize;
|
|
1759
1901
|
void this.deps.animateTo(restoreTo, 0);
|
|
1760
1902
|
}
|
|
@@ -1828,6 +1970,287 @@ function createScrollCache(deps) {
|
|
|
1828
1970
|
};
|
|
1829
1971
|
}
|
|
1830
1972
|
|
|
1973
|
+
// src/core/primitives/anchor-animations.ts
|
|
1974
|
+
var DEFAULT_DURATION3 = 200;
|
|
1975
|
+
var DEFAULT_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
1976
|
+
var PRESET_FRAMES = {
|
|
1977
|
+
fade: {
|
|
1978
|
+
enter: [{ opacity: 0 }, { opacity: 1 }],
|
|
1979
|
+
exit: [{ opacity: 1 }, { opacity: 0 }]
|
|
1980
|
+
},
|
|
1981
|
+
scale: {
|
|
1982
|
+
enter: [
|
|
1983
|
+
{ opacity: 0, transform: "scale(0.85)" },
|
|
1984
|
+
{ opacity: 1, transform: "scale(1)" }
|
|
1985
|
+
],
|
|
1986
|
+
exit: [
|
|
1987
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
1988
|
+
{ opacity: 0, transform: "scale(0.85)" }
|
|
1989
|
+
]
|
|
1990
|
+
},
|
|
1991
|
+
slide: {
|
|
1992
|
+
enter: [
|
|
1993
|
+
{ opacity: 0, transform: "translateY(10px)" },
|
|
1994
|
+
{ opacity: 1, transform: "translateY(0)" }
|
|
1995
|
+
],
|
|
1996
|
+
exit: [
|
|
1997
|
+
{ opacity: 1, transform: "translateY(0)" },
|
|
1998
|
+
{ opacity: 0, transform: "translateY(10px)" }
|
|
1999
|
+
]
|
|
2000
|
+
},
|
|
2001
|
+
pop: {
|
|
2002
|
+
enter: [
|
|
2003
|
+
{ opacity: 0, transform: "scale(0.6)", offset: 0 },
|
|
2004
|
+
{ opacity: 1, transform: "scale(1.06)", offset: 0.7 },
|
|
2005
|
+
{ opacity: 1, transform: "scale(1)", offset: 1 }
|
|
2006
|
+
],
|
|
2007
|
+
exit: [
|
|
2008
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
2009
|
+
{ opacity: 0, transform: "scale(0.6)" }
|
|
2010
|
+
]
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
var INSTANT = {
|
|
2014
|
+
finished: Promise.resolve(),
|
|
2015
|
+
cancel: () => {
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
function resolveTransitionFrames(spec, phase) {
|
|
2019
|
+
const fallback = { frames: null, duration: 0, easing: DEFAULT_EASING };
|
|
2020
|
+
if (spec === "none") return fallback;
|
|
2021
|
+
if (spec === void 0 || typeof spec === "string") {
|
|
2022
|
+
const preset2 = PRESET_FRAMES[spec ?? "fade"];
|
|
2023
|
+
return {
|
|
2024
|
+
frames: preset2[phase],
|
|
2025
|
+
duration: DEFAULT_DURATION3,
|
|
2026
|
+
easing: DEFAULT_EASING
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
const custom = phase === "enter" ? spec.enter : spec.exit;
|
|
2030
|
+
if (custom) {
|
|
2031
|
+
return {
|
|
2032
|
+
frames: custom,
|
|
2033
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
2034
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
if (spec.preset === "none") return fallback;
|
|
2038
|
+
const preset = PRESET_FRAMES[spec.preset ?? "fade"];
|
|
2039
|
+
return {
|
|
2040
|
+
frames: preset[phase],
|
|
2041
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
2042
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
function runAnchorTransition(el, spec, phase) {
|
|
2046
|
+
const respectReduced = typeof spec === "object" ? spec.respectReducedMotion !== false : true;
|
|
2047
|
+
if (respectReduced && prefersReducedMotion()) return INSTANT;
|
|
2048
|
+
const { frames, duration, easing } = resolveTransitionFrames(spec, phase);
|
|
2049
|
+
if (!frames || duration <= 0) return INSTANT;
|
|
2050
|
+
if (typeof el.animate !== "function") return INSTANT;
|
|
2051
|
+
const animation = el.animate(frames, {
|
|
2052
|
+
duration,
|
|
2053
|
+
easing,
|
|
2054
|
+
fill: "both"
|
|
2055
|
+
});
|
|
2056
|
+
const finished = animation.finished.then(() => void 0).catch(() => void 0);
|
|
2057
|
+
return {
|
|
2058
|
+
finished,
|
|
2059
|
+
cancel: () => {
|
|
2060
|
+
try {
|
|
2061
|
+
animation.cancel();
|
|
2062
|
+
} catch {
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/core/features/sheet-anchors.ts
|
|
2070
|
+
function attachAnchor(deps, opts) {
|
|
2071
|
+
const doc = deps.host.ownerDocument;
|
|
2072
|
+
const wrapper = doc.createElement("div");
|
|
2073
|
+
wrapper.className = "bs-anchor";
|
|
2074
|
+
const interactive = opts.interactive ?? true;
|
|
2075
|
+
const position = opts.position ?? "sheet-top-right";
|
|
2076
|
+
const isDock = position === "dock-bottom" || position === "dock-top";
|
|
2077
|
+
const ws = wrapper.style;
|
|
2078
|
+
ws.position = "fixed";
|
|
2079
|
+
if (isDock) {
|
|
2080
|
+
ws.left = "0";
|
|
2081
|
+
ws.right = "0";
|
|
2082
|
+
if (position === "dock-bottom") {
|
|
2083
|
+
ws.bottom = "0";
|
|
2084
|
+
} else {
|
|
2085
|
+
ws.top = "0";
|
|
2086
|
+
}
|
|
2087
|
+
} else {
|
|
2088
|
+
applyOverlayPosition(ws, deps.mode, position, opts.inset ?? "16px");
|
|
2089
|
+
}
|
|
2090
|
+
if (opts.fadeRange) {
|
|
2091
|
+
const [r0, r1] = opts.fadeRange;
|
|
2092
|
+
const span = Math.max(r1 - r0, 1e-4);
|
|
2093
|
+
ws.opacity = `clamp(0, calc((var(--bs-progress, 0) - ${r0}) / ${span}), 1)`;
|
|
2094
|
+
}
|
|
2095
|
+
wrapper.appendChild(opts.element);
|
|
2096
|
+
deps.host.appendChild(wrapper);
|
|
2097
|
+
let visible = null;
|
|
2098
|
+
let inFlight = null;
|
|
2099
|
+
const shouldShow = (state) => {
|
|
2100
|
+
if (typeof opts.showOn === "function") return opts.showOn(state);
|
|
2101
|
+
if (Array.isArray(opts.showOn)) return opts.showOn.includes(state.activeId);
|
|
2102
|
+
return isDock || state.size > 0;
|
|
2103
|
+
};
|
|
2104
|
+
const applyVisibility = (next, animate) => {
|
|
2105
|
+
if (next === visible) return;
|
|
2106
|
+
visible = next;
|
|
2107
|
+
inFlight?.cancel();
|
|
2108
|
+
inFlight = null;
|
|
2109
|
+
wrapper.style.pointerEvents = next && interactive ? "auto" : "none";
|
|
2110
|
+
if (next) {
|
|
2111
|
+
wrapper.style.visibility = "";
|
|
2112
|
+
if (animate) {
|
|
2113
|
+
inFlight = runAnchorTransition(opts.element, opts.animation, "enter");
|
|
2114
|
+
}
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
if (!animate) {
|
|
2118
|
+
wrapper.style.visibility = "hidden";
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
const handle = runAnchorTransition(opts.element, opts.animation, "exit");
|
|
2122
|
+
inFlight = handle;
|
|
2123
|
+
void handle.finished.then(() => {
|
|
2124
|
+
if (inFlight === handle && visible === false) {
|
|
2125
|
+
wrapper.style.visibility = "hidden";
|
|
2126
|
+
}
|
|
2127
|
+
});
|
|
2128
|
+
};
|
|
2129
|
+
const evaluate = (animate) => {
|
|
2130
|
+
if (deps.isDestroyed()) return;
|
|
2131
|
+
applyVisibility(shouldShow(deps.getState()), animate);
|
|
2132
|
+
};
|
|
2133
|
+
const offs = [
|
|
2134
|
+
deps.on("snap", () => evaluate(true)),
|
|
2135
|
+
deps.on("open", () => evaluate(true)),
|
|
2136
|
+
deps.on("close", () => evaluate(true))
|
|
2137
|
+
];
|
|
2138
|
+
evaluate(false);
|
|
2139
|
+
return {
|
|
2140
|
+
wrapper,
|
|
2141
|
+
detach: () => {
|
|
2142
|
+
offs.forEach((off) => off());
|
|
2143
|
+
inFlight?.cancel();
|
|
2144
|
+
inFlight = null;
|
|
2145
|
+
if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);
|
|
2146
|
+
},
|
|
2147
|
+
syncZ: (z) => {
|
|
2148
|
+
wrapper.style.zIndex = String(z);
|
|
2149
|
+
}
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
// src/core/features/scrim-stages.ts
|
|
2154
|
+
var matchesId = (def, activeId) => {
|
|
2155
|
+
if (def.for === void 0) return false;
|
|
2156
|
+
return Array.isArray(def.for) ? def.for.includes(activeId) : def.for === activeId;
|
|
2157
|
+
};
|
|
2158
|
+
var matchesRange = (def, progress) => {
|
|
2159
|
+
if (!def.forRange) return false;
|
|
2160
|
+
const [from, to] = def.forRange;
|
|
2161
|
+
return progress >= from && progress <= to;
|
|
2162
|
+
};
|
|
2163
|
+
function installScrimStages(deps, opts) {
|
|
2164
|
+
const doc = deps.host.ownerDocument;
|
|
2165
|
+
const entries = opts.stages.map((def) => {
|
|
2166
|
+
const wrapper = doc.createElement("div");
|
|
2167
|
+
wrapper.className = "bs-scrim-stage";
|
|
2168
|
+
const ws = wrapper.style;
|
|
2169
|
+
ws.position = "absolute";
|
|
2170
|
+
applyOverlayPosition(
|
|
2171
|
+
ws,
|
|
2172
|
+
deps.mode,
|
|
2173
|
+
def.position ?? opts.position ?? "center",
|
|
2174
|
+
def.inset ?? opts.inset ?? "16px"
|
|
2175
|
+
);
|
|
2176
|
+
ws.visibility = "hidden";
|
|
2177
|
+
ws.pointerEvents = "none";
|
|
2178
|
+
wrapper.appendChild(def.element);
|
|
2179
|
+
deps.host.appendChild(wrapper);
|
|
2180
|
+
return { def, wrapper, inFlight: null };
|
|
2181
|
+
});
|
|
2182
|
+
let active = null;
|
|
2183
|
+
const resolveActive = () => {
|
|
2184
|
+
const state = deps.getState();
|
|
2185
|
+
if (state.size === 0) {
|
|
2186
|
+
return entries.find((e) => matchesId(e.def, state.activeId)) ?? null;
|
|
2187
|
+
}
|
|
2188
|
+
return entries.find((e) => matchesId(e.def, state.activeId)) ?? entries.find((e) => matchesRange(e.def, state.progress)) ?? null;
|
|
2189
|
+
};
|
|
2190
|
+
const hide = (entry, animate) => {
|
|
2191
|
+
entry.inFlight?.cancel();
|
|
2192
|
+
entry.wrapper.style.pointerEvents = "none";
|
|
2193
|
+
if (!animate) {
|
|
2194
|
+
entry.inFlight = null;
|
|
2195
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2196
|
+
return;
|
|
2197
|
+
}
|
|
2198
|
+
const handle = runAnchorTransition(
|
|
2199
|
+
entry.def.element,
|
|
2200
|
+
entry.def.animation ?? opts.animation,
|
|
2201
|
+
"exit"
|
|
2202
|
+
);
|
|
2203
|
+
entry.inFlight = handle;
|
|
2204
|
+
void handle.finished.then(() => {
|
|
2205
|
+
if (entry.inFlight === handle && active !== entry) {
|
|
2206
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2209
|
+
};
|
|
2210
|
+
const show = (entry, animate) => {
|
|
2211
|
+
entry.inFlight?.cancel();
|
|
2212
|
+
entry.inFlight = null;
|
|
2213
|
+
entry.wrapper.style.visibility = "";
|
|
2214
|
+
entry.wrapper.style.pointerEvents = entry.def.interactive ?? opts.interactive ?? false ? "auto" : "none";
|
|
2215
|
+
if (animate) {
|
|
2216
|
+
entry.inFlight = runAnchorTransition(
|
|
2217
|
+
entry.def.element,
|
|
2218
|
+
entry.def.animation ?? opts.animation,
|
|
2219
|
+
"enter"
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
const update = (animate) => {
|
|
2224
|
+
if (deps.isDestroyed()) return;
|
|
2225
|
+
const next = resolveActive();
|
|
2226
|
+
if (next === active) return;
|
|
2227
|
+
const prev = active;
|
|
2228
|
+
active = next;
|
|
2229
|
+
if (prev) hide(prev, animate);
|
|
2230
|
+
if (next) show(next, animate);
|
|
2231
|
+
};
|
|
2232
|
+
const offs = [
|
|
2233
|
+
deps.on("snap", () => update(true)),
|
|
2234
|
+
deps.on("open", () => update(true)),
|
|
2235
|
+
deps.on("close", () => update(true))
|
|
2236
|
+
];
|
|
2237
|
+
if (entries.some((e) => e.def.forRange)) {
|
|
2238
|
+
offs.push(deps.on("progress", () => update(true)));
|
|
2239
|
+
}
|
|
2240
|
+
update(false);
|
|
2241
|
+
return () => {
|
|
2242
|
+
offs.forEach((off) => off());
|
|
2243
|
+
for (const entry of entries) {
|
|
2244
|
+
entry.inFlight?.cancel();
|
|
2245
|
+
entry.inFlight = null;
|
|
2246
|
+
if (entry.wrapper.parentNode) {
|
|
2247
|
+
entry.wrapper.parentNode.removeChild(entry.wrapper);
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
active = null;
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
|
|
1831
2254
|
// src/core/primitives/engine-options.ts
|
|
1832
2255
|
var DEFAULT_FLICK_VELOCITY = 0.65;
|
|
1833
2256
|
var DEFAULT_DRAG_THRESHOLD = 18;
|
|
@@ -1846,6 +2269,12 @@ function resolveEngineOptions(opts, extras) {
|
|
|
1846
2269
|
dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
|
|
1847
2270
|
rubberBandEnabled: opts.rubberBand ?? true,
|
|
1848
2271
|
closeOnBack: opts.closeOnBack ?? false,
|
|
2272
|
+
persistent: opts.persistent ?? false,
|
|
2273
|
+
disableClose: opts.disableClose ?? false,
|
|
2274
|
+
disableDrag: opts.disableDrag ?? false,
|
|
2275
|
+
closeOnRouteChange: opts.closeOnRouteChange ?? false,
|
|
2276
|
+
radius: opts.radius,
|
|
2277
|
+
maxHeight: opts.maxHeight,
|
|
1849
2278
|
initialAllowed,
|
|
1850
2279
|
initialId,
|
|
1851
2280
|
scrim: {
|
|
@@ -1872,7 +2301,8 @@ function resolveEngineOptions(opts, extras) {
|
|
|
1872
2301
|
closeOnEscape: opts.closeOnEscape,
|
|
1873
2302
|
lockBodyScroll: opts.lockBodyScroll,
|
|
1874
2303
|
inertSiblings: opts.inertSiblings,
|
|
1875
|
-
shouldApplyInertSiblings: extras?.shouldApplyInertSiblings
|
|
2304
|
+
shouldApplyInertSiblings: extras?.shouldApplyInertSiblings,
|
|
2305
|
+
returnFocus: opts.returnFocusTo
|
|
1876
2306
|
}
|
|
1877
2307
|
};
|
|
1878
2308
|
}
|
|
@@ -1917,6 +2347,11 @@ var BottomSheetEngine = class {
|
|
|
1917
2347
|
__publicField(this, "lifecycle");
|
|
1918
2348
|
__publicField(this, "closeOnBack");
|
|
1919
2349
|
__publicField(this, "routedTo");
|
|
2350
|
+
__publicField(this, "persistent");
|
|
2351
|
+
__publicField(this, "disableCloseFlag");
|
|
2352
|
+
__publicField(this, "disableDragFlag");
|
|
2353
|
+
__publicField(this, "closeOnRouteChange");
|
|
2354
|
+
__publicField(this, "maxHeightCap");
|
|
1920
2355
|
__publicField(this, "snapPointsRaw");
|
|
1921
2356
|
__publicField(this, "snaps");
|
|
1922
2357
|
__publicField(this, "activeId");
|
|
@@ -1929,6 +2364,7 @@ var BottomSheetEngine = class {
|
|
|
1929
2364
|
__publicField(this, "sizeWriteSentinel", new WriteSentinel());
|
|
1930
2365
|
__publicField(this, "progressWriteSentinel", new WriteSentinel());
|
|
1931
2366
|
__publicField(this, "isTopSheet", true);
|
|
2367
|
+
__publicField(this, "opening", false);
|
|
1932
2368
|
__publicField(this, "progressPayload", {
|
|
1933
2369
|
value: 0,
|
|
1934
2370
|
size: 0
|
|
@@ -1944,6 +2380,12 @@ var BottomSheetEngine = class {
|
|
|
1944
2380
|
__publicField(this, "linkedSheets", []);
|
|
1945
2381
|
__publicField(this, "scrollCache");
|
|
1946
2382
|
__publicField(this, "teardowns", new TeardownStack());
|
|
2383
|
+
__publicField(this, "anchors", []);
|
|
2384
|
+
__publicField(this, "anchorHost", null);
|
|
2385
|
+
__publicField(this, "stackZ", 100);
|
|
2386
|
+
__publicField(this, "detachScrimStages", null);
|
|
2387
|
+
__publicField(this, "stackEffectEnabled", false);
|
|
2388
|
+
__publicField(this, "stackEffectPrimed", false);
|
|
1947
2389
|
__publicField(this, "transformTemplate");
|
|
1948
2390
|
const resolved = resolveEngineOptions(opts, {
|
|
1949
2391
|
shouldApplyInertSiblings: () => {
|
|
@@ -1977,6 +2419,10 @@ var BottomSheetEngine = class {
|
|
|
1977
2419
|
getResolvedSnaps: () => this.snaps.getResolvedSnaps().slice(),
|
|
1978
2420
|
snapTo: (id) => {
|
|
1979
2421
|
void this.snapTo(id);
|
|
2422
|
+
},
|
|
2423
|
+
close: () => {
|
|
2424
|
+
if (!this.canDismiss()) return;
|
|
2425
|
+
void this.close("backdrop");
|
|
1980
2426
|
}
|
|
1981
2427
|
},
|
|
1982
2428
|
resolved.scrim
|
|
@@ -2000,6 +2446,11 @@ var BottomSheetEngine = class {
|
|
|
2000
2446
|
);
|
|
2001
2447
|
this.closeOnBack = resolved.closeOnBack;
|
|
2002
2448
|
this.routedTo = opts.routedTo;
|
|
2449
|
+
this.persistent = resolved.persistent;
|
|
2450
|
+
this.disableCloseFlag = resolved.disableClose;
|
|
2451
|
+
this.disableDragFlag = resolved.disableDrag;
|
|
2452
|
+
this.closeOnRouteChange = resolved.closeOnRouteChange;
|
|
2453
|
+
this.stackEffectEnabled = opts.stackEffect ?? false;
|
|
2003
2454
|
this.snapPointsRaw = opts.snapPoints;
|
|
2004
2455
|
this.persistKey = opts.persistKey;
|
|
2005
2456
|
if (opts.linkedSheets) {
|
|
@@ -2012,7 +2463,7 @@ var BottomSheetEngine = class {
|
|
|
2012
2463
|
this.snapPointsRaw,
|
|
2013
2464
|
resolved.initialAllowed,
|
|
2014
2465
|
this.mode,
|
|
2015
|
-
() => this.
|
|
2466
|
+
() => this.measureFitSize(),
|
|
2016
2467
|
(maxAxisSize) => {
|
|
2017
2468
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2018
2469
|
}
|
|
@@ -2046,6 +2497,19 @@ var BottomSheetEngine = class {
|
|
|
2046
2497
|
io.observe(this.element);
|
|
2047
2498
|
this.teardowns.add(() => io.disconnect());
|
|
2048
2499
|
}
|
|
2500
|
+
this.installFitObserver();
|
|
2501
|
+
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2502
|
+
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2503
|
+
this.applyAutoAriaLabelledBy();
|
|
2504
|
+
if (this.closeOnRouteChange) {
|
|
2505
|
+
this.teardowns.add(
|
|
2506
|
+
installRouteChange({
|
|
2507
|
+
isDestroyed: () => this.destroyed,
|
|
2508
|
+
getSize: () => this.size,
|
|
2509
|
+
close: () => this.close()
|
|
2510
|
+
})
|
|
2511
|
+
);
|
|
2512
|
+
}
|
|
2049
2513
|
if (this.persistKey) {
|
|
2050
2514
|
this.teardowns.add(installPersist(this, this.persistKey));
|
|
2051
2515
|
}
|
|
@@ -2070,7 +2534,7 @@ var BottomSheetEngine = class {
|
|
|
2070
2534
|
isTopSheet: () => this.isTopSheet,
|
|
2071
2535
|
getSize: () => this.size,
|
|
2072
2536
|
isDestroyed: () => this.destroyed,
|
|
2073
|
-
close: () => this.close(),
|
|
2537
|
+
close: () => this.close("back"),
|
|
2074
2538
|
on: (event, fn) => this.on(event, fn),
|
|
2075
2539
|
sheetId: this.id
|
|
2076
2540
|
})
|
|
@@ -2164,6 +2628,10 @@ var BottomSheetEngine = class {
|
|
|
2164
2628
|
const previousSize = this.size;
|
|
2165
2629
|
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
2166
2630
|
this.activeId = id;
|
|
2631
|
+
if (wasClosed && target.size > 0) {
|
|
2632
|
+
this.opening = true;
|
|
2633
|
+
sheetStack.promote(this.id);
|
|
2634
|
+
}
|
|
2167
2635
|
if (this.animation.viewTransitionsAvailable) {
|
|
2168
2636
|
this.currentViewTransition?.skipTransition?.();
|
|
2169
2637
|
const vt = document.startViewTransition(() => {
|
|
@@ -2178,19 +2646,26 @@ var BottomSheetEngine = class {
|
|
|
2178
2646
|
} else {
|
|
2179
2647
|
await this.animation.animateTo(target.size, velocityPxPerMs);
|
|
2180
2648
|
}
|
|
2649
|
+
this.opening = false;
|
|
2181
2650
|
externalSignal?.removeEventListener("abort", onExternalAbort);
|
|
2182
2651
|
if (signal.aborted) return;
|
|
2183
2652
|
this.scrollCache.restore(id, previousSize, target.size);
|
|
2184
2653
|
this.updateAriaSlider();
|
|
2185
|
-
this.emit("snap", {
|
|
2654
|
+
this.emit("snap", {
|
|
2655
|
+
id,
|
|
2656
|
+
size: target.size,
|
|
2657
|
+
progress: this.computeProgress(target.size)
|
|
2658
|
+
});
|
|
2186
2659
|
if (wasClosed && target.size > 0) {
|
|
2187
2660
|
this.emit("open", { id });
|
|
2188
2661
|
this.handleOpen();
|
|
2189
2662
|
notifyLinkedSheets(this.linkedSheets, this);
|
|
2663
|
+
this.emit("opened", { id });
|
|
2190
2664
|
}
|
|
2191
2665
|
if (target.size === 0) {
|
|
2192
2666
|
this.emit("close", void 0);
|
|
2193
2667
|
this.handleClose();
|
|
2668
|
+
this.emit("closed", void 0);
|
|
2194
2669
|
}
|
|
2195
2670
|
}
|
|
2196
2671
|
async dragTo(targetSize, velocityOrOpts = 0) {
|
|
@@ -2215,18 +2690,76 @@ var BottomSheetEngine = class {
|
|
|
2215
2690
|
const target = id ?? this.snaps.getAllowedIds().find((a) => a !== "closed") ?? this.activeId;
|
|
2216
2691
|
return this.snapTo(target);
|
|
2217
2692
|
}
|
|
2218
|
-
close() {
|
|
2693
|
+
close(reason = "programmatic") {
|
|
2219
2694
|
if (this.destroyed) return Promise.resolve();
|
|
2695
|
+
if (this.disableCloseFlag) return Promise.resolve();
|
|
2696
|
+
if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
|
|
2220
2697
|
const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
|
|
2221
2698
|
return this.snapTo(closedId ?? this.activeId);
|
|
2222
2699
|
}
|
|
2223
|
-
|
|
2700
|
+
canDismiss() {
|
|
2701
|
+
return !this.persistent && !this.disableCloseFlag && !this.destroyed;
|
|
2702
|
+
}
|
|
2703
|
+
isTop() {
|
|
2704
|
+
return this.isTopSheet;
|
|
2705
|
+
}
|
|
2706
|
+
depth() {
|
|
2707
|
+
return sheetStack.depthOf(this.id);
|
|
2708
|
+
}
|
|
2709
|
+
expand() {
|
|
2710
|
+
if (this.destroyed) return Promise.resolve();
|
|
2711
|
+
const ids = this.allowedIdsBySize();
|
|
2712
|
+
const target = ids[ids.length - 1];
|
|
2713
|
+
if (!target) return Promise.resolve();
|
|
2714
|
+
return this.snapTo(target);
|
|
2715
|
+
}
|
|
2716
|
+
collapse() {
|
|
2717
|
+
if (this.destroyed) return Promise.resolve();
|
|
2718
|
+
const ids = this.allowedIdsBySize();
|
|
2719
|
+
const nonZero = ids.find((id) => (this.snaps.findById(id)?.size ?? 0) > 0);
|
|
2720
|
+
const target = nonZero ?? ids[0];
|
|
2721
|
+
if (!target) return Promise.resolve();
|
|
2722
|
+
return this.snapTo(target);
|
|
2723
|
+
}
|
|
2724
|
+
setRadius(r) {
|
|
2224
2725
|
if (this.destroyed) return;
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2726
|
+
this.element.style.setProperty(
|
|
2727
|
+
"--bs-radius",
|
|
2728
|
+
typeof r === "number" ? `${r}px` : r
|
|
2729
|
+
);
|
|
2730
|
+
}
|
|
2731
|
+
setMaxHeight(h) {
|
|
2732
|
+
if (this.destroyed) return;
|
|
2733
|
+
const value = typeof h === "number" ? `${h}px` : h;
|
|
2734
|
+
const axis = layoutAxis(this.mode);
|
|
2735
|
+
this.element.style.setProperty(
|
|
2736
|
+
axis === "height" ? "maxHeight" : "maxWidth",
|
|
2737
|
+
value
|
|
2738
|
+
);
|
|
2739
|
+
if (typeof h === "number") {
|
|
2740
|
+
this.maxHeightCap = h;
|
|
2741
|
+
this.clampToMaxHeight();
|
|
2742
|
+
} else if (typeof window !== "undefined") {
|
|
2743
|
+
const probe2 = document.createElement("div");
|
|
2744
|
+
probe2.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;${axis === "height" ? "height" : "width"}:${value};`;
|
|
2745
|
+
document.body.appendChild(probe2);
|
|
2746
|
+
const measured = axis === "height" ? probe2.offsetHeight : probe2.offsetWidth;
|
|
2747
|
+
probe2.remove();
|
|
2748
|
+
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2749
|
+
this.clampToMaxHeight();
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
clampToMaxHeight() {
|
|
2753
|
+
if (this.maxHeightCap === void 0) return;
|
|
2754
|
+
if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
|
|
2755
|
+
this.snaps.setMaxAxisSize(this.maxHeightCap);
|
|
2756
|
+
}
|
|
2757
|
+
if (this.size > this.maxHeightCap && !this.gesture?.isDragging) {
|
|
2758
|
+
this.applySize(this.maxHeightCap);
|
|
2229
2759
|
}
|
|
2760
|
+
}
|
|
2761
|
+
setAllowed(ids, snap) {
|
|
2762
|
+
if (this.destroyed) return;
|
|
2230
2763
|
this.snaps.setAllowedIds(ids);
|
|
2231
2764
|
this.updateAriaSlider();
|
|
2232
2765
|
if (snap && ids.includes(snap)) {
|
|
@@ -2266,6 +2799,79 @@ var BottomSheetEngine = class {
|
|
|
2266
2799
|
setScrimOverlay(opts) {
|
|
2267
2800
|
return this.scrim.setScrimOverlay(opts);
|
|
2268
2801
|
}
|
|
2802
|
+
addAnchor(opts) {
|
|
2803
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2804
|
+
};
|
|
2805
|
+
if (!this.anchorHost) {
|
|
2806
|
+
this.anchorHost = this.rootEl ?? this.element.parentElement ?? document.body;
|
|
2807
|
+
this.anchorHost.style.setProperty("--bs-size", `${this.size}px`);
|
|
2808
|
+
this.anchorHost.style.setProperty(
|
|
2809
|
+
"--bs-progress",
|
|
2810
|
+
String(this.computeProgress(this.size))
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
const handle = attachAnchor(
|
|
2814
|
+
{
|
|
2815
|
+
mode: this.mode,
|
|
2816
|
+
host: this.anchorHost,
|
|
2817
|
+
getState: () => ({
|
|
2818
|
+
activeId: this.activeId,
|
|
2819
|
+
size: this.size,
|
|
2820
|
+
progress: this.computeProgress(this.size)
|
|
2821
|
+
}),
|
|
2822
|
+
on: (event, fn) => this.on(event, fn),
|
|
2823
|
+
isDestroyed: () => this.destroyed
|
|
2824
|
+
},
|
|
2825
|
+
opts
|
|
2826
|
+
);
|
|
2827
|
+
handle.syncZ(this.stackZ + 1);
|
|
2828
|
+
this.anchors.push(handle);
|
|
2829
|
+
const detach = () => {
|
|
2830
|
+
const idx = this.anchors.indexOf(handle);
|
|
2831
|
+
if (idx === -1) return;
|
|
2832
|
+
this.anchors.splice(idx, 1);
|
|
2833
|
+
handle.detach();
|
|
2834
|
+
};
|
|
2835
|
+
this.teardowns.add(detach);
|
|
2836
|
+
return detach;
|
|
2837
|
+
}
|
|
2838
|
+
setScrimStages(opts) {
|
|
2839
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2840
|
+
};
|
|
2841
|
+
this.detachScrimStages?.();
|
|
2842
|
+
this.detachScrimStages = null;
|
|
2843
|
+
if (!opts) return () => {
|
|
2844
|
+
};
|
|
2845
|
+
const host = this.screenComponent?.parentElement;
|
|
2846
|
+
if (!host) {
|
|
2847
|
+
console.warn(
|
|
2848
|
+
"[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
|
|
2849
|
+
);
|
|
2850
|
+
return () => {
|
|
2851
|
+
};
|
|
2852
|
+
}
|
|
2853
|
+
const detachInstalled = installScrimStages(
|
|
2854
|
+
{
|
|
2855
|
+
mode: this.mode,
|
|
2856
|
+
host,
|
|
2857
|
+
getState: () => ({
|
|
2858
|
+
activeId: this.activeId,
|
|
2859
|
+
size: this.size,
|
|
2860
|
+
progress: this.computeProgress(this.size)
|
|
2861
|
+
}),
|
|
2862
|
+
on: (event, fn) => this.on(event, fn),
|
|
2863
|
+
isDestroyed: () => this.destroyed
|
|
2864
|
+
},
|
|
2865
|
+
opts
|
|
2866
|
+
);
|
|
2867
|
+
const detach = () => {
|
|
2868
|
+
if (this.detachScrimStages === detach) this.detachScrimStages = null;
|
|
2869
|
+
detachInstalled();
|
|
2870
|
+
};
|
|
2871
|
+
this.detachScrimStages = detach;
|
|
2872
|
+
this.teardowns.add(() => this.detachScrimStages?.());
|
|
2873
|
+
return detach;
|
|
2874
|
+
}
|
|
2269
2875
|
getScrimState() {
|
|
2270
2876
|
return { mode: this.scrim.scrimMode, enabled: this.scrim.scrimEnabled };
|
|
2271
2877
|
}
|
|
@@ -2285,8 +2891,53 @@ var BottomSheetEngine = class {
|
|
|
2285
2891
|
}
|
|
2286
2892
|
this.updateAriaSlider();
|
|
2287
2893
|
}
|
|
2894
|
+
recompute() {
|
|
2895
|
+
if (this.destroyed) return;
|
|
2896
|
+
this.snaps.recompute();
|
|
2897
|
+
this.scrim.invalidateOpacityCache();
|
|
2898
|
+
if (this.gesture?.isDragging) return;
|
|
2899
|
+
const current = this.snaps.findById(this.activeId);
|
|
2900
|
+
if (current) {
|
|
2901
|
+
this.size = current.size;
|
|
2902
|
+
this.applySize(this.size);
|
|
2903
|
+
this.updateAriaSlider();
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
measureFitSize() {
|
|
2907
|
+
const vertical = layoutAxis(this.mode) === "height";
|
|
2908
|
+
const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
|
|
2909
|
+
const content = this.scrollContainer;
|
|
2910
|
+
const natural = content ? handleSize + (vertical ? content.scrollHeight : content.scrollWidth) : handleSize;
|
|
2911
|
+
if (typeof window === "undefined") return natural;
|
|
2912
|
+
const viewport = vertical ? window.innerHeight : window.innerWidth;
|
|
2913
|
+
return viewport > 0 ? Math.min(natural, viewport) : natural;
|
|
2914
|
+
}
|
|
2915
|
+
installFitObserver() {
|
|
2916
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
2917
|
+
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2918
|
+
return;
|
|
2919
|
+
const targets = [this.handle];
|
|
2920
|
+
if (this.scrollContainer && this.scrollContainer !== this.handle) {
|
|
2921
|
+
targets.push(this.scrollContainer);
|
|
2922
|
+
}
|
|
2923
|
+
let raf = 0;
|
|
2924
|
+
const ro = new ResizeObserver(() => {
|
|
2925
|
+
if (raf) return;
|
|
2926
|
+
raf = requestAnimationFrame(() => {
|
|
2927
|
+
raf = 0;
|
|
2928
|
+
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2929
|
+
this.recompute();
|
|
2930
|
+
});
|
|
2931
|
+
});
|
|
2932
|
+
for (const t of targets) ro.observe(t);
|
|
2933
|
+
this.teardowns.add(() => {
|
|
2934
|
+
ro.disconnect();
|
|
2935
|
+
if (raf) cancelAnimationFrame(raf);
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2288
2938
|
destroy() {
|
|
2289
2939
|
this.destroyed = true;
|
|
2940
|
+
this.opening = false;
|
|
2290
2941
|
this.currentAbort.abort();
|
|
2291
2942
|
this.currentViewTransition?.skipTransition?.();
|
|
2292
2943
|
this.currentViewTransition = null;
|
|
@@ -2336,6 +2987,36 @@ var BottomSheetEngine = class {
|
|
|
2336
2987
|
frozen = true;
|
|
2337
2988
|
return cancelled;
|
|
2338
2989
|
}
|
|
2990
|
+
emitBeforeClose(reason) {
|
|
2991
|
+
let cancelled = false;
|
|
2992
|
+
let frozen = false;
|
|
2993
|
+
this.emit("before-close", {
|
|
2994
|
+
reason,
|
|
2995
|
+
cancel: () => {
|
|
2996
|
+
if (frozen) {
|
|
2997
|
+
console.warn(
|
|
2998
|
+
"[BottomSheet] before-close.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
|
|
2999
|
+
);
|
|
3000
|
+
return;
|
|
3001
|
+
}
|
|
3002
|
+
cancelled = true;
|
|
3003
|
+
}
|
|
3004
|
+
});
|
|
3005
|
+
frozen = true;
|
|
3006
|
+
return cancelled;
|
|
3007
|
+
}
|
|
3008
|
+
applyAutoAriaLabelledBy() {
|
|
3009
|
+
if (typeof document === "undefined") return;
|
|
3010
|
+
if (!this.lifecycle.focusTrapEnabled) return;
|
|
3011
|
+
if (this.element.getAttribute("aria-labelledby")) return;
|
|
3012
|
+
const scope = this.handle ?? this.element;
|
|
3013
|
+
const titled = scope.querySelector("[data-bs-title]") ?? scope.querySelector("h1,h2,h3,h4,h5,h6");
|
|
3014
|
+
if (!titled) return;
|
|
3015
|
+
if (!titled.id) {
|
|
3016
|
+
titled.id = nextInstanceId("bs-title");
|
|
3017
|
+
}
|
|
3018
|
+
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3019
|
+
}
|
|
2339
3020
|
recomputeSnaps() {
|
|
2340
3021
|
const seen = /* @__PURE__ */ new Set();
|
|
2341
3022
|
for (const p of this.snapPointsRaw) {
|
|
@@ -2352,24 +3033,42 @@ var BottomSheetEngine = class {
|
|
|
2352
3033
|
getAllowedRange() {
|
|
2353
3034
|
return this.snaps.getAllowedRange();
|
|
2354
3035
|
}
|
|
3036
|
+
allowedIdsBySize() {
|
|
3037
|
+
return this.snaps.getAllowedIds().slice().sort(
|
|
3038
|
+
(a, b) => (this.snaps.findById(a)?.size ?? 0) - (this.snaps.findById(b)?.size ?? 0)
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
2355
3041
|
updateAriaSlider() {
|
|
2356
|
-
this.aria.setValue(this.
|
|
3042
|
+
this.aria.setValue(this.allowedIdsBySize(), this.activeId);
|
|
2357
3043
|
}
|
|
2358
3044
|
registerInStack() {
|
|
2359
3045
|
this.teardowns.add(sheetStack.push({
|
|
2360
3046
|
id: this.id,
|
|
2361
3047
|
setZIndex: (z) => {
|
|
3048
|
+
this.stackZ = z;
|
|
2362
3049
|
this.element.style.zIndex = String(z);
|
|
2363
3050
|
if (this.backdrop) this.backdrop.style.zIndex = String(z - 1);
|
|
3051
|
+
for (const anchor of this.anchors) anchor.syncZ(z + 1);
|
|
2364
3052
|
},
|
|
2365
3053
|
setIsTop: (isTop) => {
|
|
2366
3054
|
this.isTopSheet = isTop;
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
}
|
|
3055
|
+
},
|
|
3056
|
+
isOpen: () => this.size > 0 || this.opening,
|
|
3057
|
+
setDepth: (depth) => this.applyStackDepth(depth)
|
|
2371
3058
|
}));
|
|
2372
3059
|
}
|
|
3060
|
+
applyStackDepth(depth) {
|
|
3061
|
+
if (!this.stackEffectEnabled) return;
|
|
3062
|
+
this.element.setAttribute("data-stack-depth", String(depth));
|
|
3063
|
+
if (!this.stackEffectPrimed) {
|
|
3064
|
+
this.stackEffectPrimed = true;
|
|
3065
|
+
const isVertical = this.mode === "bottom" || this.mode === "top";
|
|
3066
|
+
this.element.style.transformOrigin = isVertical ? "50% 100%" : "0% 50%";
|
|
3067
|
+
this.element.style.transition = "scale 320ms cubic-bezier(0.29, 1.04, 0.84, 0.99)";
|
|
3068
|
+
}
|
|
3069
|
+
const scale = Math.max(1 - depth * 0.04, 0.86);
|
|
3070
|
+
this.element.style.scale = scale === 1 ? "" : String(scale);
|
|
3071
|
+
}
|
|
2373
3072
|
attach() {
|
|
2374
3073
|
this.gesture = new GestureController({
|
|
2375
3074
|
handle: this.handle,
|
|
@@ -2386,6 +3085,7 @@ var BottomSheetEngine = class {
|
|
|
2386
3085
|
buf.rubberBandEnabled = this.rubberBandEnabled;
|
|
2387
3086
|
return buf;
|
|
2388
3087
|
},
|
|
3088
|
+
getDisableDrag: () => this.disableDragFlag,
|
|
2389
3089
|
cancelAnimation: () => this.animation.cancel(),
|
|
2390
3090
|
applySize: (size) => this.applySize(size),
|
|
2391
3091
|
animateTo: (size, velocity) => this.animation.animateTo(size, velocity),
|
|
@@ -2429,7 +3129,7 @@ var BottomSheetEngine = class {
|
|
|
2429
3129
|
container: this.scrollContainer,
|
|
2430
3130
|
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2431
3131
|
isAnimating: () => this.animation.isAnimating,
|
|
2432
|
-
getAllowedIds: () => this.
|
|
3132
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2433
3133
|
getActiveId: () => this.activeId,
|
|
2434
3134
|
snapTo: (id) => {
|
|
2435
3135
|
void this.snapTo(id);
|
|
@@ -2458,13 +3158,16 @@ var BottomSheetEngine = class {
|
|
|
2458
3158
|
},
|
|
2459
3159
|
newCycle: () => {
|
|
2460
3160
|
this.newCycle();
|
|
2461
|
-
}
|
|
3161
|
+
},
|
|
3162
|
+
isAnimating: () => this.animation.isAnimating,
|
|
3163
|
+
resyncAfterCancel: () => this.resyncAfterResize()
|
|
2462
3164
|
}));
|
|
2463
3165
|
if (this.lifecycle.closeOnEscape) {
|
|
2464
3166
|
const onKey = (e) => {
|
|
2465
|
-
if (this.destroyed) return;
|
|
3167
|
+
if (this.destroyed || e.defaultPrevented) return;
|
|
3168
|
+
if (!this.canDismiss()) return;
|
|
2466
3169
|
if (e.key === "Escape" && this.isTopSheet && this.size > 0) {
|
|
2467
|
-
void this.close();
|
|
3170
|
+
void this.close("escape");
|
|
2468
3171
|
}
|
|
2469
3172
|
};
|
|
2470
3173
|
document.addEventListener("keydown", onKey);
|
|
@@ -2494,7 +3197,7 @@ var BottomSheetEngine = class {
|
|
|
2494
3197
|
handle: this.handle,
|
|
2495
3198
|
mode: this.mode,
|
|
2496
3199
|
isDestroyed: () => this.destroyed,
|
|
2497
|
-
getAllowedIds: () => this.
|
|
3200
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2498
3201
|
getActiveId: () => this.activeId,
|
|
2499
3202
|
snapTo: (id) => {
|
|
2500
3203
|
void this.snapTo(id);
|
|
@@ -2515,6 +3218,7 @@ var BottomSheetEngine = class {
|
|
|
2515
3218
|
});
|
|
2516
3219
|
if (!target) return;
|
|
2517
3220
|
const previousId = this.activeId;
|
|
3221
|
+
if (target.id === previousId && target.size === this.size) return;
|
|
2518
3222
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
2519
3223
|
const restore = this.snaps.findById(previousId);
|
|
2520
3224
|
if (restore) {
|
|
@@ -2523,21 +3227,34 @@ var BottomSheetEngine = class {
|
|
|
2523
3227
|
return;
|
|
2524
3228
|
}
|
|
2525
3229
|
const previousSize = this.size;
|
|
3230
|
+
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
2526
3231
|
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
2527
3232
|
this.activeId = target.id;
|
|
3233
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
3234
|
+
this.opening = true;
|
|
3235
|
+
sheetStack.promote(this.id);
|
|
3236
|
+
}
|
|
2528
3237
|
void this.animation.animateTo(target.size, velocity).then(() => {
|
|
3238
|
+
this.opening = false;
|
|
2529
3239
|
if (signal.aborted) return;
|
|
2530
3240
|
this.scrollCache.restore(target.id, previousSize, target.size);
|
|
2531
3241
|
this.updateAriaSlider();
|
|
2532
|
-
this.emit("snap", {
|
|
3242
|
+
this.emit("snap", {
|
|
3243
|
+
id: target.id,
|
|
3244
|
+
size: target.size,
|
|
3245
|
+
progress: this.computeProgress(target.size)
|
|
3246
|
+
});
|
|
2533
3247
|
this.haptic();
|
|
2534
|
-
if (
|
|
3248
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
2535
3249
|
this.emit("open", { id: target.id });
|
|
2536
3250
|
this.handleOpen();
|
|
3251
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
3252
|
+
this.emit("opened", { id: target.id });
|
|
2537
3253
|
}
|
|
2538
3254
|
if (target.size === 0) {
|
|
2539
3255
|
this.emit("close", void 0);
|
|
2540
3256
|
this.handleClose();
|
|
3257
|
+
this.emit("closed", void 0);
|
|
2541
3258
|
}
|
|
2542
3259
|
});
|
|
2543
3260
|
}
|
|
@@ -2559,6 +3276,9 @@ var BottomSheetEngine = class {
|
|
|
2559
3276
|
if (this.scrimParent) {
|
|
2560
3277
|
this.scrimParent.style.setProperty("--bs-size", `${size}px`);
|
|
2561
3278
|
}
|
|
3279
|
+
if (this.anchorHost && this.anchorHost !== this.scrimParent) {
|
|
3280
|
+
this.anchorHost.style.setProperty("--bs-size", `${size}px`);
|
|
3281
|
+
}
|
|
2562
3282
|
}
|
|
2563
3283
|
const progress = this.computeProgress(size);
|
|
2564
3284
|
const progressChanged = this.progressWriteSentinel.shouldWrite(
|
|
@@ -2567,6 +3287,9 @@ var BottomSheetEngine = class {
|
|
|
2567
3287
|
);
|
|
2568
3288
|
if (progressChanged) {
|
|
2569
3289
|
style.setProperty("--bs-progress", String(progress));
|
|
3290
|
+
if (this.anchorHost) {
|
|
3291
|
+
this.anchorHost.style.setProperty("--bs-progress", String(progress));
|
|
3292
|
+
}
|
|
2570
3293
|
}
|
|
2571
3294
|
this.scrim.applyOpacity(progress, progressChanged);
|
|
2572
3295
|
if (progressChanged && this.bus.listenerCount("progress") > 0) {
|
|
@@ -2581,6 +3304,7 @@ var BottomSheetEngine = class {
|
|
|
2581
3304
|
return Math.min(Math.max((size - min) / (max - min), 0), 1);
|
|
2582
3305
|
}
|
|
2583
3306
|
handleOpen() {
|
|
3307
|
+
sheetStack.promote(this.id);
|
|
2584
3308
|
try {
|
|
2585
3309
|
this.lifecycle.install();
|
|
2586
3310
|
} catch (err) {
|
|
@@ -2594,8 +3318,31 @@ var BottomSheetEngine = class {
|
|
|
2594
3318
|
});
|
|
2595
3319
|
}
|
|
2596
3320
|
}
|
|
3321
|
+
resyncAfterResize() {
|
|
3322
|
+
if (this.destroyed) return;
|
|
3323
|
+
const target = this.snaps.findById(this.activeId);
|
|
3324
|
+
if (!target) return;
|
|
3325
|
+
this.updateAriaSlider();
|
|
3326
|
+
this.emit("snap", {
|
|
3327
|
+
id: target.id,
|
|
3328
|
+
size: target.size,
|
|
3329
|
+
progress: this.computeProgress(target.size)
|
|
3330
|
+
});
|
|
3331
|
+
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3332
|
+
this.emit("open", { id: target.id });
|
|
3333
|
+
this.handleOpen();
|
|
3334
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
3335
|
+
this.emit("opened", { id: target.id });
|
|
3336
|
+
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3337
|
+
this.emit("close", void 0);
|
|
3338
|
+
this.handleClose();
|
|
3339
|
+
this.emit("closed", void 0);
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
2597
3342
|
handleClose() {
|
|
3343
|
+
this.opening = false;
|
|
2598
3344
|
this.lifecycle.release();
|
|
3345
|
+
sheetStack.update();
|
|
2599
3346
|
}
|
|
2600
3347
|
};
|
|
2601
3348
|
|
|
@@ -2643,8 +3390,23 @@ function useBottomSheet(opts) {
|
|
|
2643
3390
|
refresh();
|
|
2644
3391
|
optsRef.current.onSnap?.(payload.id);
|
|
2645
3392
|
}),
|
|
2646
|
-
engine.on("
|
|
2647
|
-
|
|
3393
|
+
engine.on("before-close", (payload) => {
|
|
3394
|
+
optsRef.current.onBeforeClose?.(payload);
|
|
3395
|
+
}),
|
|
3396
|
+
engine.on("opened", (payload) => {
|
|
3397
|
+
optsRef.current.onOpened?.(payload.id);
|
|
3398
|
+
}),
|
|
3399
|
+
engine.on("closed", () => {
|
|
3400
|
+
optsRef.current.onClosed?.();
|
|
3401
|
+
}),
|
|
3402
|
+
engine.on("dragstart", (payload) => {
|
|
3403
|
+
refresh();
|
|
3404
|
+
optsRef.current.onDragStart?.(payload);
|
|
3405
|
+
}),
|
|
3406
|
+
engine.on("dragend", (payload) => {
|
|
3407
|
+
refresh();
|
|
3408
|
+
optsRef.current.onDragEnd?.(payload);
|
|
3409
|
+
})
|
|
2648
3410
|
];
|
|
2649
3411
|
return () => {
|
|
2650
3412
|
offs.forEach((off) => off());
|
|
@@ -2682,13 +3444,34 @@ function useBottomSheet(opts) {
|
|
|
2682
3444
|
[]
|
|
2683
3445
|
);
|
|
2684
3446
|
const close = useCallback(
|
|
2685
|
-
() => engineRef.current?.close() ?? Promise.resolve(),
|
|
3447
|
+
(reason) => engineRef.current?.close(reason) ?? Promise.resolve(),
|
|
2686
3448
|
[]
|
|
2687
3449
|
);
|
|
3450
|
+
const expand = useCallback(
|
|
3451
|
+
() => engineRef.current?.expand() ?? Promise.resolve(),
|
|
3452
|
+
[]
|
|
3453
|
+
);
|
|
3454
|
+
const collapse = useCallback(
|
|
3455
|
+
() => engineRef.current?.collapse() ?? Promise.resolve(),
|
|
3456
|
+
[]
|
|
3457
|
+
);
|
|
3458
|
+
const isTop = useCallback(() => engineRef.current?.isTop() ?? false, []);
|
|
3459
|
+
const depth = useCallback(() => engineRef.current?.depth() ?? 0, []);
|
|
2688
3460
|
const setAllowed = useCallback((ids, snap) => {
|
|
2689
3461
|
engineRef.current?.setAllowed(ids, snap);
|
|
2690
3462
|
}, []);
|
|
2691
3463
|
const getEngine = useCallback(() => engineRef.current, []);
|
|
3464
|
+
const addAnchor = useCallback(
|
|
3465
|
+
(anchorOpts) => engineRef.current?.addAnchor(anchorOpts) ?? (() => {
|
|
3466
|
+
}),
|
|
3467
|
+
[]
|
|
3468
|
+
);
|
|
3469
|
+
const setScrimStages = useCallback(
|
|
3470
|
+
(stagesOpts) => engineRef.current?.setScrimStages(stagesOpts) ?? (() => {
|
|
3471
|
+
}),
|
|
3472
|
+
[]
|
|
3473
|
+
);
|
|
3474
|
+
const recompute = useCallback(() => engineRef.current?.recompute(), []);
|
|
2692
3475
|
return useMemo(
|
|
2693
3476
|
() => ({
|
|
2694
3477
|
sheetRef,
|
|
@@ -2700,11 +3483,32 @@ function useBottomSheet(opts) {
|
|
|
2700
3483
|
snapTo,
|
|
2701
3484
|
open,
|
|
2702
3485
|
close,
|
|
3486
|
+
expand,
|
|
3487
|
+
collapse,
|
|
3488
|
+
isTop,
|
|
3489
|
+
depth,
|
|
2703
3490
|
setAllowed,
|
|
3491
|
+
addAnchor,
|
|
3492
|
+
setScrimStages,
|
|
3493
|
+
recompute,
|
|
2704
3494
|
engine: engineRef.current,
|
|
2705
3495
|
getEngine
|
|
2706
3496
|
}),
|
|
2707
|
-
[
|
|
3497
|
+
[
|
|
3498
|
+
state,
|
|
3499
|
+
snapTo,
|
|
3500
|
+
open,
|
|
3501
|
+
close,
|
|
3502
|
+
expand,
|
|
3503
|
+
collapse,
|
|
3504
|
+
isTop,
|
|
3505
|
+
depth,
|
|
3506
|
+
setAllowed,
|
|
3507
|
+
addAnchor,
|
|
3508
|
+
setScrimStages,
|
|
3509
|
+
recompute,
|
|
3510
|
+
getEngine
|
|
3511
|
+
]
|
|
2708
3512
|
);
|
|
2709
3513
|
}
|
|
2710
3514
|
var useHasMounted = () => {
|
|
@@ -2724,7 +3528,14 @@ var BottomSheet = forwardRef(
|
|
|
2724
3528
|
leftButton,
|
|
2725
3529
|
rightButton,
|
|
2726
3530
|
screen,
|
|
3531
|
+
anchors,
|
|
3532
|
+
scrimStages,
|
|
2727
3533
|
onChange,
|
|
3534
|
+
onBeforeClose,
|
|
3535
|
+
onOpened,
|
|
3536
|
+
onClosed,
|
|
3537
|
+
onDragStart,
|
|
3538
|
+
onDragEnd,
|
|
2728
3539
|
ariaLabel = "Bottom sheet",
|
|
2729
3540
|
ariaLabelledBy,
|
|
2730
3541
|
noSSR = false,
|
|
@@ -2741,13 +3552,21 @@ var BottomSheet = forwardRef(
|
|
|
2741
3552
|
snapTo,
|
|
2742
3553
|
open,
|
|
2743
3554
|
close,
|
|
3555
|
+
expand,
|
|
3556
|
+
collapse,
|
|
3557
|
+
isTop,
|
|
3558
|
+
depth,
|
|
2744
3559
|
setAllowed,
|
|
2745
3560
|
getEngine
|
|
2746
|
-
} = useBottomSheet(
|
|
2747
|
-
|
|
3561
|
+
} = useBottomSheet({
|
|
3562
|
+
...engineOpts,
|
|
3563
|
+
onBeforeClose,
|
|
3564
|
+
onOpened,
|
|
3565
|
+
onClosed,
|
|
3566
|
+
onDragStart,
|
|
3567
|
+
onDragEnd
|
|
3568
|
+
});
|
|
2748
3569
|
const ariaModal = engineOpts.focusTrap === true;
|
|
2749
|
-
const allowedIds = engineOpts.allowed ?? engineOpts.snapPoints.map((p) => p.id);
|
|
2750
|
-
const activeIdx = allowedIds.indexOf(state.activeId);
|
|
2751
3570
|
const lastAnnouncedRef = useRef("");
|
|
2752
3571
|
const [announce, setAnnounce] = useState("");
|
|
2753
3572
|
useEffect(() => {
|
|
@@ -2762,21 +3581,96 @@ var BottomSheet = forwardRef(
|
|
|
2762
3581
|
snapTo,
|
|
2763
3582
|
open,
|
|
2764
3583
|
close,
|
|
3584
|
+
expand,
|
|
3585
|
+
collapse,
|
|
3586
|
+
isTop,
|
|
3587
|
+
depth,
|
|
2765
3588
|
setAllowed,
|
|
2766
3589
|
setSnapPoints: (points, allowed) => getEngine()?.setSnapPoints(points, allowed),
|
|
2767
3590
|
setScrim: (opts) => getEngine()?.setScrim(opts),
|
|
2768
3591
|
setScrimOverlay: (opts) => getEngine()?.setScrimOverlay(opts) ?? (() => {
|
|
2769
3592
|
}),
|
|
3593
|
+
addAnchor: (opts) => getEngine()?.addAnchor(opts) ?? (() => {
|
|
3594
|
+
}),
|
|
3595
|
+
setScrimStages: (opts) => getEngine()?.setScrimStages(opts) ?? (() => {
|
|
3596
|
+
}),
|
|
3597
|
+
recompute: () => getEngine()?.recompute(),
|
|
2770
3598
|
getEngine,
|
|
2771
3599
|
get state() {
|
|
2772
3600
|
return getEngine()?.state ?? state;
|
|
2773
3601
|
}
|
|
2774
3602
|
}),
|
|
2775
|
-
[
|
|
3603
|
+
[
|
|
3604
|
+
snapTo,
|
|
3605
|
+
open,
|
|
3606
|
+
close,
|
|
3607
|
+
expand,
|
|
3608
|
+
collapse,
|
|
3609
|
+
isTop,
|
|
3610
|
+
depth,
|
|
3611
|
+
setAllowed,
|
|
3612
|
+
getEngine,
|
|
3613
|
+
state
|
|
3614
|
+
]
|
|
2776
3615
|
);
|
|
2777
3616
|
useEffect(() => {
|
|
2778
3617
|
onChange?.(state);
|
|
2779
3618
|
}, [state, onChange]);
|
|
3619
|
+
const [anchorHosts, setAnchorHosts] = useState([]);
|
|
3620
|
+
const anchorsKey = anchors ? JSON.stringify(
|
|
3621
|
+
anchors.map((a) => [
|
|
3622
|
+
a.position,
|
|
3623
|
+
a.inset,
|
|
3624
|
+
Array.isArray(a.showOn) ? a.showOn : a.showOn ? "fn" : null,
|
|
3625
|
+
a.fadeRange,
|
|
3626
|
+
a.interactive,
|
|
3627
|
+
typeof a.animation === "string" ? a.animation : a.animation ? "custom" : null
|
|
3628
|
+
])
|
|
3629
|
+
) : "";
|
|
3630
|
+
useEffect(() => {
|
|
3631
|
+
const engine = getEngine();
|
|
3632
|
+
if (!engine || !anchors || anchors.length === 0) return;
|
|
3633
|
+
const hosts = [];
|
|
3634
|
+
const detachers = anchors.map((a) => {
|
|
3635
|
+
const host = document.createElement("div");
|
|
3636
|
+
hosts.push(host);
|
|
3637
|
+
const { node: _node, ...rest } = a;
|
|
3638
|
+
return engine.addAnchor({ ...rest, element: host });
|
|
3639
|
+
});
|
|
3640
|
+
setAnchorHosts(hosts);
|
|
3641
|
+
return () => {
|
|
3642
|
+
detachers.forEach((d) => d());
|
|
3643
|
+
setAnchorHosts([]);
|
|
3644
|
+
};
|
|
3645
|
+
}, [getEngine, anchorsKey]);
|
|
3646
|
+
const [stageHosts, setStageHosts] = useState([]);
|
|
3647
|
+
const stagesKey = scrimStages ? JSON.stringify(
|
|
3648
|
+
scrimStages.stages.map((s) => [
|
|
3649
|
+
s.for,
|
|
3650
|
+
s.forRange,
|
|
3651
|
+
s.position,
|
|
3652
|
+
s.inset,
|
|
3653
|
+
s.interactive,
|
|
3654
|
+
typeof s.animation === "string" ? s.animation : s.animation ? "custom" : null
|
|
3655
|
+
])
|
|
3656
|
+
) : "";
|
|
3657
|
+
useEffect(() => {
|
|
3658
|
+
const engine = getEngine();
|
|
3659
|
+
if (!engine || !scrimStages || scrimStages.stages.length === 0) return;
|
|
3660
|
+
const hosts = [];
|
|
3661
|
+
const defs = scrimStages.stages.map((s) => {
|
|
3662
|
+
const host = document.createElement("div");
|
|
3663
|
+
hosts.push(host);
|
|
3664
|
+
const { node: _node, ...rest } = s;
|
|
3665
|
+
return { ...rest, element: host };
|
|
3666
|
+
});
|
|
3667
|
+
const detach = engine.setScrimStages({ ...scrimStages, stages: defs });
|
|
3668
|
+
setStageHosts(hosts);
|
|
3669
|
+
return () => {
|
|
3670
|
+
detach();
|
|
3671
|
+
setStageHosts([]);
|
|
3672
|
+
};
|
|
3673
|
+
}, [getEngine, stagesKey]);
|
|
2780
3674
|
if (noSSR && !mounted) return null;
|
|
2781
3675
|
return /* @__PURE__ */ jsxs("div", { className: "bs-root", children: [
|
|
2782
3676
|
backdrop && /* @__PURE__ */ jsx(
|
|
@@ -2784,7 +3678,9 @@ var BottomSheet = forwardRef(
|
|
|
2784
3678
|
{
|
|
2785
3679
|
ref: backdropRef,
|
|
2786
3680
|
className: "bs-backdrop",
|
|
2787
|
-
onClick: closeOnBackdrop ? () =>
|
|
3681
|
+
onClick: closeOnBackdrop ? () => {
|
|
3682
|
+
if (getEngine()?.canDismiss()) void close("backdrop");
|
|
3683
|
+
} : void 0
|
|
2788
3684
|
}
|
|
2789
3685
|
),
|
|
2790
3686
|
/* @__PURE__ */ jsx(
|
|
@@ -2817,11 +3713,6 @@ var BottomSheet = forwardRef(
|
|
|
2817
3713
|
className: "bs-handle",
|
|
2818
3714
|
role: "slider",
|
|
2819
3715
|
tabIndex: 0,
|
|
2820
|
-
"aria-orientation": isVerticalAxis ? "vertical" : "horizontal",
|
|
2821
|
-
"aria-valuemin": 0,
|
|
2822
|
-
"aria-valuemax": Math.max(0, allowedIds.length - 1),
|
|
2823
|
-
"aria-valuenow": Math.max(0, activeIdx),
|
|
2824
|
-
"aria-valuetext": state.activeId,
|
|
2825
3716
|
"aria-label": "Resize sheet",
|
|
2826
3717
|
children: typeof header === "function" ? header(state) : header
|
|
2827
3718
|
}
|
|
@@ -2840,6 +3731,12 @@ var BottomSheet = forwardRef(
|
|
|
2840
3731
|
/* @__PURE__ */ jsx("span", { className: "bs-sr-only", role: "status", "aria-live": "polite", children: announce })
|
|
2841
3732
|
]
|
|
2842
3733
|
}
|
|
3734
|
+
),
|
|
3735
|
+
anchorHosts.map(
|
|
3736
|
+
(host, i) => anchors?.[i] ? createPortal(anchors[i].node, host) : null
|
|
3737
|
+
),
|
|
3738
|
+
stageHosts.map(
|
|
3739
|
+
(host, i) => scrimStages?.stages[i] ? createPortal(scrimStages.stages[i].node, host) : null
|
|
2843
3740
|
)
|
|
2844
3741
|
] });
|
|
2845
3742
|
}
|
|
@@ -2924,6 +3821,10 @@ var OverlayEngine = class {
|
|
|
2924
3821
|
__publicField(this, "closeOnOutsidePointerEnabled");
|
|
2925
3822
|
__publicField(this, "detachOutsidePointer", null);
|
|
2926
3823
|
__publicField(this, "detachSwipe", null);
|
|
3824
|
+
__publicField(this, "respectReducedMotionEnabled");
|
|
3825
|
+
__publicField(this, "isTop", true);
|
|
3826
|
+
__publicField(this, "backPushed", false);
|
|
3827
|
+
__publicField(this, "movedToTarget", false);
|
|
2927
3828
|
__publicField(this, "onOpenCb");
|
|
2928
3829
|
__publicField(this, "onCloseCb");
|
|
2929
3830
|
__publicField(this, "isOpen_", false);
|
|
@@ -2960,6 +3861,7 @@ var OverlayEngine = class {
|
|
|
2960
3861
|
this.mountTarget = opts.mountTo;
|
|
2961
3862
|
this.peekRaw = opts.peek;
|
|
2962
3863
|
this.closeOnOutsidePointerEnabled = opts.closeOnOutsidePointer ?? false;
|
|
3864
|
+
this.respectReducedMotionEnabled = opts.respectReducedMotion ?? true;
|
|
2963
3865
|
this.onOpenCb = opts.onOpen;
|
|
2964
3866
|
this.onCloseCb = opts.onClose;
|
|
2965
3867
|
if (this.peekRaw !== void 0 && this.edge !== "bottom") {
|
|
@@ -3007,15 +3909,17 @@ var OverlayEngine = class {
|
|
|
3007
3909
|
this.emit("before-open", void 0);
|
|
3008
3910
|
this.isOpen_ = true;
|
|
3009
3911
|
this.isAnimating_ = true;
|
|
3912
|
+
sheetStack.promote(this.id);
|
|
3010
3913
|
this.element.removeAttribute("hidden");
|
|
3011
3914
|
this.element.setAttribute("data-state", "entering");
|
|
3012
3915
|
if (this.focusTrapEnabled) {
|
|
3013
3916
|
this.element.setAttribute("aria-modal", "true");
|
|
3014
3917
|
}
|
|
3015
|
-
const
|
|
3918
|
+
const dur = this.effectiveDuration();
|
|
3919
|
+
const transitionStr = `transform ${dur}ms ${this.enterEasing}, opacity ${dur}ms ease-out`;
|
|
3016
3920
|
this.element.style.transition = transitionStr;
|
|
3017
3921
|
if (this.backdrop) {
|
|
3018
|
-
this.backdrop.style.transition = `opacity ${
|
|
3922
|
+
this.backdrop.style.transition = `opacity ${dur}ms ease-out`;
|
|
3019
3923
|
}
|
|
3020
3924
|
const cycle = ++this.cycleNonce;
|
|
3021
3925
|
return new Promise((resolve) => {
|
|
@@ -3027,7 +3931,7 @@ var OverlayEngine = class {
|
|
|
3027
3931
|
this.element.style.opacity = "1";
|
|
3028
3932
|
if (this.backdrop) {
|
|
3029
3933
|
this.backdrop.style.opacity = String(this.backdropOpacity);
|
|
3030
|
-
this.backdrop.style.pointerEvents = "auto";
|
|
3934
|
+
this.backdrop.style.pointerEvents = this.backdropOpacity > 0 ? "auto" : "none";
|
|
3031
3935
|
if (this.backdropFilter) {
|
|
3032
3936
|
this.backdrop.style.backdropFilter = this.backdropFilter;
|
|
3033
3937
|
this.backdrop.style.webkitBackdropFilter = this.backdropFilter;
|
|
@@ -3063,7 +3967,10 @@ var OverlayEngine = class {
|
|
|
3063
3967
|
});
|
|
3064
3968
|
return resolve();
|
|
3065
3969
|
}
|
|
3066
|
-
this.awaitTransition(
|
|
3970
|
+
this.awaitTransition(
|
|
3971
|
+
cycle,
|
|
3972
|
+
this.enterAnimation === "fade" ? "opacity" : "transform"
|
|
3973
|
+
).then(() => {
|
|
3067
3974
|
if (this.destroyed || cycle !== this.cycleNonce) return resolve();
|
|
3068
3975
|
this.isAnimating_ = false;
|
|
3069
3976
|
this.element.setAttribute("data-state", "open");
|
|
@@ -3080,11 +3987,14 @@ var OverlayEngine = class {
|
|
|
3080
3987
|
this.emit("before-close", void 0);
|
|
3081
3988
|
this.isOpen_ = false;
|
|
3082
3989
|
this.isAnimating_ = true;
|
|
3990
|
+
sheetStack.update();
|
|
3991
|
+
this.popBackMarker(reason);
|
|
3083
3992
|
this.element.setAttribute("data-state", "exiting");
|
|
3084
|
-
const
|
|
3993
|
+
const dur = this.effectiveDuration();
|
|
3994
|
+
const transitionStr = `transform ${dur}ms ${this.exitEasing}, opacity ${dur}ms ease-in`;
|
|
3085
3995
|
this.element.style.transition = transitionStr;
|
|
3086
3996
|
if (this.backdrop) {
|
|
3087
|
-
this.backdrop.style.transition = `opacity ${
|
|
3997
|
+
this.backdrop.style.transition = `opacity ${dur}ms ease-in`;
|
|
3088
3998
|
}
|
|
3089
3999
|
const cycle = ++this.cycleNonce;
|
|
3090
4000
|
return new Promise((resolve) => {
|
|
@@ -3095,7 +4005,7 @@ var OverlayEngine = class {
|
|
|
3095
4005
|
this.exitAnimation,
|
|
3096
4006
|
this.peekPx
|
|
3097
4007
|
);
|
|
3098
|
-
this.element.style.opacity = "0";
|
|
4008
|
+
this.element.style.opacity = this.peekPx !== void 0 ? "1" : "0";
|
|
3099
4009
|
if (this.backdrop) {
|
|
3100
4010
|
this.backdrop.style.opacity = "0";
|
|
3101
4011
|
this.backdrop.style.pointerEvents = "none";
|
|
@@ -3105,7 +4015,10 @@ var OverlayEngine = class {
|
|
|
3105
4015
|
}
|
|
3106
4016
|
}
|
|
3107
4017
|
this.releaseInteractiveListeners();
|
|
3108
|
-
this.awaitTransition(
|
|
4018
|
+
this.awaitTransition(
|
|
4019
|
+
cycle,
|
|
4020
|
+
this.exitAnimation === "fade" ? "opacity" : "transform"
|
|
4021
|
+
).then(() => {
|
|
3109
4022
|
if (this.destroyed || cycle !== this.cycleNonce) return resolve();
|
|
3110
4023
|
this.isAnimating_ = false;
|
|
3111
4024
|
if (this.peekPx === void 0) {
|
|
@@ -3133,7 +4046,11 @@ var OverlayEngine = class {
|
|
|
3133
4046
|
this.releaseInteractiveListeners();
|
|
3134
4047
|
this.releaseStackEntry?.();
|
|
3135
4048
|
this.releaseStackEntry = null;
|
|
4049
|
+
const hadOriginalParent = this.originalParent !== null;
|
|
3136
4050
|
this.restoreMount();
|
|
4051
|
+
if (this.movedToTarget && !hadOriginalParent && this.element.parentNode) {
|
|
4052
|
+
this.element.parentNode.removeChild(this.element);
|
|
4053
|
+
}
|
|
3137
4054
|
}
|
|
3138
4055
|
setBackdropOpacity(opacity) {
|
|
3139
4056
|
if (this.destroyed) return;
|
|
@@ -3234,6 +4151,36 @@ var OverlayEngine = class {
|
|
|
3234
4151
|
}
|
|
3235
4152
|
}
|
|
3236
4153
|
}
|
|
4154
|
+
if (opts.duration !== void 0) this.duration = opts.duration;
|
|
4155
|
+
if (opts.enterEasing !== void 0) this.enterEasing = opts.enterEasing;
|
|
4156
|
+
if (opts.exitEasing !== void 0) this.exitEasing = opts.exitEasing;
|
|
4157
|
+
if (opts.closeOnEscape !== void 0) {
|
|
4158
|
+
this.closeOnEscape = opts.closeOnEscape;
|
|
4159
|
+
if (!opts.closeOnEscape) {
|
|
4160
|
+
this.detachEscape?.();
|
|
4161
|
+
this.detachEscape = null;
|
|
4162
|
+
} else if (this.isOpen_) {
|
|
4163
|
+
this.installInteractiveListeners();
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
if (opts.closeOnBackdrop !== void 0) {
|
|
4167
|
+
this.closeOnBackdropEnabled = opts.closeOnBackdrop;
|
|
4168
|
+
if (!opts.closeOnBackdrop) {
|
|
4169
|
+
this.detachBackdrop?.();
|
|
4170
|
+
this.detachBackdrop = null;
|
|
4171
|
+
} else if (this.isOpen_) {
|
|
4172
|
+
this.installInteractiveListeners();
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
if (opts.closeOnOutsidePointer !== void 0) {
|
|
4176
|
+
this.closeOnOutsidePointerEnabled = opts.closeOnOutsidePointer;
|
|
4177
|
+
if (!opts.closeOnOutsidePointer) {
|
|
4178
|
+
this.detachOutsidePointer?.();
|
|
4179
|
+
this.detachOutsidePointer = null;
|
|
4180
|
+
} else if (this.isOpen_) {
|
|
4181
|
+
this.installInteractiveListeners();
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
3237
4184
|
if (opts.children !== void 0) {
|
|
3238
4185
|
if (opts.children === null) {
|
|
3239
4186
|
this.clearOverlayChildren();
|
|
@@ -3267,6 +4214,22 @@ var OverlayEngine = class {
|
|
|
3267
4214
|
emit(event, payload) {
|
|
3268
4215
|
this.bus.emit(event, payload);
|
|
3269
4216
|
}
|
|
4217
|
+
effectiveDuration() {
|
|
4218
|
+
return this.respectReducedMotionEnabled && prefersReducedMotion() ? 0 : this.duration;
|
|
4219
|
+
}
|
|
4220
|
+
popBackMarker(reason) {
|
|
4221
|
+
if (!this.backPushed) return;
|
|
4222
|
+
this.backPushed = false;
|
|
4223
|
+
if (reason === "back") return;
|
|
4224
|
+
const state = history.state;
|
|
4225
|
+
if (state && state.__bsOverlay === this.id) {
|
|
4226
|
+
try {
|
|
4227
|
+
history.back();
|
|
4228
|
+
} catch {
|
|
4229
|
+
return;
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
3270
4233
|
resolvePeekPx(raw) {
|
|
3271
4234
|
if (typeof raw === "number") return Math.max(0, raw);
|
|
3272
4235
|
try {
|
|
@@ -3288,6 +4251,7 @@ var OverlayEngine = class {
|
|
|
3288
4251
|
this.originalParent = this.element.parentNode;
|
|
3289
4252
|
this.originalNextSibling = this.element.nextSibling;
|
|
3290
4253
|
target.appendChild(this.element);
|
|
4254
|
+
this.movedToTarget = true;
|
|
3291
4255
|
this.mounted = true;
|
|
3292
4256
|
}
|
|
3293
4257
|
restoreMount() {
|
|
@@ -3321,7 +4285,7 @@ var OverlayEngine = class {
|
|
|
3321
4285
|
this.backdrop.style.willChange = "opacity";
|
|
3322
4286
|
}
|
|
3323
4287
|
}
|
|
3324
|
-
awaitTransition(cycle) {
|
|
4288
|
+
awaitTransition(cycle, property = "transform") {
|
|
3325
4289
|
return new Promise((resolve) => {
|
|
3326
4290
|
let done = false;
|
|
3327
4291
|
const finish = () => {
|
|
@@ -3336,10 +4300,10 @@ var OverlayEngine = class {
|
|
|
3336
4300
|
finish();
|
|
3337
4301
|
return;
|
|
3338
4302
|
}
|
|
3339
|
-
if (e.propertyName ===
|
|
4303
|
+
if (e.target === this.element && e.propertyName === property) finish();
|
|
3340
4304
|
};
|
|
3341
4305
|
this.element.addEventListener("transitionend", onEnd);
|
|
3342
|
-
const timer = window.setTimeout(finish, this.
|
|
4306
|
+
const timer = window.setTimeout(finish, this.effectiveDuration() + 50);
|
|
3343
4307
|
});
|
|
3344
4308
|
}
|
|
3345
4309
|
installInteractiveListeners() {
|
|
@@ -3349,7 +4313,10 @@ var OverlayEngine = class {
|
|
|
3349
4313
|
}
|
|
3350
4314
|
if (this.closeOnEscape && !this.detachEscape) {
|
|
3351
4315
|
const handler = (e) => {
|
|
3352
|
-
if (e.
|
|
4316
|
+
if (e.defaultPrevented) return;
|
|
4317
|
+
if (e.key === "Escape" && this.isOpen_ && this.isTop) {
|
|
4318
|
+
void this.close("escape");
|
|
4319
|
+
}
|
|
3353
4320
|
};
|
|
3354
4321
|
document.addEventListener("keydown", handler);
|
|
3355
4322
|
this.detachEscape = () => document.removeEventListener("keydown", handler);
|
|
@@ -3362,10 +4329,14 @@ var OverlayEngine = class {
|
|
|
3362
4329
|
if (this.closeOnBackEnabled && typeof window !== "undefined" && !this.detachHardwareBack) {
|
|
3363
4330
|
try {
|
|
3364
4331
|
history.pushState({ __bsOverlay: this.id }, "");
|
|
4332
|
+
this.backPushed = true;
|
|
3365
4333
|
} catch {
|
|
3366
4334
|
}
|
|
3367
4335
|
const onPop = () => {
|
|
3368
|
-
if (this.isOpen_
|
|
4336
|
+
if (this.isOpen_ && this.isTop) {
|
|
4337
|
+
this.backPushed = false;
|
|
4338
|
+
void this.close("back");
|
|
4339
|
+
}
|
|
3369
4340
|
};
|
|
3370
4341
|
window.addEventListener("popstate", onPop);
|
|
3371
4342
|
this.detachHardwareBack = () => window.removeEventListener("popstate", onPop);
|
|
@@ -3401,43 +4372,52 @@ var OverlayEngine = class {
|
|
|
3401
4372
|
const edge = this.edge;
|
|
3402
4373
|
const isVertical = edge === "bottom" || edge === "top";
|
|
3403
4374
|
const sign = edge === "bottom" || edge === "right" ? 1 : -1;
|
|
3404
|
-
const
|
|
3405
|
-
const velocityThreshold = this.swipeVelocityThreshold;
|
|
4375
|
+
const SLOP = 8;
|
|
3406
4376
|
let startX = 0;
|
|
3407
4377
|
let startY = 0;
|
|
3408
4378
|
let startT = 0;
|
|
4379
|
+
let tracking = false;
|
|
3409
4380
|
let dragging = false;
|
|
3410
4381
|
let pointerId = null;
|
|
4382
|
+
const previousTouchAction = el.style.touchAction;
|
|
4383
|
+
el.style.touchAction = isVertical ? "pan-x" : "pan-y";
|
|
3411
4384
|
const onDown = (e) => {
|
|
3412
4385
|
if (e.button !== void 0 && e.button !== 0) return;
|
|
3413
4386
|
pointerId = e.pointerId;
|
|
3414
4387
|
startX = e.clientX;
|
|
3415
4388
|
startY = e.clientY;
|
|
3416
4389
|
startT = performance.now();
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
try {
|
|
3420
|
-
el.setPointerCapture(e.pointerId);
|
|
3421
|
-
} catch {
|
|
3422
|
-
}
|
|
4390
|
+
tracking = true;
|
|
4391
|
+
dragging = false;
|
|
3423
4392
|
};
|
|
3424
4393
|
const onMove = (e) => {
|
|
3425
|
-
if (!
|
|
4394
|
+
if (!tracking || e.pointerId !== pointerId) return;
|
|
3426
4395
|
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
4396
|
+
if (!dragging) {
|
|
4397
|
+
if (Math.abs(delta) < SLOP) return;
|
|
4398
|
+
dragging = true;
|
|
4399
|
+
el.style.transition = "none";
|
|
4400
|
+
try {
|
|
4401
|
+
el.setPointerCapture(e.pointerId);
|
|
4402
|
+
} catch {
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
3427
4405
|
const offset = Math.max(0, sign * delta);
|
|
3428
4406
|
el.style.transform = isVertical ? `translate3d(0, ${sign * offset}px, 0)` : `translate3d(${sign * offset}px, 0, 0)`;
|
|
3429
4407
|
};
|
|
3430
4408
|
const finish = (e) => {
|
|
3431
|
-
if (!
|
|
3432
|
-
|
|
4409
|
+
if (!tracking || e.pointerId !== pointerId) return;
|
|
4410
|
+
tracking = false;
|
|
3433
4411
|
pointerId = null;
|
|
4412
|
+
if (!dragging) return;
|
|
4413
|
+
dragging = false;
|
|
3434
4414
|
const dt = performance.now() - startT || 1;
|
|
3435
4415
|
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
3436
4416
|
const offset = Math.max(0, sign * delta);
|
|
3437
4417
|
const velocity = sign * delta / dt;
|
|
3438
4418
|
const size = isVertical ? el.offsetHeight : el.offsetWidth;
|
|
3439
|
-
const past = offset > size *
|
|
3440
|
-
el.style.transition = `transform ${this.
|
|
4419
|
+
const past = offset > size * this.swipeThreshold || velocity > this.swipeVelocityThreshold;
|
|
4420
|
+
el.style.transition = `transform ${this.effectiveDuration()}ms ${this.exitEasing}`;
|
|
3441
4421
|
if (past) {
|
|
3442
4422
|
void this.close("swipe");
|
|
3443
4423
|
} else {
|
|
@@ -3449,6 +4429,7 @@ var OverlayEngine = class {
|
|
|
3449
4429
|
el.addEventListener("pointerup", finish);
|
|
3450
4430
|
el.addEventListener("pointercancel", finish);
|
|
3451
4431
|
return () => {
|
|
4432
|
+
el.style.touchAction = previousTouchAction;
|
|
3452
4433
|
el.removeEventListener("pointerdown", onDown);
|
|
3453
4434
|
el.removeEventListener("pointermove", onMove);
|
|
3454
4435
|
el.removeEventListener("pointerup", finish);
|
|
@@ -3463,10 +4444,12 @@ var OverlayEngine = class {
|
|
|
3463
4444
|
if (this.backdrop) this.backdrop.style.zIndex = String(z - 1);
|
|
3464
4445
|
},
|
|
3465
4446
|
setIsTop: (isTop) => {
|
|
4447
|
+
this.isTop = isTop;
|
|
3466
4448
|
if (this.backdrop) {
|
|
3467
4449
|
this.backdrop.style.display = isTop ? "" : "none";
|
|
3468
4450
|
}
|
|
3469
|
-
}
|
|
4451
|
+
},
|
|
4452
|
+
isOpen: () => this.isOpen_
|
|
3470
4453
|
});
|
|
3471
4454
|
}
|
|
3472
4455
|
};
|
|
@@ -3552,7 +4535,7 @@ var Overlay = forwardRef(function Overlay2(props, ref) {
|
|
|
3552
4535
|
if (openProp === void 0) return;
|
|
3553
4536
|
if (openProp && !state.isOpen) void open();
|
|
3554
4537
|
else if (!openProp && state.isOpen) void close();
|
|
3555
|
-
}, [openProp]);
|
|
4538
|
+
}, [openProp, state.isOpen]);
|
|
3556
4539
|
useEffect(() => {
|
|
3557
4540
|
onChange?.(state);
|
|
3558
4541
|
}, [state, onChange]);
|
|
@@ -3684,46 +4667,34 @@ var BottomSheetFromConfig = forwardRef(function BottomSheetFromConfig2(props, re
|
|
|
3684
4667
|
() => sheetRef.current,
|
|
3685
4668
|
[]
|
|
3686
4669
|
);
|
|
3687
|
-
const
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
const
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
const hs = handlersRef.current;
|
|
3694
|
-
if (evs.onSnap) {
|
|
3695
|
-
const fn = hs[evs.onSnap];
|
|
3696
|
-
if (typeof fn === "function") {
|
|
3697
|
-
fn(next);
|
|
3698
|
-
} else {
|
|
3699
|
-
console.warn(
|
|
3700
|
-
`[BottomSheetFromConfig] eventHandlers["${evs.onSnap}"] is not a function; onSnap is a no-op.`
|
|
3701
|
-
);
|
|
3702
|
-
}
|
|
3703
|
-
}
|
|
3704
|
-
const isClosedNext = next === "" || next === "closed";
|
|
3705
|
-
const isClosedPrev = prev === null || prev === "" || prev === "closed";
|
|
3706
|
-
if (isClosedPrev && !isClosedNext && evs.onOpen) {
|
|
3707
|
-
const fn = hs[evs.onOpen];
|
|
3708
|
-
if (typeof fn === "function") {
|
|
3709
|
-
fn(next);
|
|
3710
|
-
} else {
|
|
3711
|
-
console.warn(
|
|
3712
|
-
`[BottomSheetFromConfig] eventHandlers["${evs.onOpen}"] is not a function; onOpen is a no-op.`
|
|
3713
|
-
);
|
|
3714
|
-
}
|
|
3715
|
-
}
|
|
3716
|
-
if (!isClosedPrev && isClosedNext && evs.onClose) {
|
|
3717
|
-
const fn = hs[evs.onClose];
|
|
3718
|
-
if (typeof fn === "function") {
|
|
4670
|
+
const invoke = (key, arg) => {
|
|
4671
|
+
const evName = eventsRef.current[key];
|
|
4672
|
+
if (!evName) return;
|
|
4673
|
+
const fn = handlersRef.current[evName];
|
|
4674
|
+
if (typeof fn === "function") {
|
|
4675
|
+
if (arg === void 0) {
|
|
3719
4676
|
fn();
|
|
3720
4677
|
} else {
|
|
3721
|
-
|
|
3722
|
-
`[BottomSheetFromConfig] eventHandlers["${evs.onClose}"] is not a function; onClose is a no-op.`
|
|
3723
|
-
);
|
|
4678
|
+
fn(arg);
|
|
3724
4679
|
}
|
|
4680
|
+
} else {
|
|
4681
|
+
console.warn(
|
|
4682
|
+
`[BottomSheetFromConfig] eventHandlers["${evName}"] is not a function; ${key} is a no-op.`
|
|
4683
|
+
);
|
|
3725
4684
|
}
|
|
3726
4685
|
};
|
|
4686
|
+
const invokeRef = useRef(invoke);
|
|
4687
|
+
invokeRef.current = invoke;
|
|
4688
|
+
useEffect(() => {
|
|
4689
|
+
const engine = sheetRef.current?.getEngine();
|
|
4690
|
+
if (!engine) return;
|
|
4691
|
+
const offs = [
|
|
4692
|
+
engine.on("snap", (p) => invokeRef.current("onSnap", p.id)),
|
|
4693
|
+
engine.on("open", (p) => invokeRef.current("onOpen", p.id)),
|
|
4694
|
+
engine.on("close", () => invokeRef.current("onClose"))
|
|
4695
|
+
];
|
|
4696
|
+
return () => offs.forEach((off) => off());
|
|
4697
|
+
}, []);
|
|
3727
4698
|
return /* @__PURE__ */ jsx(
|
|
3728
4699
|
BottomSheet,
|
|
3729
4700
|
{
|
|
@@ -3739,7 +4710,6 @@ var BottomSheetFromConfig = forwardRef(function BottomSheetFromConfig2(props, re
|
|
|
3739
4710
|
closeOnBackdrop: derived.behavior.closeOnBackdrop,
|
|
3740
4711
|
lockBodyScroll: derived.behavior.lockBodyScroll,
|
|
3741
4712
|
rubberBand: derived.behavior.rubberBand,
|
|
3742
|
-
onChange: handleChange,
|
|
3743
4713
|
header: slotContent?.header,
|
|
3744
4714
|
children: slotContent?.body
|
|
3745
4715
|
}
|