@surdeddd/bottom-sheet 0.2.0 → 0.3.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-CAymrH-P.d.cts} +67 -1
- package/dist/{BottomSheetEngine-Df9MwBbm.d.ts → BottomSheetEngine-DcqcuudN.d.ts} +67 -1
- package/dist/element.cjs +699 -116
- package/dist/element.d.cts +7 -2
- package/dist/element.d.ts +7 -2
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +699 -116
- package/dist/index.cjs +715 -145
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +713 -146
- 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 +168 -35
- package/dist/overlay.d.cts +13 -0
- package/dist/overlay.d.ts +13 -0
- package/dist/overlay.js +168 -35
- package/dist/preact.d.cts +1 -1
- package/dist/preact.d.ts +1 -1
- package/dist/qwik.cjs +619 -119
- package/dist/qwik.d.cts +2 -2
- package/dist/qwik.d.ts +2 -2
- package/dist/qwik.js +620 -120
- package/dist/react.cjs +821 -191
- package/dist/react.d.cts +20 -3
- package/dist/react.d.ts +20 -3
- package/dist/react.js +821 -191
- package/dist/solid.cjs +656 -161
- package/dist/solid.d.cts +263 -4
- package/dist/solid.d.ts +263 -4
- package/dist/solid.js +657 -162
- package/dist/solid.source.jsx +3215 -0
- package/dist/styles.css +10 -10
- package/dist/svelte-core.cjs +3149 -0
- package/dist/svelte-core.js +3147 -0
- package/dist/svelte-src/BottomSheet.svelte +210 -0
- package/dist/svelte-src/index.js +2 -0
- package/dist/svelte.cjs +618 -124
- package/dist/svelte.d.cts +100 -0
- package/dist/svelte.d.ts +7 -3
- package/dist/svelte.js +619 -125
- package/dist/vue.cjs +612 -119
- package/dist/vue.d.cts +78 -0
- package/dist/vue.d.ts +6 -2
- package/dist/vue.js +612 -119
- package/package.json +103 -43
package/dist/vue.js
CHANGED
|
@@ -22,6 +22,18 @@ var SheetStack = class {
|
|
|
22
22
|
this.entries.splice(idx, 1);
|
|
23
23
|
this.recompute();
|
|
24
24
|
}
|
|
25
|
+
promote(id) {
|
|
26
|
+
const idx = this.entries.findIndex((e) => e.id === id);
|
|
27
|
+
if (idx === -1) return;
|
|
28
|
+
if (idx !== this.entries.length - 1) {
|
|
29
|
+
const [entry] = this.entries.splice(idx, 1);
|
|
30
|
+
this.entries.push(entry);
|
|
31
|
+
}
|
|
32
|
+
this.recompute();
|
|
33
|
+
}
|
|
34
|
+
update() {
|
|
35
|
+
this.recompute();
|
|
36
|
+
}
|
|
25
37
|
size() {
|
|
26
38
|
return this.entries.length;
|
|
27
39
|
}
|
|
@@ -29,9 +41,24 @@ var SheetStack = class {
|
|
|
29
41
|
this.entries = [];
|
|
30
42
|
}
|
|
31
43
|
recompute() {
|
|
44
|
+
let top = null;
|
|
45
|
+
const open = [];
|
|
46
|
+
for (const entry of this.entries) {
|
|
47
|
+
if (!entry.isOpen || entry.isOpen()) {
|
|
48
|
+
top = entry;
|
|
49
|
+
open.push(entry);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!top && this.entries.length > 0) {
|
|
53
|
+
top = this.entries[this.entries.length - 1];
|
|
54
|
+
}
|
|
32
55
|
this.entries.forEach((entry, i) => {
|
|
33
56
|
entry.setZIndex(BASE_Z + i * STEP);
|
|
34
|
-
entry.setIsTop(
|
|
57
|
+
entry.setIsTop(entry === top);
|
|
58
|
+
if (entry.setDepth) {
|
|
59
|
+
const openIdx = open.indexOf(entry);
|
|
60
|
+
entry.setDepth(openIdx === -1 ? 0 : open.length - 1 - openIdx);
|
|
61
|
+
}
|
|
35
62
|
});
|
|
36
63
|
}
|
|
37
64
|
};
|
|
@@ -316,14 +343,17 @@ function installAutoCollapse(deps) {
|
|
|
316
343
|
const fire = () => {
|
|
317
344
|
if (deps.isDestroyed()) return;
|
|
318
345
|
if (deps.isDragging()) return;
|
|
319
|
-
const
|
|
320
|
-
|
|
346
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
347
|
+
if (!active || active.size === 0) return;
|
|
348
|
+
let target = null;
|
|
349
|
+
for (const id of deps.getAllowedIds()) {
|
|
321
350
|
const snap = deps.resolveSnap(id);
|
|
322
|
-
|
|
323
|
-
|
|
351
|
+
if (!snap || snap.size <= 0) continue;
|
|
352
|
+
if (!target || snap.size < target.size) target = snap;
|
|
353
|
+
}
|
|
324
354
|
if (!target) return;
|
|
325
|
-
if (target ===
|
|
326
|
-
deps.snapTo(target);
|
|
355
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
356
|
+
deps.snapTo(target.id);
|
|
327
357
|
};
|
|
328
358
|
const reset = () => {
|
|
329
359
|
clearTimer();
|
|
@@ -334,6 +364,7 @@ function installAutoCollapse(deps) {
|
|
|
334
364
|
}, ms);
|
|
335
365
|
};
|
|
336
366
|
const unsubscribe = deps.on("snap", () => reset());
|
|
367
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset();
|
|
337
368
|
return () => {
|
|
338
369
|
clearTimer();
|
|
339
370
|
unsubscribe();
|
|
@@ -346,6 +377,7 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
346
377
|
for (const linked of sheets) {
|
|
347
378
|
if (linked === self) continue;
|
|
348
379
|
try {
|
|
380
|
+
if (linked.state.size === 0) continue;
|
|
349
381
|
const ids = linked.getAllowedIds();
|
|
350
382
|
const target = ids.find((id) => id !== "closed");
|
|
351
383
|
if (target && target !== linked.state.activeId) {
|
|
@@ -392,7 +424,7 @@ function installRoute(deps) {
|
|
|
392
424
|
const onPop = (event) => {
|
|
393
425
|
if (deps.isDestroyed()) return;
|
|
394
426
|
const state = event.state;
|
|
395
|
-
if (state
|
|
427
|
+
if ((!state || state.__bsRouted !== target) && deps.getSize() > 0) {
|
|
396
428
|
routePushed = false;
|
|
397
429
|
void deps.close();
|
|
398
430
|
}
|
|
@@ -546,13 +578,17 @@ function installResizeObserver(deps) {
|
|
|
546
578
|
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
547
579
|
deps.setMaxAxisSize(viewportSize2);
|
|
548
580
|
}
|
|
581
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
549
582
|
deps.cancelInFlight();
|
|
550
583
|
deps.newCycle();
|
|
551
584
|
const current = deps.resolveActiveSnap();
|
|
552
585
|
const newMax = deps.getMaxAxisSize();
|
|
553
586
|
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
554
587
|
deps.setSize(targetSize);
|
|
555
|
-
if (current && !deps.isDragging())
|
|
588
|
+
if (current && !deps.isDragging()) {
|
|
589
|
+
deps.applySize(targetSize);
|
|
590
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
591
|
+
}
|
|
556
592
|
};
|
|
557
593
|
let resizeObserver = null;
|
|
558
594
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -667,6 +703,85 @@ function devWarn(...args) {
|
|
|
667
703
|
}
|
|
668
704
|
}
|
|
669
705
|
|
|
706
|
+
// src/core/primitives/overlay-position.ts
|
|
707
|
+
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
708
|
+
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
709
|
+
switch (mode) {
|
|
710
|
+
case "bottom":
|
|
711
|
+
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
712
|
+
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
713
|
+
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
714
|
+
case "top":
|
|
715
|
+
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
716
|
+
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
717
|
+
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
718
|
+
case "left":
|
|
719
|
+
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
720
|
+
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
721
|
+
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
722
|
+
case "right":
|
|
723
|
+
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
724
|
+
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
725
|
+
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
function applyOverlayPosition(ws, mode, position, inset) {
|
|
729
|
+
switch (position) {
|
|
730
|
+
case "top-left":
|
|
731
|
+
ws.top = inset;
|
|
732
|
+
ws.left = inset;
|
|
733
|
+
break;
|
|
734
|
+
case "top-center":
|
|
735
|
+
ws.top = inset;
|
|
736
|
+
ws.left = "50%";
|
|
737
|
+
ws.transform = "translateX(-50%)";
|
|
738
|
+
break;
|
|
739
|
+
case "top-right":
|
|
740
|
+
ws.top = inset;
|
|
741
|
+
ws.right = inset;
|
|
742
|
+
break;
|
|
743
|
+
case "center-left":
|
|
744
|
+
ws.top = "50%";
|
|
745
|
+
ws.left = inset;
|
|
746
|
+
ws.transform = "translateY(-50%)";
|
|
747
|
+
break;
|
|
748
|
+
case "center":
|
|
749
|
+
ws.top = "50%";
|
|
750
|
+
ws.left = "50%";
|
|
751
|
+
ws.transform = "translate(-50%, -50%)";
|
|
752
|
+
break;
|
|
753
|
+
case "center-right":
|
|
754
|
+
ws.top = "50%";
|
|
755
|
+
ws.right = inset;
|
|
756
|
+
ws.transform = "translateY(-50%)";
|
|
757
|
+
break;
|
|
758
|
+
case "bottom-left":
|
|
759
|
+
ws.bottom = inset;
|
|
760
|
+
ws.left = inset;
|
|
761
|
+
break;
|
|
762
|
+
case "bottom-center":
|
|
763
|
+
ws.bottom = inset;
|
|
764
|
+
ws.left = "50%";
|
|
765
|
+
ws.transform = "translateX(-50%)";
|
|
766
|
+
break;
|
|
767
|
+
case "bottom-right":
|
|
768
|
+
ws.bottom = inset;
|
|
769
|
+
ws.right = inset;
|
|
770
|
+
break;
|
|
771
|
+
case "sheet-top-left":
|
|
772
|
+
case "sheet-top-center":
|
|
773
|
+
case "sheet-top-right": {
|
|
774
|
+
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
775
|
+
if (style.top !== void 0) ws.top = style.top;
|
|
776
|
+
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
777
|
+
if (style.left !== void 0) ws.left = style.left;
|
|
778
|
+
if (style.right !== void 0) ws.right = style.right;
|
|
779
|
+
if (style.transform !== void 0) ws.transform = style.transform;
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
670
785
|
// src/core/controllers/scrim-controller.ts
|
|
671
786
|
var VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
|
|
672
787
|
var ScrimController = class {
|
|
@@ -679,6 +794,8 @@ var ScrimController = class {
|
|
|
679
794
|
__publicField(this, "getAllowedIds");
|
|
680
795
|
__publicField(this, "getResolvedSnaps");
|
|
681
796
|
__publicField(this, "snapToFn");
|
|
797
|
+
__publicField(this, "closeFn");
|
|
798
|
+
__publicField(this, "scrimInteractive", false);
|
|
682
799
|
__publicField(this, "scrimMode");
|
|
683
800
|
__publicField(this, "backdropRange");
|
|
684
801
|
__publicField(this, "screenRange");
|
|
@@ -699,6 +816,7 @@ var ScrimController = class {
|
|
|
699
816
|
this.getAllowedIds = deps.getAllowedIds;
|
|
700
817
|
this.getResolvedSnaps = deps.getResolvedSnaps;
|
|
701
818
|
this.snapToFn = deps.snapTo;
|
|
819
|
+
this.closeFn = deps.close;
|
|
702
820
|
this.scrimMode = opts.scrimMode ?? "full";
|
|
703
821
|
const preset = opts.scrimPreset ? SCRIM_PRESETS[opts.scrimPreset] : null;
|
|
704
822
|
this.backdropRange = opts.backdropRange ?? preset?.range ?? [0, 1];
|
|
@@ -840,11 +958,15 @@ var ScrimController = class {
|
|
|
840
958
|
}
|
|
841
959
|
const onClick = () => {
|
|
842
960
|
if (this.isDestroyed()) return;
|
|
961
|
+
if (this.closeFn) {
|
|
962
|
+
this.closeFn();
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
843
965
|
const allowed = this.getAllowedIds();
|
|
844
966
|
const snaps = this.getResolvedSnaps();
|
|
845
967
|
const fallback = allowed.find((id) => {
|
|
846
968
|
const snap = findById(id, snaps);
|
|
847
|
-
return snap !== null && snap.size
|
|
969
|
+
return snap !== null && snap.size === 0;
|
|
848
970
|
});
|
|
849
971
|
if (fallback) this.snapToFn(fallback);
|
|
850
972
|
};
|
|
@@ -861,6 +983,7 @@ var ScrimController = class {
|
|
|
861
983
|
if (this.isDestroyed()) return;
|
|
862
984
|
if (enabled === this.scrimEnabled) return;
|
|
863
985
|
this.scrimEnabled = enabled;
|
|
986
|
+
this.invalidateOpacityCache();
|
|
864
987
|
if (!enabled) {
|
|
865
988
|
this.savedScrimRanges = {
|
|
866
989
|
screen: this.screenRange,
|
|
@@ -884,7 +1007,12 @@ var ScrimController = class {
|
|
|
884
1007
|
blur: cfg.blur ?? null,
|
|
885
1008
|
interactive: cfg.interactive
|
|
886
1009
|
});
|
|
887
|
-
this.
|
|
1010
|
+
if (!this.scrimEnabled && this.savedScrimRanges) {
|
|
1011
|
+
this.savedScrimRanges = { screen: cfg.range, backdrop: cfg.range };
|
|
1012
|
+
} else {
|
|
1013
|
+
this.screenRange = cfg.range;
|
|
1014
|
+
this.backdropRange = cfg.range;
|
|
1015
|
+
}
|
|
888
1016
|
}
|
|
889
1017
|
const noop = () => {
|
|
890
1018
|
};
|
|
@@ -934,59 +1062,7 @@ var ScrimController = class {
|
|
|
934
1062
|
wrapper.className = "bs-scrim-overlay";
|
|
935
1063
|
const ws = wrapper.style;
|
|
936
1064
|
ws.position = "absolute";
|
|
937
|
-
|
|
938
|
-
case "top-left":
|
|
939
|
-
ws.top = inset;
|
|
940
|
-
ws.left = inset;
|
|
941
|
-
break;
|
|
942
|
-
case "top-center":
|
|
943
|
-
ws.top = inset;
|
|
944
|
-
ws.left = "50%";
|
|
945
|
-
ws.transform = "translateX(-50%)";
|
|
946
|
-
break;
|
|
947
|
-
case "top-right":
|
|
948
|
-
ws.top = inset;
|
|
949
|
-
ws.right = inset;
|
|
950
|
-
break;
|
|
951
|
-
case "center-left":
|
|
952
|
-
ws.top = "50%";
|
|
953
|
-
ws.left = inset;
|
|
954
|
-
ws.transform = "translateY(-50%)";
|
|
955
|
-
break;
|
|
956
|
-
case "center":
|
|
957
|
-
ws.top = "50%";
|
|
958
|
-
ws.left = "50%";
|
|
959
|
-
ws.transform = "translate(-50%, -50%)";
|
|
960
|
-
break;
|
|
961
|
-
case "center-right":
|
|
962
|
-
ws.top = "50%";
|
|
963
|
-
ws.right = inset;
|
|
964
|
-
ws.transform = "translateY(-50%)";
|
|
965
|
-
break;
|
|
966
|
-
case "bottom-left":
|
|
967
|
-
ws.bottom = inset;
|
|
968
|
-
ws.left = inset;
|
|
969
|
-
break;
|
|
970
|
-
case "bottom-center":
|
|
971
|
-
ws.bottom = inset;
|
|
972
|
-
ws.left = "50%";
|
|
973
|
-
ws.transform = "translateX(-50%)";
|
|
974
|
-
break;
|
|
975
|
-
case "bottom-right":
|
|
976
|
-
ws.bottom = inset;
|
|
977
|
-
ws.right = inset;
|
|
978
|
-
break;
|
|
979
|
-
case "sheet-top-left":
|
|
980
|
-
case "sheet-top-center":
|
|
981
|
-
case "sheet-top-right":
|
|
982
|
-
applySheetAnchoredPosition(
|
|
983
|
-
ws,
|
|
984
|
-
this.mode,
|
|
985
|
-
position,
|
|
986
|
-
inset
|
|
987
|
-
);
|
|
988
|
-
break;
|
|
989
|
-
}
|
|
1065
|
+
applyOverlayPosition(ws, this.mode, position, inset);
|
|
990
1066
|
if (interactive) {
|
|
991
1067
|
ws.pointerEvents = "auto";
|
|
992
1068
|
}
|
|
@@ -1045,6 +1121,7 @@ var ScrimController = class {
|
|
|
1045
1121
|
}
|
|
1046
1122
|
}
|
|
1047
1123
|
if (opts.interactive !== void 0) {
|
|
1124
|
+
this.scrimInteractive = opts.interactive;
|
|
1048
1125
|
s.pointerEvents = opts.interactive ? "auto" : "none";
|
|
1049
1126
|
}
|
|
1050
1127
|
}
|
|
@@ -1059,38 +1136,9 @@ var ScrimController = class {
|
|
|
1059
1136
|
const s = this.screenComponent.style;
|
|
1060
1137
|
s.position = "fixed";
|
|
1061
1138
|
s.inset = insetByMode[this.mode];
|
|
1062
|
-
s.pointerEvents = "none";
|
|
1139
|
+
s.pointerEvents = this.scrimInteractive || this.scrimTapToCloseEnabled ? "auto" : "none";
|
|
1063
1140
|
}
|
|
1064
1141
|
};
|
|
1065
|
-
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
1066
|
-
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
1067
|
-
switch (mode) {
|
|
1068
|
-
case "bottom":
|
|
1069
|
-
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
1070
|
-
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
1071
|
-
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1072
|
-
case "top":
|
|
1073
|
-
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
1074
|
-
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
1075
|
-
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1076
|
-
case "left":
|
|
1077
|
-
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
1078
|
-
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
1079
|
-
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1080
|
-
case "right":
|
|
1081
|
-
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
1082
|
-
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
1083
|
-
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
function applySheetAnchoredPosition(ws, mode, position, inset) {
|
|
1087
|
-
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
1088
|
-
if (style.top !== void 0) ws.top = style.top;
|
|
1089
|
-
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
1090
|
-
if (style.left !== void 0) ws.left = style.left;
|
|
1091
|
-
if (style.right !== void 0) ws.right = style.right;
|
|
1092
|
-
if (style.transform !== void 0) ws.transform = style.transform;
|
|
1093
|
-
}
|
|
1094
1142
|
|
|
1095
1143
|
// src/core/animation/animation.ts
|
|
1096
1144
|
var easeOutBack = (t) => {
|
|
@@ -1142,6 +1190,10 @@ var tween = ({
|
|
|
1142
1190
|
promise
|
|
1143
1191
|
};
|
|
1144
1192
|
};
|
|
1193
|
+
var prefersReducedMotion = () => {
|
|
1194
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1195
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1196
|
+
};
|
|
1145
1197
|
|
|
1146
1198
|
// src/core/animation/spring.ts
|
|
1147
1199
|
var DEFAULT_SPRING = {
|
|
@@ -1172,14 +1224,20 @@ var runSpring = ({
|
|
|
1172
1224
|
if (cancelled) return;
|
|
1173
1225
|
const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
|
|
1174
1226
|
lastTime = now;
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1227
|
+
const steps = Math.max(1, Math.ceil(dt * 240));
|
|
1228
|
+
const subDt = dt / steps;
|
|
1229
|
+
let stepsLeft = steps;
|
|
1177
1230
|
while (stepsLeft-- > 0) {
|
|
1178
1231
|
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1179
1232
|
const accel = force / cfg.mass;
|
|
1180
1233
|
v += accel * subDt;
|
|
1181
1234
|
x += v * subDt;
|
|
1182
1235
|
}
|
|
1236
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1237
|
+
onUpdate(to, 0);
|
|
1238
|
+
resolve();
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1183
1241
|
onUpdate(x, v);
|
|
1184
1242
|
const isAtRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1185
1243
|
if (isAtRest) {
|
|
@@ -1354,9 +1412,13 @@ var isVisible = (el) => {
|
|
|
1354
1412
|
var focusables = (root) => Array.from(root.querySelectorAll(FOCUSABLE)).filter(
|
|
1355
1413
|
(el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
|
|
1356
1414
|
);
|
|
1415
|
+
var trapStack = [];
|
|
1357
1416
|
var installFocusTrap = (container, options = {}) => {
|
|
1358
1417
|
if (typeof document === "undefined") return () => {
|
|
1359
1418
|
};
|
|
1419
|
+
const token = {};
|
|
1420
|
+
trapStack.push(token);
|
|
1421
|
+
const isActive = () => trapStack[trapStack.length - 1] === token;
|
|
1360
1422
|
const previouslyFocused = document.activeElement;
|
|
1361
1423
|
const focusInitial = () => {
|
|
1362
1424
|
const initial = typeof options.initialFocus === "string" ? container.querySelector(options.initialFocus) : options.initialFocus ?? focusables(container)[0] ?? container;
|
|
@@ -1364,6 +1426,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1364
1426
|
};
|
|
1365
1427
|
focusInitial();
|
|
1366
1428
|
const handleKey = (e) => {
|
|
1429
|
+
if (!isActive()) return;
|
|
1367
1430
|
if (e.key === "Escape" && options.onEscape) {
|
|
1368
1431
|
options.onEscape();
|
|
1369
1432
|
return;
|
|
@@ -1386,6 +1449,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1386
1449
|
}
|
|
1387
1450
|
};
|
|
1388
1451
|
const handleFocusIn = (e) => {
|
|
1452
|
+
if (!isActive()) return;
|
|
1389
1453
|
const target = e.target;
|
|
1390
1454
|
if (target && !container.contains(target)) {
|
|
1391
1455
|
const list = focusables(container);
|
|
@@ -1398,6 +1462,8 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1398
1462
|
return () => {
|
|
1399
1463
|
if (released) return;
|
|
1400
1464
|
released = true;
|
|
1465
|
+
const idx = trapStack.indexOf(token);
|
|
1466
|
+
if (idx !== -1) trapStack.splice(idx, 1);
|
|
1401
1467
|
document.removeEventListener("keydown", handleKey, true);
|
|
1402
1468
|
document.removeEventListener("focusin", handleFocusIn, true);
|
|
1403
1469
|
if (previouslyFocused && document.contains(previouslyFocused)) {
|
|
@@ -1453,11 +1519,17 @@ function createInertSiblings(rootProvider) {
|
|
|
1453
1519
|
return {
|
|
1454
1520
|
apply() {
|
|
1455
1521
|
if (typeof document === "undefined") return;
|
|
1456
|
-
|
|
1457
|
-
|
|
1522
|
+
let top = rootProvider();
|
|
1523
|
+
while (top.parentElement && top.parentElement !== document.body) {
|
|
1524
|
+
top = top.parentElement;
|
|
1525
|
+
}
|
|
1526
|
+
const parent = top.parentElement ?? document.body;
|
|
1458
1527
|
for (const child of Array.from(parent.children)) {
|
|
1459
|
-
if (child ===
|
|
1528
|
+
if (child === top) continue;
|
|
1460
1529
|
if (child.hasAttribute("inert")) continue;
|
|
1530
|
+
if (child.classList.contains("bs-backdrop") || child.classList.contains("bs-screen") || child.classList.contains("bs-root")) {
|
|
1531
|
+
continue;
|
|
1532
|
+
}
|
|
1461
1533
|
child.setAttribute("inert", "");
|
|
1462
1534
|
tracked.push(child);
|
|
1463
1535
|
}
|
|
@@ -1473,7 +1545,6 @@ function createInertSiblings(rootProvider) {
|
|
|
1473
1545
|
var LifecycleController = class {
|
|
1474
1546
|
constructor(deps, opts) {
|
|
1475
1547
|
__publicField(this, "element");
|
|
1476
|
-
__publicField(this, "closeFn");
|
|
1477
1548
|
__publicField(this, "focusTrapEnabled");
|
|
1478
1549
|
__publicField(this, "initialFocus");
|
|
1479
1550
|
__publicField(this, "closeOnEscape");
|
|
@@ -1487,7 +1558,6 @@ var LifecycleController = class {
|
|
|
1487
1558
|
__publicField(this, "installed", false);
|
|
1488
1559
|
__publicField(this, "destroyed", false);
|
|
1489
1560
|
this.element = deps.element;
|
|
1490
|
-
this.closeFn = deps.close;
|
|
1491
1561
|
this.focusTrapEnabled = opts.focusTrap ?? false;
|
|
1492
1562
|
this.initialFocus = opts.initialFocus;
|
|
1493
1563
|
this.closeOnEscape = opts.closeOnEscape ?? true;
|
|
@@ -1497,6 +1567,9 @@ var LifecycleController = class {
|
|
|
1497
1567
|
this.returnFocus = opts.returnFocus;
|
|
1498
1568
|
this.inertSiblings = createInertSiblings(() => this.element);
|
|
1499
1569
|
}
|
|
1570
|
+
get isInstalled() {
|
|
1571
|
+
return this.installed;
|
|
1572
|
+
}
|
|
1500
1573
|
install() {
|
|
1501
1574
|
if (this.destroyed) return;
|
|
1502
1575
|
this.installed = true;
|
|
@@ -1505,8 +1578,7 @@ var LifecycleController = class {
|
|
|
1505
1578
|
}
|
|
1506
1579
|
if (this.focusTrapEnabled && !this.releaseFocusTrap) {
|
|
1507
1580
|
this.releaseFocusTrap = installFocusTrap(this.element, {
|
|
1508
|
-
initialFocus: this.initialFocus
|
|
1509
|
-
onEscape: this.closeOnEscape ? () => void this.closeFn() : void 0
|
|
1581
|
+
initialFocus: this.initialFocus
|
|
1510
1582
|
});
|
|
1511
1583
|
}
|
|
1512
1584
|
if (this.inertSiblingsEnabled && this.shouldApplyInertSiblings()) {
|
|
@@ -1660,10 +1732,11 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
1660
1732
|
};
|
|
1661
1733
|
|
|
1662
1734
|
// src/core/primitives/rubber-band.ts
|
|
1663
|
-
var RUBBER_BAND_FACTOR = 0.55;
|
|
1664
1735
|
function rubberBand(overshoot, maxAxisSize) {
|
|
1665
1736
|
const cap = Math.min(maxAxisSize * 0.15, 80);
|
|
1666
|
-
|
|
1737
|
+
if (cap <= 0) return 0;
|
|
1738
|
+
const abs = Math.abs(overshoot);
|
|
1739
|
+
return Math.sign(overshoot) * (cap * abs / (abs + cap));
|
|
1667
1740
|
}
|
|
1668
1741
|
|
|
1669
1742
|
// src/core/features/soft-keyboard.ts
|
|
@@ -1748,6 +1821,10 @@ var GestureController = class {
|
|
|
1748
1821
|
this.isDragging_ = false;
|
|
1749
1822
|
this.keyboardDismissed = false;
|
|
1750
1823
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1824
|
+
this.deps.emit("dragend", {
|
|
1825
|
+
size: this.deps.getDragContext().size,
|
|
1826
|
+
velocity: 0
|
|
1827
|
+
});
|
|
1751
1828
|
const restoreTo = this.dragStartSize;
|
|
1752
1829
|
void this.deps.animateTo(restoreTo, 0);
|
|
1753
1830
|
}
|
|
@@ -1821,6 +1898,287 @@ function createScrollCache(deps) {
|
|
|
1821
1898
|
};
|
|
1822
1899
|
}
|
|
1823
1900
|
|
|
1901
|
+
// src/core/primitives/anchor-animations.ts
|
|
1902
|
+
var DEFAULT_DURATION3 = 200;
|
|
1903
|
+
var DEFAULT_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
1904
|
+
var PRESET_FRAMES = {
|
|
1905
|
+
fade: {
|
|
1906
|
+
enter: [{ opacity: 0 }, { opacity: 1 }],
|
|
1907
|
+
exit: [{ opacity: 1 }, { opacity: 0 }]
|
|
1908
|
+
},
|
|
1909
|
+
scale: {
|
|
1910
|
+
enter: [
|
|
1911
|
+
{ opacity: 0, transform: "scale(0.85)" },
|
|
1912
|
+
{ opacity: 1, transform: "scale(1)" }
|
|
1913
|
+
],
|
|
1914
|
+
exit: [
|
|
1915
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
1916
|
+
{ opacity: 0, transform: "scale(0.85)" }
|
|
1917
|
+
]
|
|
1918
|
+
},
|
|
1919
|
+
slide: {
|
|
1920
|
+
enter: [
|
|
1921
|
+
{ opacity: 0, transform: "translateY(10px)" },
|
|
1922
|
+
{ opacity: 1, transform: "translateY(0)" }
|
|
1923
|
+
],
|
|
1924
|
+
exit: [
|
|
1925
|
+
{ opacity: 1, transform: "translateY(0)" },
|
|
1926
|
+
{ opacity: 0, transform: "translateY(10px)" }
|
|
1927
|
+
]
|
|
1928
|
+
},
|
|
1929
|
+
pop: {
|
|
1930
|
+
enter: [
|
|
1931
|
+
{ opacity: 0, transform: "scale(0.6)", offset: 0 },
|
|
1932
|
+
{ opacity: 1, transform: "scale(1.06)", offset: 0.7 },
|
|
1933
|
+
{ opacity: 1, transform: "scale(1)", offset: 1 }
|
|
1934
|
+
],
|
|
1935
|
+
exit: [
|
|
1936
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
1937
|
+
{ opacity: 0, transform: "scale(0.6)" }
|
|
1938
|
+
]
|
|
1939
|
+
}
|
|
1940
|
+
};
|
|
1941
|
+
var INSTANT = {
|
|
1942
|
+
finished: Promise.resolve(),
|
|
1943
|
+
cancel: () => {
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
function resolveTransitionFrames(spec, phase) {
|
|
1947
|
+
const fallback = { frames: null, duration: 0, easing: DEFAULT_EASING };
|
|
1948
|
+
if (spec === "none") return fallback;
|
|
1949
|
+
if (spec === void 0 || typeof spec === "string") {
|
|
1950
|
+
const preset2 = PRESET_FRAMES[spec ?? "fade"];
|
|
1951
|
+
return {
|
|
1952
|
+
frames: preset2[phase],
|
|
1953
|
+
duration: DEFAULT_DURATION3,
|
|
1954
|
+
easing: DEFAULT_EASING
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
const custom = phase === "enter" ? spec.enter : spec.exit;
|
|
1958
|
+
if (custom) {
|
|
1959
|
+
return {
|
|
1960
|
+
frames: custom,
|
|
1961
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
1962
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
if (spec.preset === "none") return fallback;
|
|
1966
|
+
const preset = PRESET_FRAMES[spec.preset ?? "fade"];
|
|
1967
|
+
return {
|
|
1968
|
+
frames: preset[phase],
|
|
1969
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
1970
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
function runAnchorTransition(el, spec, phase) {
|
|
1974
|
+
const respectReduced = typeof spec === "object" ? spec.respectReducedMotion !== false : true;
|
|
1975
|
+
if (respectReduced && prefersReducedMotion()) return INSTANT;
|
|
1976
|
+
const { frames, duration, easing } = resolveTransitionFrames(spec, phase);
|
|
1977
|
+
if (!frames || duration <= 0) return INSTANT;
|
|
1978
|
+
if (typeof el.animate !== "function") return INSTANT;
|
|
1979
|
+
const animation = el.animate(frames, {
|
|
1980
|
+
duration,
|
|
1981
|
+
easing,
|
|
1982
|
+
fill: "both"
|
|
1983
|
+
});
|
|
1984
|
+
const finished = animation.finished.then(() => void 0).catch(() => void 0);
|
|
1985
|
+
return {
|
|
1986
|
+
finished,
|
|
1987
|
+
cancel: () => {
|
|
1988
|
+
try {
|
|
1989
|
+
animation.cancel();
|
|
1990
|
+
} catch {
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
// src/core/features/sheet-anchors.ts
|
|
1998
|
+
function attachAnchor(deps, opts) {
|
|
1999
|
+
const doc = deps.host.ownerDocument;
|
|
2000
|
+
const wrapper = doc.createElement("div");
|
|
2001
|
+
wrapper.className = "bs-anchor";
|
|
2002
|
+
const interactive = opts.interactive ?? true;
|
|
2003
|
+
const position = opts.position ?? "sheet-top-right";
|
|
2004
|
+
const isDock = position === "dock-bottom" || position === "dock-top";
|
|
2005
|
+
const ws = wrapper.style;
|
|
2006
|
+
ws.position = "fixed";
|
|
2007
|
+
if (isDock) {
|
|
2008
|
+
ws.left = "0";
|
|
2009
|
+
ws.right = "0";
|
|
2010
|
+
if (position === "dock-bottom") {
|
|
2011
|
+
ws.bottom = "0";
|
|
2012
|
+
} else {
|
|
2013
|
+
ws.top = "0";
|
|
2014
|
+
}
|
|
2015
|
+
} else {
|
|
2016
|
+
applyOverlayPosition(ws, deps.mode, position, opts.inset ?? "16px");
|
|
2017
|
+
}
|
|
2018
|
+
if (opts.fadeRange) {
|
|
2019
|
+
const [r0, r1] = opts.fadeRange;
|
|
2020
|
+
const span = Math.max(r1 - r0, 1e-4);
|
|
2021
|
+
ws.opacity = `clamp(0, calc((var(--bs-progress, 0) - ${r0}) / ${span}), 1)`;
|
|
2022
|
+
}
|
|
2023
|
+
wrapper.appendChild(opts.element);
|
|
2024
|
+
deps.host.appendChild(wrapper);
|
|
2025
|
+
let visible = null;
|
|
2026
|
+
let inFlight = null;
|
|
2027
|
+
const shouldShow = (state) => {
|
|
2028
|
+
if (typeof opts.showOn === "function") return opts.showOn(state);
|
|
2029
|
+
if (Array.isArray(opts.showOn)) return opts.showOn.includes(state.activeId);
|
|
2030
|
+
return isDock || state.size > 0;
|
|
2031
|
+
};
|
|
2032
|
+
const applyVisibility = (next, animate) => {
|
|
2033
|
+
if (next === visible) return;
|
|
2034
|
+
visible = next;
|
|
2035
|
+
inFlight?.cancel();
|
|
2036
|
+
inFlight = null;
|
|
2037
|
+
wrapper.style.pointerEvents = next && interactive ? "auto" : "none";
|
|
2038
|
+
if (next) {
|
|
2039
|
+
wrapper.style.visibility = "";
|
|
2040
|
+
if (animate) {
|
|
2041
|
+
inFlight = runAnchorTransition(opts.element, opts.animation, "enter");
|
|
2042
|
+
}
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
if (!animate) {
|
|
2046
|
+
wrapper.style.visibility = "hidden";
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
2049
|
+
const handle = runAnchorTransition(opts.element, opts.animation, "exit");
|
|
2050
|
+
inFlight = handle;
|
|
2051
|
+
void handle.finished.then(() => {
|
|
2052
|
+
if (inFlight === handle && visible === false) {
|
|
2053
|
+
wrapper.style.visibility = "hidden";
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
2056
|
+
};
|
|
2057
|
+
const evaluate = (animate) => {
|
|
2058
|
+
if (deps.isDestroyed()) return;
|
|
2059
|
+
applyVisibility(shouldShow(deps.getState()), animate);
|
|
2060
|
+
};
|
|
2061
|
+
const offs = [
|
|
2062
|
+
deps.on("snap", () => evaluate(true)),
|
|
2063
|
+
deps.on("open", () => evaluate(true)),
|
|
2064
|
+
deps.on("close", () => evaluate(true))
|
|
2065
|
+
];
|
|
2066
|
+
evaluate(false);
|
|
2067
|
+
return {
|
|
2068
|
+
wrapper,
|
|
2069
|
+
detach: () => {
|
|
2070
|
+
offs.forEach((off) => off());
|
|
2071
|
+
inFlight?.cancel();
|
|
2072
|
+
inFlight = null;
|
|
2073
|
+
if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);
|
|
2074
|
+
},
|
|
2075
|
+
syncZ: (z) => {
|
|
2076
|
+
wrapper.style.zIndex = String(z);
|
|
2077
|
+
}
|
|
2078
|
+
};
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
// src/core/features/scrim-stages.ts
|
|
2082
|
+
var matchesId = (def, activeId) => {
|
|
2083
|
+
if (def.for === void 0) return false;
|
|
2084
|
+
return Array.isArray(def.for) ? def.for.includes(activeId) : def.for === activeId;
|
|
2085
|
+
};
|
|
2086
|
+
var matchesRange = (def, progress) => {
|
|
2087
|
+
if (!def.forRange) return false;
|
|
2088
|
+
const [from, to] = def.forRange;
|
|
2089
|
+
return progress >= from && progress <= to;
|
|
2090
|
+
};
|
|
2091
|
+
function installScrimStages(deps, opts) {
|
|
2092
|
+
const doc = deps.host.ownerDocument;
|
|
2093
|
+
const entries = opts.stages.map((def) => {
|
|
2094
|
+
const wrapper = doc.createElement("div");
|
|
2095
|
+
wrapper.className = "bs-scrim-stage";
|
|
2096
|
+
const ws = wrapper.style;
|
|
2097
|
+
ws.position = "absolute";
|
|
2098
|
+
applyOverlayPosition(
|
|
2099
|
+
ws,
|
|
2100
|
+
deps.mode,
|
|
2101
|
+
def.position ?? opts.position ?? "center",
|
|
2102
|
+
def.inset ?? opts.inset ?? "16px"
|
|
2103
|
+
);
|
|
2104
|
+
ws.visibility = "hidden";
|
|
2105
|
+
ws.pointerEvents = "none";
|
|
2106
|
+
wrapper.appendChild(def.element);
|
|
2107
|
+
deps.host.appendChild(wrapper);
|
|
2108
|
+
return { def, wrapper, inFlight: null };
|
|
2109
|
+
});
|
|
2110
|
+
let active = null;
|
|
2111
|
+
const resolveActive = () => {
|
|
2112
|
+
const state = deps.getState();
|
|
2113
|
+
if (state.size === 0) {
|
|
2114
|
+
return entries.find((e) => matchesId(e.def, state.activeId)) ?? null;
|
|
2115
|
+
}
|
|
2116
|
+
return entries.find((e) => matchesId(e.def, state.activeId)) ?? entries.find((e) => matchesRange(e.def, state.progress)) ?? null;
|
|
2117
|
+
};
|
|
2118
|
+
const hide = (entry, animate) => {
|
|
2119
|
+
entry.inFlight?.cancel();
|
|
2120
|
+
entry.wrapper.style.pointerEvents = "none";
|
|
2121
|
+
if (!animate) {
|
|
2122
|
+
entry.inFlight = null;
|
|
2123
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
const handle = runAnchorTransition(
|
|
2127
|
+
entry.def.element,
|
|
2128
|
+
entry.def.animation ?? opts.animation,
|
|
2129
|
+
"exit"
|
|
2130
|
+
);
|
|
2131
|
+
entry.inFlight = handle;
|
|
2132
|
+
void handle.finished.then(() => {
|
|
2133
|
+
if (entry.inFlight === handle && active !== entry) {
|
|
2134
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
};
|
|
2138
|
+
const show = (entry, animate) => {
|
|
2139
|
+
entry.inFlight?.cancel();
|
|
2140
|
+
entry.inFlight = null;
|
|
2141
|
+
entry.wrapper.style.visibility = "";
|
|
2142
|
+
entry.wrapper.style.pointerEvents = entry.def.interactive ?? opts.interactive ?? false ? "auto" : "none";
|
|
2143
|
+
if (animate) {
|
|
2144
|
+
entry.inFlight = runAnchorTransition(
|
|
2145
|
+
entry.def.element,
|
|
2146
|
+
entry.def.animation ?? opts.animation,
|
|
2147
|
+
"enter"
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
};
|
|
2151
|
+
const update = (animate) => {
|
|
2152
|
+
if (deps.isDestroyed()) return;
|
|
2153
|
+
const next = resolveActive();
|
|
2154
|
+
if (next === active) return;
|
|
2155
|
+
const prev = active;
|
|
2156
|
+
active = next;
|
|
2157
|
+
if (prev) hide(prev, animate);
|
|
2158
|
+
if (next) show(next, animate);
|
|
2159
|
+
};
|
|
2160
|
+
const offs = [
|
|
2161
|
+
deps.on("snap", () => update(true)),
|
|
2162
|
+
deps.on("open", () => update(true)),
|
|
2163
|
+
deps.on("close", () => update(true))
|
|
2164
|
+
];
|
|
2165
|
+
if (entries.some((e) => e.def.forRange)) {
|
|
2166
|
+
offs.push(deps.on("progress", () => update(true)));
|
|
2167
|
+
}
|
|
2168
|
+
update(false);
|
|
2169
|
+
return () => {
|
|
2170
|
+
offs.forEach((off) => off());
|
|
2171
|
+
for (const entry of entries) {
|
|
2172
|
+
entry.inFlight?.cancel();
|
|
2173
|
+
entry.inFlight = null;
|
|
2174
|
+
if (entry.wrapper.parentNode) {
|
|
2175
|
+
entry.wrapper.parentNode.removeChild(entry.wrapper);
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
active = null;
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
|
|
1824
2182
|
// src/core/primitives/engine-options.ts
|
|
1825
2183
|
var DEFAULT_FLICK_VELOCITY = 0.65;
|
|
1826
2184
|
var DEFAULT_DRAG_THRESHOLD = 18;
|
|
@@ -1937,6 +2295,12 @@ var BottomSheetEngine = class {
|
|
|
1937
2295
|
__publicField(this, "linkedSheets", []);
|
|
1938
2296
|
__publicField(this, "scrollCache");
|
|
1939
2297
|
__publicField(this, "teardowns", new TeardownStack());
|
|
2298
|
+
__publicField(this, "anchors", []);
|
|
2299
|
+
__publicField(this, "anchorHost", null);
|
|
2300
|
+
__publicField(this, "stackZ", 100);
|
|
2301
|
+
__publicField(this, "detachScrimStages", null);
|
|
2302
|
+
__publicField(this, "stackEffectEnabled", false);
|
|
2303
|
+
__publicField(this, "stackEffectPrimed", false);
|
|
1940
2304
|
__publicField(this, "transformTemplate");
|
|
1941
2305
|
const resolved = resolveEngineOptions(opts, {
|
|
1942
2306
|
shouldApplyInertSiblings: () => {
|
|
@@ -1970,6 +2334,9 @@ var BottomSheetEngine = class {
|
|
|
1970
2334
|
getResolvedSnaps: () => this.snaps.getResolvedSnaps().slice(),
|
|
1971
2335
|
snapTo: (id) => {
|
|
1972
2336
|
void this.snapTo(id);
|
|
2337
|
+
},
|
|
2338
|
+
close: () => {
|
|
2339
|
+
void this.close();
|
|
1973
2340
|
}
|
|
1974
2341
|
},
|
|
1975
2342
|
resolved.scrim
|
|
@@ -1993,6 +2360,7 @@ var BottomSheetEngine = class {
|
|
|
1993
2360
|
);
|
|
1994
2361
|
this.closeOnBack = resolved.closeOnBack;
|
|
1995
2362
|
this.routedTo = opts.routedTo;
|
|
2363
|
+
this.stackEffectEnabled = opts.stackEffect ?? false;
|
|
1996
2364
|
this.snapPointsRaw = opts.snapPoints;
|
|
1997
2365
|
this.persistKey = opts.persistKey;
|
|
1998
2366
|
if (opts.linkedSheets) {
|
|
@@ -2005,7 +2373,7 @@ var BottomSheetEngine = class {
|
|
|
2005
2373
|
this.snapPointsRaw,
|
|
2006
2374
|
resolved.initialAllowed,
|
|
2007
2375
|
this.mode,
|
|
2008
|
-
() => this.handle.offsetHeight,
|
|
2376
|
+
() => layoutAxis(this.mode) === "width" ? this.handle.offsetWidth : this.handle.offsetHeight,
|
|
2009
2377
|
(maxAxisSize) => {
|
|
2010
2378
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2011
2379
|
}
|
|
@@ -2215,11 +2583,6 @@ var BottomSheetEngine = class {
|
|
|
2215
2583
|
}
|
|
2216
2584
|
setAllowed(ids, snap) {
|
|
2217
2585
|
if (this.destroyed) return;
|
|
2218
|
-
const willSnap = snap !== void 0 && ids.includes(snap) || !ids.includes(this.activeId) && ids.length > 0;
|
|
2219
|
-
if (!willSnap) {
|
|
2220
|
-
this.animation.cancel();
|
|
2221
|
-
this.newCycle();
|
|
2222
|
-
}
|
|
2223
2586
|
this.snaps.setAllowedIds(ids);
|
|
2224
2587
|
this.updateAriaSlider();
|
|
2225
2588
|
if (snap && ids.includes(snap)) {
|
|
@@ -2259,6 +2622,79 @@ var BottomSheetEngine = class {
|
|
|
2259
2622
|
setScrimOverlay(opts) {
|
|
2260
2623
|
return this.scrim.setScrimOverlay(opts);
|
|
2261
2624
|
}
|
|
2625
|
+
addAnchor(opts) {
|
|
2626
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2627
|
+
};
|
|
2628
|
+
if (!this.anchorHost) {
|
|
2629
|
+
this.anchorHost = this.rootEl ?? this.element.parentElement ?? document.body;
|
|
2630
|
+
this.anchorHost.style.setProperty("--bs-size", `${this.size}px`);
|
|
2631
|
+
this.anchorHost.style.setProperty(
|
|
2632
|
+
"--bs-progress",
|
|
2633
|
+
String(this.computeProgress(this.size))
|
|
2634
|
+
);
|
|
2635
|
+
}
|
|
2636
|
+
const handle = attachAnchor(
|
|
2637
|
+
{
|
|
2638
|
+
mode: this.mode,
|
|
2639
|
+
host: this.anchorHost,
|
|
2640
|
+
getState: () => ({
|
|
2641
|
+
activeId: this.activeId,
|
|
2642
|
+
size: this.size,
|
|
2643
|
+
progress: this.computeProgress(this.size)
|
|
2644
|
+
}),
|
|
2645
|
+
on: (event, fn) => this.on(event, fn),
|
|
2646
|
+
isDestroyed: () => this.destroyed
|
|
2647
|
+
},
|
|
2648
|
+
opts
|
|
2649
|
+
);
|
|
2650
|
+
handle.syncZ(this.stackZ + 1);
|
|
2651
|
+
this.anchors.push(handle);
|
|
2652
|
+
const detach = () => {
|
|
2653
|
+
const idx = this.anchors.indexOf(handle);
|
|
2654
|
+
if (idx === -1) return;
|
|
2655
|
+
this.anchors.splice(idx, 1);
|
|
2656
|
+
handle.detach();
|
|
2657
|
+
};
|
|
2658
|
+
this.teardowns.add(detach);
|
|
2659
|
+
return detach;
|
|
2660
|
+
}
|
|
2661
|
+
setScrimStages(opts) {
|
|
2662
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2663
|
+
};
|
|
2664
|
+
this.detachScrimStages?.();
|
|
2665
|
+
this.detachScrimStages = null;
|
|
2666
|
+
if (!opts) return () => {
|
|
2667
|
+
};
|
|
2668
|
+
const host = this.screenComponent?.parentElement;
|
|
2669
|
+
if (!host) {
|
|
2670
|
+
console.warn(
|
|
2671
|
+
"[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
|
|
2672
|
+
);
|
|
2673
|
+
return () => {
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2676
|
+
const detachInstalled = installScrimStages(
|
|
2677
|
+
{
|
|
2678
|
+
mode: this.mode,
|
|
2679
|
+
host,
|
|
2680
|
+
getState: () => ({
|
|
2681
|
+
activeId: this.activeId,
|
|
2682
|
+
size: this.size,
|
|
2683
|
+
progress: this.computeProgress(this.size)
|
|
2684
|
+
}),
|
|
2685
|
+
on: (event, fn) => this.on(event, fn),
|
|
2686
|
+
isDestroyed: () => this.destroyed
|
|
2687
|
+
},
|
|
2688
|
+
opts
|
|
2689
|
+
);
|
|
2690
|
+
const detach = () => {
|
|
2691
|
+
if (this.detachScrimStages === detach) this.detachScrimStages = null;
|
|
2692
|
+
detachInstalled();
|
|
2693
|
+
};
|
|
2694
|
+
this.detachScrimStages = detach;
|
|
2695
|
+
this.teardowns.add(() => this.detachScrimStages?.());
|
|
2696
|
+
return detach;
|
|
2697
|
+
}
|
|
2262
2698
|
getScrimState() {
|
|
2263
2699
|
return { mode: this.scrim.scrimMode, enabled: this.scrim.scrimEnabled };
|
|
2264
2700
|
}
|
|
@@ -2345,24 +2781,45 @@ var BottomSheetEngine = class {
|
|
|
2345
2781
|
getAllowedRange() {
|
|
2346
2782
|
return this.snaps.getAllowedRange();
|
|
2347
2783
|
}
|
|
2784
|
+
allowedIdsBySize() {
|
|
2785
|
+
return this.snaps.getAllowedIds().slice().sort(
|
|
2786
|
+
(a, b) => (this.snaps.findById(a)?.size ?? 0) - (this.snaps.findById(b)?.size ?? 0)
|
|
2787
|
+
);
|
|
2788
|
+
}
|
|
2348
2789
|
updateAriaSlider() {
|
|
2349
|
-
this.aria.setValue(this.
|
|
2790
|
+
this.aria.setValue(this.allowedIdsBySize(), this.activeId);
|
|
2350
2791
|
}
|
|
2351
2792
|
registerInStack() {
|
|
2352
2793
|
this.teardowns.add(sheetStack.push({
|
|
2353
2794
|
id: this.id,
|
|
2354
2795
|
setZIndex: (z) => {
|
|
2796
|
+
this.stackZ = z;
|
|
2355
2797
|
this.element.style.zIndex = String(z);
|
|
2356
2798
|
if (this.backdrop) this.backdrop.style.zIndex = String(z - 1);
|
|
2799
|
+
for (const anchor of this.anchors) anchor.syncZ(z + 1);
|
|
2357
2800
|
},
|
|
2358
2801
|
setIsTop: (isTop) => {
|
|
2359
2802
|
this.isTopSheet = isTop;
|
|
2360
2803
|
if (this.backdrop) {
|
|
2361
2804
|
this.backdrop.style.display = isTop ? "" : "none";
|
|
2362
2805
|
}
|
|
2363
|
-
}
|
|
2806
|
+
},
|
|
2807
|
+
isOpen: () => this.size > 0,
|
|
2808
|
+
setDepth: (depth) => this.applyStackDepth(depth)
|
|
2364
2809
|
}));
|
|
2365
2810
|
}
|
|
2811
|
+
applyStackDepth(depth) {
|
|
2812
|
+
if (!this.stackEffectEnabled) return;
|
|
2813
|
+
this.element.setAttribute("data-stack-depth", String(depth));
|
|
2814
|
+
if (!this.stackEffectPrimed) {
|
|
2815
|
+
this.stackEffectPrimed = true;
|
|
2816
|
+
const isVertical = this.mode === "bottom" || this.mode === "top";
|
|
2817
|
+
this.element.style.transformOrigin = isVertical ? "50% 100%" : "0% 50%";
|
|
2818
|
+
this.element.style.transition = "scale 320ms cubic-bezier(0.29, 1.04, 0.84, 0.99)";
|
|
2819
|
+
}
|
|
2820
|
+
const scale = Math.max(1 - depth * 0.04, 0.86);
|
|
2821
|
+
this.element.style.scale = scale === 1 ? "" : String(scale);
|
|
2822
|
+
}
|
|
2366
2823
|
attach() {
|
|
2367
2824
|
this.gesture = new GestureController({
|
|
2368
2825
|
handle: this.handle,
|
|
@@ -2422,7 +2879,7 @@ var BottomSheetEngine = class {
|
|
|
2422
2879
|
container: this.scrollContainer,
|
|
2423
2880
|
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2424
2881
|
isAnimating: () => this.animation.isAnimating,
|
|
2425
|
-
getAllowedIds: () => this.
|
|
2882
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2426
2883
|
getActiveId: () => this.activeId,
|
|
2427
2884
|
snapTo: (id) => {
|
|
2428
2885
|
void this.snapTo(id);
|
|
@@ -2451,11 +2908,13 @@ var BottomSheetEngine = class {
|
|
|
2451
2908
|
},
|
|
2452
2909
|
newCycle: () => {
|
|
2453
2910
|
this.newCycle();
|
|
2454
|
-
}
|
|
2911
|
+
},
|
|
2912
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2913
|
+
resyncAfterCancel: () => this.resyncAfterResize()
|
|
2455
2914
|
}));
|
|
2456
2915
|
if (this.lifecycle.closeOnEscape) {
|
|
2457
2916
|
const onKey = (e) => {
|
|
2458
|
-
if (this.destroyed) return;
|
|
2917
|
+
if (this.destroyed || e.defaultPrevented) return;
|
|
2459
2918
|
if (e.key === "Escape" && this.isTopSheet && this.size > 0) {
|
|
2460
2919
|
void this.close();
|
|
2461
2920
|
}
|
|
@@ -2487,7 +2946,7 @@ var BottomSheetEngine = class {
|
|
|
2487
2946
|
handle: this.handle,
|
|
2488
2947
|
mode: this.mode,
|
|
2489
2948
|
isDestroyed: () => this.destroyed,
|
|
2490
|
-
getAllowedIds: () => this.
|
|
2949
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2491
2950
|
getActiveId: () => this.activeId,
|
|
2492
2951
|
snapTo: (id) => {
|
|
2493
2952
|
void this.snapTo(id);
|
|
@@ -2508,6 +2967,7 @@ var BottomSheetEngine = class {
|
|
|
2508
2967
|
});
|
|
2509
2968
|
if (!target) return;
|
|
2510
2969
|
const previousId = this.activeId;
|
|
2970
|
+
if (target.id === previousId && target.size === this.size) return;
|
|
2511
2971
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
2512
2972
|
const restore = this.snaps.findById(previousId);
|
|
2513
2973
|
if (restore) {
|
|
@@ -2516,6 +2976,7 @@ var BottomSheetEngine = class {
|
|
|
2516
2976
|
return;
|
|
2517
2977
|
}
|
|
2518
2978
|
const previousSize = this.size;
|
|
2979
|
+
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
2519
2980
|
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
2520
2981
|
this.activeId = target.id;
|
|
2521
2982
|
void this.animation.animateTo(target.size, velocity).then(() => {
|
|
@@ -2524,9 +2985,10 @@ var BottomSheetEngine = class {
|
|
|
2524
2985
|
this.updateAriaSlider();
|
|
2525
2986
|
this.emit("snap", { id: target.id, size: target.size });
|
|
2526
2987
|
this.haptic();
|
|
2527
|
-
if (
|
|
2988
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
2528
2989
|
this.emit("open", { id: target.id });
|
|
2529
2990
|
this.handleOpen();
|
|
2991
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
2530
2992
|
}
|
|
2531
2993
|
if (target.size === 0) {
|
|
2532
2994
|
this.emit("close", void 0);
|
|
@@ -2552,6 +3014,9 @@ var BottomSheetEngine = class {
|
|
|
2552
3014
|
if (this.scrimParent) {
|
|
2553
3015
|
this.scrimParent.style.setProperty("--bs-size", `${size}px`);
|
|
2554
3016
|
}
|
|
3017
|
+
if (this.anchorHost && this.anchorHost !== this.scrimParent) {
|
|
3018
|
+
this.anchorHost.style.setProperty("--bs-size", `${size}px`);
|
|
3019
|
+
}
|
|
2555
3020
|
}
|
|
2556
3021
|
const progress = this.computeProgress(size);
|
|
2557
3022
|
const progressChanged = this.progressWriteSentinel.shouldWrite(
|
|
@@ -2560,6 +3025,9 @@ var BottomSheetEngine = class {
|
|
|
2560
3025
|
);
|
|
2561
3026
|
if (progressChanged) {
|
|
2562
3027
|
style.setProperty("--bs-progress", String(progress));
|
|
3028
|
+
if (this.anchorHost) {
|
|
3029
|
+
this.anchorHost.style.setProperty("--bs-progress", String(progress));
|
|
3030
|
+
}
|
|
2563
3031
|
}
|
|
2564
3032
|
this.scrim.applyOpacity(progress, progressChanged);
|
|
2565
3033
|
if (progressChanged && this.bus.listenerCount("progress") > 0) {
|
|
@@ -2574,6 +3042,7 @@ var BottomSheetEngine = class {
|
|
|
2574
3042
|
return Math.min(Math.max((size - min) / (max - min), 0), 1);
|
|
2575
3043
|
}
|
|
2576
3044
|
handleOpen() {
|
|
3045
|
+
sheetStack.promote(this.id);
|
|
2577
3046
|
try {
|
|
2578
3047
|
this.lifecycle.install();
|
|
2579
3048
|
} catch (err) {
|
|
@@ -2587,8 +3056,24 @@ var BottomSheetEngine = class {
|
|
|
2587
3056
|
});
|
|
2588
3057
|
}
|
|
2589
3058
|
}
|
|
3059
|
+
resyncAfterResize() {
|
|
3060
|
+
if (this.destroyed) return;
|
|
3061
|
+
const target = this.snaps.findById(this.activeId);
|
|
3062
|
+
if (!target) return;
|
|
3063
|
+
this.updateAriaSlider();
|
|
3064
|
+
this.emit("snap", { id: target.id, size: target.size });
|
|
3065
|
+
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3066
|
+
this.emit("open", { id: target.id });
|
|
3067
|
+
this.handleOpen();
|
|
3068
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
3069
|
+
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3070
|
+
this.emit("close", void 0);
|
|
3071
|
+
this.handleClose();
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
2590
3074
|
handleClose() {
|
|
2591
3075
|
this.lifecycle.release();
|
|
3076
|
+
sheetStack.update();
|
|
2592
3077
|
}
|
|
2593
3078
|
};
|
|
2594
3079
|
|
|
@@ -2657,6 +3142,10 @@ function useBottomSheet(opts) {
|
|
|
2657
3142
|
setScrim: (opts2) => engine?.setScrim(opts2),
|
|
2658
3143
|
setScrimOverlay: (opts2) => engine?.setScrimOverlay(opts2) ?? (() => {
|
|
2659
3144
|
}),
|
|
3145
|
+
addAnchor: (opts2) => engine?.addAnchor(opts2) ?? (() => {
|
|
3146
|
+
}),
|
|
3147
|
+
setScrimStages: (opts2) => engine?.setScrimStages(opts2) ?? (() => {
|
|
3148
|
+
}),
|
|
2660
3149
|
on: (event, fn) => {
|
|
2661
3150
|
if (engine) return engine.on(event, fn);
|
|
2662
3151
|
const entry = {
|
|
@@ -2808,6 +3297,10 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2808
3297
|
type: Boolean,
|
|
2809
3298
|
required: false
|
|
2810
3299
|
},
|
|
3300
|
+
stackEffect: {
|
|
3301
|
+
type: Boolean,
|
|
3302
|
+
required: false
|
|
3303
|
+
},
|
|
2811
3304
|
snapPoints: {
|
|
2812
3305
|
type: Array,
|
|
2813
3306
|
required: true
|
|
@@ -3009,7 +3502,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
3009
3502
|
], 8, _hoisted_3)
|
|
3010
3503
|
]);
|
|
3011
3504
|
}
|
|
3012
|
-
var BottomSheet_default = /* @__PURE__ */ export_helper_default(_sfc_main, [["render", _sfc_render], ["__file", "/
|
|
3505
|
+
var BottomSheet_default = /* @__PURE__ */ export_helper_default(_sfc_main, [["render", _sfc_render], ["__file", "/home/runner/work/BottomSheet/BottomSheet/src/vue/BottomSheet.vue"]]);
|
|
3013
3506
|
|
|
3014
3507
|
export { BottomSheet_default as BottomSheet, useBottomSheet };
|
|
3015
3508
|
//# sourceMappingURL=vue.js.map
|