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