@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/svelte.cjs
CHANGED
|
@@ -46,6 +46,18 @@ var SheetStack = class {
|
|
|
46
46
|
this.entries.splice(idx, 1);
|
|
47
47
|
this.recompute();
|
|
48
48
|
}
|
|
49
|
+
promote(id) {
|
|
50
|
+
const idx = this.entries.findIndex((e) => e.id === id);
|
|
51
|
+
if (idx === -1) return;
|
|
52
|
+
if (idx !== this.entries.length - 1) {
|
|
53
|
+
const [entry] = this.entries.splice(idx, 1);
|
|
54
|
+
this.entries.push(entry);
|
|
55
|
+
}
|
|
56
|
+
this.recompute();
|
|
57
|
+
}
|
|
58
|
+
update() {
|
|
59
|
+
this.recompute();
|
|
60
|
+
}
|
|
49
61
|
size() {
|
|
50
62
|
return this.entries.length;
|
|
51
63
|
}
|
|
@@ -53,9 +65,24 @@ var SheetStack = class {
|
|
|
53
65
|
this.entries = [];
|
|
54
66
|
}
|
|
55
67
|
recompute() {
|
|
68
|
+
let top = null;
|
|
69
|
+
const open = [];
|
|
70
|
+
for (const entry of this.entries) {
|
|
71
|
+
if (!entry.isOpen || entry.isOpen()) {
|
|
72
|
+
top = entry;
|
|
73
|
+
open.push(entry);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (!top && this.entries.length > 0) {
|
|
77
|
+
top = this.entries[this.entries.length - 1];
|
|
78
|
+
}
|
|
56
79
|
this.entries.forEach((entry, i) => {
|
|
57
80
|
entry.setZIndex(BASE_Z + i * STEP);
|
|
58
|
-
entry.setIsTop(
|
|
81
|
+
entry.setIsTop(entry === top);
|
|
82
|
+
if (entry.setDepth) {
|
|
83
|
+
const openIdx = open.indexOf(entry);
|
|
84
|
+
entry.setDepth(openIdx === -1 ? 0 : open.length - 1 - openIdx);
|
|
85
|
+
}
|
|
59
86
|
});
|
|
60
87
|
}
|
|
61
88
|
};
|
|
@@ -340,14 +367,17 @@ function installAutoCollapse(deps) {
|
|
|
340
367
|
const fire = () => {
|
|
341
368
|
if (deps.isDestroyed()) return;
|
|
342
369
|
if (deps.isDragging()) return;
|
|
343
|
-
const
|
|
344
|
-
|
|
370
|
+
const active = deps.resolveSnap(deps.getActiveId());
|
|
371
|
+
if (!active || active.size === 0) return;
|
|
372
|
+
let target = null;
|
|
373
|
+
for (const id of deps.getAllowedIds()) {
|
|
345
374
|
const snap = deps.resolveSnap(id);
|
|
346
|
-
|
|
347
|
-
|
|
375
|
+
if (!snap || snap.size <= 0) continue;
|
|
376
|
+
if (!target || snap.size < target.size) target = snap;
|
|
377
|
+
}
|
|
348
378
|
if (!target) return;
|
|
349
|
-
if (target ===
|
|
350
|
-
deps.snapTo(target);
|
|
379
|
+
if (target.id === active.id || target.size >= active.size) return;
|
|
380
|
+
deps.snapTo(target.id);
|
|
351
381
|
};
|
|
352
382
|
const reset2 = () => {
|
|
353
383
|
clearTimer();
|
|
@@ -358,6 +388,7 @@ function installAutoCollapse(deps) {
|
|
|
358
388
|
}, ms);
|
|
359
389
|
};
|
|
360
390
|
const unsubscribe = deps.on("snap", () => reset2());
|
|
391
|
+
if ((deps.resolveSnap(deps.getActiveId())?.size ?? 0) > 0) reset2();
|
|
361
392
|
return () => {
|
|
362
393
|
clearTimer();
|
|
363
394
|
unsubscribe();
|
|
@@ -370,6 +401,7 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
370
401
|
for (const linked of sheets) {
|
|
371
402
|
if (linked === self) continue;
|
|
372
403
|
try {
|
|
404
|
+
if (linked.state.size === 0) continue;
|
|
373
405
|
const ids = linked.getAllowedIds();
|
|
374
406
|
const target = ids.find((id) => id !== "closed");
|
|
375
407
|
if (target && target !== linked.state.activeId) {
|
|
@@ -416,7 +448,7 @@ function installRoute(deps) {
|
|
|
416
448
|
const onPop = (event) => {
|
|
417
449
|
if (deps.isDestroyed()) return;
|
|
418
450
|
const state2 = event.state;
|
|
419
|
-
if (state2
|
|
451
|
+
if ((!state2 || state2.__bsRouted !== target) && deps.getSize() > 0) {
|
|
420
452
|
routePushed = false;
|
|
421
453
|
void deps.close();
|
|
422
454
|
}
|
|
@@ -570,13 +602,17 @@ function installResizeObserver(deps) {
|
|
|
570
602
|
if (viewportSize2 > 0 && viewportSize2 < max) {
|
|
571
603
|
deps.setMaxAxisSize(viewportSize2);
|
|
572
604
|
}
|
|
605
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
573
606
|
deps.cancelInFlight();
|
|
574
607
|
deps.newCycle();
|
|
575
608
|
const current = deps.resolveActiveSnap();
|
|
576
609
|
const newMax = deps.getMaxAxisSize();
|
|
577
610
|
const targetSize = current ? Math.min(current.size, newMax) : Math.min(deps.getSize(), newMax);
|
|
578
611
|
deps.setSize(targetSize);
|
|
579
|
-
if (current && !deps.isDragging())
|
|
612
|
+
if (current && !deps.isDragging()) {
|
|
613
|
+
deps.applySize(targetSize);
|
|
614
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
615
|
+
}
|
|
580
616
|
};
|
|
581
617
|
let resizeObserver = null;
|
|
582
618
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -691,6 +727,85 @@ function devWarn(...args) {
|
|
|
691
727
|
}
|
|
692
728
|
}
|
|
693
729
|
|
|
730
|
+
// src/core/primitives/overlay-position.ts
|
|
731
|
+
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
732
|
+
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
733
|
+
switch (mode) {
|
|
734
|
+
case "bottom":
|
|
735
|
+
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
736
|
+
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
737
|
+
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
738
|
+
case "top":
|
|
739
|
+
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
740
|
+
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
741
|
+
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
742
|
+
case "left":
|
|
743
|
+
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
744
|
+
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
745
|
+
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
746
|
+
case "right":
|
|
747
|
+
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
748
|
+
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
749
|
+
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
function applyOverlayPosition(ws, mode, position, inset) {
|
|
753
|
+
switch (position) {
|
|
754
|
+
case "top-left":
|
|
755
|
+
ws.top = inset;
|
|
756
|
+
ws.left = inset;
|
|
757
|
+
break;
|
|
758
|
+
case "top-center":
|
|
759
|
+
ws.top = inset;
|
|
760
|
+
ws.left = "50%";
|
|
761
|
+
ws.transform = "translateX(-50%)";
|
|
762
|
+
break;
|
|
763
|
+
case "top-right":
|
|
764
|
+
ws.top = inset;
|
|
765
|
+
ws.right = inset;
|
|
766
|
+
break;
|
|
767
|
+
case "center-left":
|
|
768
|
+
ws.top = "50%";
|
|
769
|
+
ws.left = inset;
|
|
770
|
+
ws.transform = "translateY(-50%)";
|
|
771
|
+
break;
|
|
772
|
+
case "center":
|
|
773
|
+
ws.top = "50%";
|
|
774
|
+
ws.left = "50%";
|
|
775
|
+
ws.transform = "translate(-50%, -50%)";
|
|
776
|
+
break;
|
|
777
|
+
case "center-right":
|
|
778
|
+
ws.top = "50%";
|
|
779
|
+
ws.right = inset;
|
|
780
|
+
ws.transform = "translateY(-50%)";
|
|
781
|
+
break;
|
|
782
|
+
case "bottom-left":
|
|
783
|
+
ws.bottom = inset;
|
|
784
|
+
ws.left = inset;
|
|
785
|
+
break;
|
|
786
|
+
case "bottom-center":
|
|
787
|
+
ws.bottom = inset;
|
|
788
|
+
ws.left = "50%";
|
|
789
|
+
ws.transform = "translateX(-50%)";
|
|
790
|
+
break;
|
|
791
|
+
case "bottom-right":
|
|
792
|
+
ws.bottom = inset;
|
|
793
|
+
ws.right = inset;
|
|
794
|
+
break;
|
|
795
|
+
case "sheet-top-left":
|
|
796
|
+
case "sheet-top-center":
|
|
797
|
+
case "sheet-top-right": {
|
|
798
|
+
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
799
|
+
if (style.top !== void 0) ws.top = style.top;
|
|
800
|
+
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
801
|
+
if (style.left !== void 0) ws.left = style.left;
|
|
802
|
+
if (style.right !== void 0) ws.right = style.right;
|
|
803
|
+
if (style.transform !== void 0) ws.transform = style.transform;
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
694
809
|
// src/core/controllers/scrim-controller.ts
|
|
695
810
|
var VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
|
|
696
811
|
var ScrimController = class {
|
|
@@ -703,6 +818,8 @@ var ScrimController = class {
|
|
|
703
818
|
__publicField(this, "getAllowedIds");
|
|
704
819
|
__publicField(this, "getResolvedSnaps");
|
|
705
820
|
__publicField(this, "snapToFn");
|
|
821
|
+
__publicField(this, "closeFn");
|
|
822
|
+
__publicField(this, "scrimInteractive", false);
|
|
706
823
|
__publicField(this, "scrimMode");
|
|
707
824
|
__publicField(this, "backdropRange");
|
|
708
825
|
__publicField(this, "screenRange");
|
|
@@ -723,6 +840,7 @@ var ScrimController = class {
|
|
|
723
840
|
this.getAllowedIds = deps.getAllowedIds;
|
|
724
841
|
this.getResolvedSnaps = deps.getResolvedSnaps;
|
|
725
842
|
this.snapToFn = deps.snapTo;
|
|
843
|
+
this.closeFn = deps.close;
|
|
726
844
|
this.scrimMode = opts.scrimMode ?? "full";
|
|
727
845
|
const preset = opts.scrimPreset ? SCRIM_PRESETS[opts.scrimPreset] : null;
|
|
728
846
|
this.backdropRange = opts.backdropRange ?? preset?.range ?? [0, 1];
|
|
@@ -864,11 +982,15 @@ var ScrimController = class {
|
|
|
864
982
|
}
|
|
865
983
|
const onClick = () => {
|
|
866
984
|
if (this.isDestroyed()) return;
|
|
985
|
+
if (this.closeFn) {
|
|
986
|
+
this.closeFn();
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
867
989
|
const allowed = this.getAllowedIds();
|
|
868
990
|
const snaps = this.getResolvedSnaps();
|
|
869
991
|
const fallback = allowed.find((id) => {
|
|
870
992
|
const snap = findById(id, snaps);
|
|
871
|
-
return snap !== null && snap.size
|
|
993
|
+
return snap !== null && snap.size === 0;
|
|
872
994
|
});
|
|
873
995
|
if (fallback) this.snapToFn(fallback);
|
|
874
996
|
};
|
|
@@ -885,6 +1007,7 @@ var ScrimController = class {
|
|
|
885
1007
|
if (this.isDestroyed()) return;
|
|
886
1008
|
if (enabled === this.scrimEnabled) return;
|
|
887
1009
|
this.scrimEnabled = enabled;
|
|
1010
|
+
this.invalidateOpacityCache();
|
|
888
1011
|
if (!enabled) {
|
|
889
1012
|
this.savedScrimRanges = {
|
|
890
1013
|
screen: this.screenRange,
|
|
@@ -908,7 +1031,12 @@ var ScrimController = class {
|
|
|
908
1031
|
blur: cfg.blur ?? null,
|
|
909
1032
|
interactive: cfg.interactive
|
|
910
1033
|
});
|
|
911
|
-
this.
|
|
1034
|
+
if (!this.scrimEnabled && this.savedScrimRanges) {
|
|
1035
|
+
this.savedScrimRanges = { screen: cfg.range, backdrop: cfg.range };
|
|
1036
|
+
} else {
|
|
1037
|
+
this.screenRange = cfg.range;
|
|
1038
|
+
this.backdropRange = cfg.range;
|
|
1039
|
+
}
|
|
912
1040
|
}
|
|
913
1041
|
const noop = () => {
|
|
914
1042
|
};
|
|
@@ -958,59 +1086,7 @@ var ScrimController = class {
|
|
|
958
1086
|
wrapper.className = "bs-scrim-overlay";
|
|
959
1087
|
const ws = wrapper.style;
|
|
960
1088
|
ws.position = "absolute";
|
|
961
|
-
|
|
962
|
-
case "top-left":
|
|
963
|
-
ws.top = inset;
|
|
964
|
-
ws.left = inset;
|
|
965
|
-
break;
|
|
966
|
-
case "top-center":
|
|
967
|
-
ws.top = inset;
|
|
968
|
-
ws.left = "50%";
|
|
969
|
-
ws.transform = "translateX(-50%)";
|
|
970
|
-
break;
|
|
971
|
-
case "top-right":
|
|
972
|
-
ws.top = inset;
|
|
973
|
-
ws.right = inset;
|
|
974
|
-
break;
|
|
975
|
-
case "center-left":
|
|
976
|
-
ws.top = "50%";
|
|
977
|
-
ws.left = inset;
|
|
978
|
-
ws.transform = "translateY(-50%)";
|
|
979
|
-
break;
|
|
980
|
-
case "center":
|
|
981
|
-
ws.top = "50%";
|
|
982
|
-
ws.left = "50%";
|
|
983
|
-
ws.transform = "translate(-50%, -50%)";
|
|
984
|
-
break;
|
|
985
|
-
case "center-right":
|
|
986
|
-
ws.top = "50%";
|
|
987
|
-
ws.right = inset;
|
|
988
|
-
ws.transform = "translateY(-50%)";
|
|
989
|
-
break;
|
|
990
|
-
case "bottom-left":
|
|
991
|
-
ws.bottom = inset;
|
|
992
|
-
ws.left = inset;
|
|
993
|
-
break;
|
|
994
|
-
case "bottom-center":
|
|
995
|
-
ws.bottom = inset;
|
|
996
|
-
ws.left = "50%";
|
|
997
|
-
ws.transform = "translateX(-50%)";
|
|
998
|
-
break;
|
|
999
|
-
case "bottom-right":
|
|
1000
|
-
ws.bottom = inset;
|
|
1001
|
-
ws.right = inset;
|
|
1002
|
-
break;
|
|
1003
|
-
case "sheet-top-left":
|
|
1004
|
-
case "sheet-top-center":
|
|
1005
|
-
case "sheet-top-right":
|
|
1006
|
-
applySheetAnchoredPosition(
|
|
1007
|
-
ws,
|
|
1008
|
-
this.mode,
|
|
1009
|
-
position,
|
|
1010
|
-
inset
|
|
1011
|
-
);
|
|
1012
|
-
break;
|
|
1013
|
-
}
|
|
1089
|
+
applyOverlayPosition(ws, this.mode, position, inset);
|
|
1014
1090
|
if (interactive) {
|
|
1015
1091
|
ws.pointerEvents = "auto";
|
|
1016
1092
|
}
|
|
@@ -1069,6 +1145,7 @@ var ScrimController = class {
|
|
|
1069
1145
|
}
|
|
1070
1146
|
}
|
|
1071
1147
|
if (opts.interactive !== void 0) {
|
|
1148
|
+
this.scrimInteractive = opts.interactive;
|
|
1072
1149
|
s.pointerEvents = opts.interactive ? "auto" : "none";
|
|
1073
1150
|
}
|
|
1074
1151
|
}
|
|
@@ -1083,38 +1160,9 @@ var ScrimController = class {
|
|
|
1083
1160
|
const s = this.screenComponent.style;
|
|
1084
1161
|
s.position = "fixed";
|
|
1085
1162
|
s.inset = insetByMode[this.mode];
|
|
1086
|
-
s.pointerEvents = "none";
|
|
1163
|
+
s.pointerEvents = this.scrimInteractive || this.scrimTapToCloseEnabled ? "auto" : "none";
|
|
1087
1164
|
}
|
|
1088
1165
|
};
|
|
1089
|
-
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
1090
|
-
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
1091
|
-
switch (mode) {
|
|
1092
|
-
case "bottom":
|
|
1093
|
-
if (position === "sheet-top-left") return { bottom: sizeOffset, left: inset };
|
|
1094
|
-
if (position === "sheet-top-right") return { bottom: sizeOffset, right: inset };
|
|
1095
|
-
return { bottom: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1096
|
-
case "top":
|
|
1097
|
-
if (position === "sheet-top-left") return { top: sizeOffset, left: inset };
|
|
1098
|
-
if (position === "sheet-top-right") return { top: sizeOffset, right: inset };
|
|
1099
|
-
return { top: sizeOffset, left: "50%", transform: "translateX(-50%)" };
|
|
1100
|
-
case "left":
|
|
1101
|
-
if (position === "sheet-top-left") return { left: sizeOffset, top: inset };
|
|
1102
|
-
if (position === "sheet-top-right") return { left: sizeOffset, bottom: inset };
|
|
1103
|
-
return { left: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1104
|
-
case "right":
|
|
1105
|
-
if (position === "sheet-top-left") return { right: sizeOffset, top: inset };
|
|
1106
|
-
if (position === "sheet-top-right") return { right: sizeOffset, bottom: inset };
|
|
1107
|
-
return { right: sizeOffset, top: "50%", transform: "translateY(-50%)" };
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
function applySheetAnchoredPosition(ws, mode, position, inset) {
|
|
1111
|
-
const style = resolveSheetAnchoredStyle(mode, position, inset);
|
|
1112
|
-
if (style.top !== void 0) ws.top = style.top;
|
|
1113
|
-
if (style.bottom !== void 0) ws.bottom = style.bottom;
|
|
1114
|
-
if (style.left !== void 0) ws.left = style.left;
|
|
1115
|
-
if (style.right !== void 0) ws.right = style.right;
|
|
1116
|
-
if (style.transform !== void 0) ws.transform = style.transform;
|
|
1117
|
-
}
|
|
1118
1166
|
|
|
1119
1167
|
// src/core/animation/animation.ts
|
|
1120
1168
|
var easeOutBack = (t) => {
|
|
@@ -1166,6 +1214,10 @@ var tween = ({
|
|
|
1166
1214
|
promise
|
|
1167
1215
|
};
|
|
1168
1216
|
};
|
|
1217
|
+
var prefersReducedMotion = () => {
|
|
1218
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1219
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1220
|
+
};
|
|
1169
1221
|
|
|
1170
1222
|
// src/core/animation/spring.ts
|
|
1171
1223
|
var DEFAULT_SPRING = {
|
|
@@ -1196,14 +1248,20 @@ var runSpring = ({
|
|
|
1196
1248
|
if (cancelled) return;
|
|
1197
1249
|
const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
|
|
1198
1250
|
lastTime = now;
|
|
1199
|
-
const
|
|
1200
|
-
|
|
1251
|
+
const steps = Math.max(1, Math.ceil(dt * 240));
|
|
1252
|
+
const subDt = dt / steps;
|
|
1253
|
+
let stepsLeft = steps;
|
|
1201
1254
|
while (stepsLeft-- > 0) {
|
|
1202
1255
|
const force = -cfg.stiffness * (x - to) - cfg.damping * v;
|
|
1203
1256
|
const accel = force / cfg.mass;
|
|
1204
1257
|
v += accel * subDt;
|
|
1205
1258
|
x += v * subDt;
|
|
1206
1259
|
}
|
|
1260
|
+
if (!Number.isFinite(x) || !Number.isFinite(v)) {
|
|
1261
|
+
onUpdate(to, 0);
|
|
1262
|
+
resolve();
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1207
1265
|
onUpdate(x, v);
|
|
1208
1266
|
const isAtRest = Math.abs(to - x) < (cfg.restDelta ?? 0.5) && Math.abs(v) < (cfg.restSpeed ?? 0.5);
|
|
1209
1267
|
if (isAtRest) {
|
|
@@ -1378,9 +1436,13 @@ var isVisible = (el) => {
|
|
|
1378
1436
|
var focusables = (root2) => Array.from(root2.querySelectorAll(FOCUSABLE)).filter(
|
|
1379
1437
|
(el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
|
|
1380
1438
|
);
|
|
1439
|
+
var trapStack = [];
|
|
1381
1440
|
var installFocusTrap = (container, options = {}) => {
|
|
1382
1441
|
if (typeof document === "undefined") return () => {
|
|
1383
1442
|
};
|
|
1443
|
+
const token = {};
|
|
1444
|
+
trapStack.push(token);
|
|
1445
|
+
const isActive = () => trapStack[trapStack.length - 1] === token;
|
|
1384
1446
|
const previouslyFocused = document.activeElement;
|
|
1385
1447
|
const focusInitial = () => {
|
|
1386
1448
|
const initial = typeof options.initialFocus === "string" ? container.querySelector(options.initialFocus) : options.initialFocus ?? focusables(container)[0] ?? container;
|
|
@@ -1388,6 +1450,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1388
1450
|
};
|
|
1389
1451
|
focusInitial();
|
|
1390
1452
|
const handleKey = (e) => {
|
|
1453
|
+
if (!isActive()) return;
|
|
1391
1454
|
if (e.key === "Escape" && options.onEscape) {
|
|
1392
1455
|
options.onEscape();
|
|
1393
1456
|
return;
|
|
@@ -1410,6 +1473,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1410
1473
|
}
|
|
1411
1474
|
};
|
|
1412
1475
|
const handleFocusIn = (e) => {
|
|
1476
|
+
if (!isActive()) return;
|
|
1413
1477
|
const target = e.target;
|
|
1414
1478
|
if (target && !container.contains(target)) {
|
|
1415
1479
|
const list = focusables(container);
|
|
@@ -1422,6 +1486,8 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1422
1486
|
return () => {
|
|
1423
1487
|
if (released) return;
|
|
1424
1488
|
released = true;
|
|
1489
|
+
const idx = trapStack.indexOf(token);
|
|
1490
|
+
if (idx !== -1) trapStack.splice(idx, 1);
|
|
1425
1491
|
document.removeEventListener("keydown", handleKey, true);
|
|
1426
1492
|
document.removeEventListener("focusin", handleFocusIn, true);
|
|
1427
1493
|
if (previouslyFocused && document.contains(previouslyFocused)) {
|
|
@@ -1477,11 +1543,17 @@ function createInertSiblings(rootProvider) {
|
|
|
1477
1543
|
return {
|
|
1478
1544
|
apply() {
|
|
1479
1545
|
if (typeof document === "undefined") return;
|
|
1480
|
-
|
|
1481
|
-
|
|
1546
|
+
let top = rootProvider();
|
|
1547
|
+
while (top.parentElement && top.parentElement !== document.body) {
|
|
1548
|
+
top = top.parentElement;
|
|
1549
|
+
}
|
|
1550
|
+
const parent = top.parentElement ?? document.body;
|
|
1482
1551
|
for (const child2 of Array.from(parent.children)) {
|
|
1483
|
-
if (child2 ===
|
|
1552
|
+
if (child2 === top) continue;
|
|
1484
1553
|
if (child2.hasAttribute("inert")) continue;
|
|
1554
|
+
if (child2.classList.contains("bs-backdrop") || child2.classList.contains("bs-screen") || child2.classList.contains("bs-root")) {
|
|
1555
|
+
continue;
|
|
1556
|
+
}
|
|
1485
1557
|
child2.setAttribute("inert", "");
|
|
1486
1558
|
tracked.push(child2);
|
|
1487
1559
|
}
|
|
@@ -1497,7 +1569,6 @@ function createInertSiblings(rootProvider) {
|
|
|
1497
1569
|
var LifecycleController = class {
|
|
1498
1570
|
constructor(deps, opts) {
|
|
1499
1571
|
__publicField(this, "element");
|
|
1500
|
-
__publicField(this, "closeFn");
|
|
1501
1572
|
__publicField(this, "focusTrapEnabled");
|
|
1502
1573
|
__publicField(this, "initialFocus");
|
|
1503
1574
|
__publicField(this, "closeOnEscape");
|
|
@@ -1511,7 +1582,6 @@ var LifecycleController = class {
|
|
|
1511
1582
|
__publicField(this, "installed", false);
|
|
1512
1583
|
__publicField(this, "destroyed", false);
|
|
1513
1584
|
this.element = deps.element;
|
|
1514
|
-
this.closeFn = deps.close;
|
|
1515
1585
|
this.focusTrapEnabled = opts.focusTrap ?? false;
|
|
1516
1586
|
this.initialFocus = opts.initialFocus;
|
|
1517
1587
|
this.closeOnEscape = opts.closeOnEscape ?? true;
|
|
@@ -1521,6 +1591,9 @@ var LifecycleController = class {
|
|
|
1521
1591
|
this.returnFocus = opts.returnFocus;
|
|
1522
1592
|
this.inertSiblings = createInertSiblings(() => this.element);
|
|
1523
1593
|
}
|
|
1594
|
+
get isInstalled() {
|
|
1595
|
+
return this.installed;
|
|
1596
|
+
}
|
|
1524
1597
|
install() {
|
|
1525
1598
|
if (this.destroyed) return;
|
|
1526
1599
|
this.installed = true;
|
|
@@ -1529,8 +1602,7 @@ var LifecycleController = class {
|
|
|
1529
1602
|
}
|
|
1530
1603
|
if (this.focusTrapEnabled && !this.releaseFocusTrap) {
|
|
1531
1604
|
this.releaseFocusTrap = installFocusTrap(this.element, {
|
|
1532
|
-
initialFocus: this.initialFocus
|
|
1533
|
-
onEscape: this.closeOnEscape ? () => void this.closeFn() : void 0
|
|
1605
|
+
initialFocus: this.initialFocus
|
|
1534
1606
|
});
|
|
1535
1607
|
}
|
|
1536
1608
|
if (this.inertSiblingsEnabled && this.shouldApplyInertSiblings()) {
|
|
@@ -1684,10 +1756,11 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
1684
1756
|
};
|
|
1685
1757
|
|
|
1686
1758
|
// src/core/primitives/rubber-band.ts
|
|
1687
|
-
var RUBBER_BAND_FACTOR = 0.55;
|
|
1688
1759
|
function rubberBand(overshoot, maxAxisSize) {
|
|
1689
1760
|
const cap = Math.min(maxAxisSize * 0.15, 80);
|
|
1690
|
-
|
|
1761
|
+
if (cap <= 0) return 0;
|
|
1762
|
+
const abs = Math.abs(overshoot);
|
|
1763
|
+
return Math.sign(overshoot) * (cap * abs / (abs + cap));
|
|
1691
1764
|
}
|
|
1692
1765
|
|
|
1693
1766
|
// src/core/features/soft-keyboard.ts
|
|
@@ -1772,6 +1845,10 @@ var GestureController = class {
|
|
|
1772
1845
|
this.isDragging_ = false;
|
|
1773
1846
|
this.keyboardDismissed = false;
|
|
1774
1847
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1848
|
+
this.deps.emit("dragend", {
|
|
1849
|
+
size: this.deps.getDragContext().size,
|
|
1850
|
+
velocity: 0
|
|
1851
|
+
});
|
|
1775
1852
|
const restoreTo = this.dragStartSize;
|
|
1776
1853
|
void this.deps.animateTo(restoreTo, 0);
|
|
1777
1854
|
}
|
|
@@ -1845,6 +1922,287 @@ function createScrollCache(deps) {
|
|
|
1845
1922
|
};
|
|
1846
1923
|
}
|
|
1847
1924
|
|
|
1925
|
+
// src/core/primitives/anchor-animations.ts
|
|
1926
|
+
var DEFAULT_DURATION3 = 200;
|
|
1927
|
+
var DEFAULT_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
1928
|
+
var PRESET_FRAMES = {
|
|
1929
|
+
fade: {
|
|
1930
|
+
enter: [{ opacity: 0 }, { opacity: 1 }],
|
|
1931
|
+
exit: [{ opacity: 1 }, { opacity: 0 }]
|
|
1932
|
+
},
|
|
1933
|
+
scale: {
|
|
1934
|
+
enter: [
|
|
1935
|
+
{ opacity: 0, transform: "scale(0.85)" },
|
|
1936
|
+
{ opacity: 1, transform: "scale(1)" }
|
|
1937
|
+
],
|
|
1938
|
+
exit: [
|
|
1939
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
1940
|
+
{ opacity: 0, transform: "scale(0.85)" }
|
|
1941
|
+
]
|
|
1942
|
+
},
|
|
1943
|
+
slide: {
|
|
1944
|
+
enter: [
|
|
1945
|
+
{ opacity: 0, transform: "translateY(10px)" },
|
|
1946
|
+
{ opacity: 1, transform: "translateY(0)" }
|
|
1947
|
+
],
|
|
1948
|
+
exit: [
|
|
1949
|
+
{ opacity: 1, transform: "translateY(0)" },
|
|
1950
|
+
{ opacity: 0, transform: "translateY(10px)" }
|
|
1951
|
+
]
|
|
1952
|
+
},
|
|
1953
|
+
pop: {
|
|
1954
|
+
enter: [
|
|
1955
|
+
{ opacity: 0, transform: "scale(0.6)", offset: 0 },
|
|
1956
|
+
{ opacity: 1, transform: "scale(1.06)", offset: 0.7 },
|
|
1957
|
+
{ opacity: 1, transform: "scale(1)", offset: 1 }
|
|
1958
|
+
],
|
|
1959
|
+
exit: [
|
|
1960
|
+
{ opacity: 1, transform: "scale(1)" },
|
|
1961
|
+
{ opacity: 0, transform: "scale(0.6)" }
|
|
1962
|
+
]
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
var INSTANT = {
|
|
1966
|
+
finished: Promise.resolve(),
|
|
1967
|
+
cancel: () => {
|
|
1968
|
+
}
|
|
1969
|
+
};
|
|
1970
|
+
function resolveTransitionFrames(spec, phase) {
|
|
1971
|
+
const fallback = { frames: null, duration: 0, easing: DEFAULT_EASING };
|
|
1972
|
+
if (spec === "none") return fallback;
|
|
1973
|
+
if (spec === void 0 || typeof spec === "string") {
|
|
1974
|
+
const preset2 = PRESET_FRAMES[spec ?? "fade"];
|
|
1975
|
+
return {
|
|
1976
|
+
frames: preset2[phase],
|
|
1977
|
+
duration: DEFAULT_DURATION3,
|
|
1978
|
+
easing: DEFAULT_EASING
|
|
1979
|
+
};
|
|
1980
|
+
}
|
|
1981
|
+
const custom = phase === "enter" ? spec.enter : spec.exit;
|
|
1982
|
+
if (custom) {
|
|
1983
|
+
return {
|
|
1984
|
+
frames: custom,
|
|
1985
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
1986
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
if (spec.preset === "none") return fallback;
|
|
1990
|
+
const preset = PRESET_FRAMES[spec.preset ?? "fade"];
|
|
1991
|
+
return {
|
|
1992
|
+
frames: preset[phase],
|
|
1993
|
+
duration: spec.duration ?? DEFAULT_DURATION3,
|
|
1994
|
+
easing: spec.easing ?? DEFAULT_EASING
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
function runAnchorTransition(el, spec, phase) {
|
|
1998
|
+
const respectReduced = typeof spec === "object" ? spec.respectReducedMotion !== false : true;
|
|
1999
|
+
if (respectReduced && prefersReducedMotion()) return INSTANT;
|
|
2000
|
+
const { frames, duration, easing } = resolveTransitionFrames(spec, phase);
|
|
2001
|
+
if (!frames || duration <= 0) return INSTANT;
|
|
2002
|
+
if (typeof el.animate !== "function") return INSTANT;
|
|
2003
|
+
const animation = el.animate(frames, {
|
|
2004
|
+
duration,
|
|
2005
|
+
easing,
|
|
2006
|
+
fill: "both"
|
|
2007
|
+
});
|
|
2008
|
+
const finished = animation.finished.then(() => void 0).catch(() => void 0);
|
|
2009
|
+
return {
|
|
2010
|
+
finished,
|
|
2011
|
+
cancel: () => {
|
|
2012
|
+
try {
|
|
2013
|
+
animation.cancel();
|
|
2014
|
+
} catch {
|
|
2015
|
+
return;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
// src/core/features/sheet-anchors.ts
|
|
2022
|
+
function attachAnchor(deps, opts) {
|
|
2023
|
+
const doc = deps.host.ownerDocument;
|
|
2024
|
+
const wrapper = doc.createElement("div");
|
|
2025
|
+
wrapper.className = "bs-anchor";
|
|
2026
|
+
const interactive = opts.interactive ?? true;
|
|
2027
|
+
const position = opts.position ?? "sheet-top-right";
|
|
2028
|
+
const isDock = position === "dock-bottom" || position === "dock-top";
|
|
2029
|
+
const ws = wrapper.style;
|
|
2030
|
+
ws.position = "fixed";
|
|
2031
|
+
if (isDock) {
|
|
2032
|
+
ws.left = "0";
|
|
2033
|
+
ws.right = "0";
|
|
2034
|
+
if (position === "dock-bottom") {
|
|
2035
|
+
ws.bottom = "0";
|
|
2036
|
+
} else {
|
|
2037
|
+
ws.top = "0";
|
|
2038
|
+
}
|
|
2039
|
+
} else {
|
|
2040
|
+
applyOverlayPosition(ws, deps.mode, position, opts.inset ?? "16px");
|
|
2041
|
+
}
|
|
2042
|
+
if (opts.fadeRange) {
|
|
2043
|
+
const [r0, r1] = opts.fadeRange;
|
|
2044
|
+
const span = Math.max(r1 - r0, 1e-4);
|
|
2045
|
+
ws.opacity = `clamp(0, calc((var(--bs-progress, 0) - ${r0}) / ${span}), 1)`;
|
|
2046
|
+
}
|
|
2047
|
+
wrapper.appendChild(opts.element);
|
|
2048
|
+
deps.host.appendChild(wrapper);
|
|
2049
|
+
let visible = null;
|
|
2050
|
+
let inFlight = null;
|
|
2051
|
+
const shouldShow = (state2) => {
|
|
2052
|
+
if (typeof opts.showOn === "function") return opts.showOn(state2);
|
|
2053
|
+
if (Array.isArray(opts.showOn)) return opts.showOn.includes(state2.activeId);
|
|
2054
|
+
return isDock || state2.size > 0;
|
|
2055
|
+
};
|
|
2056
|
+
const applyVisibility = (next, animate) => {
|
|
2057
|
+
if (next === visible) return;
|
|
2058
|
+
visible = next;
|
|
2059
|
+
inFlight?.cancel();
|
|
2060
|
+
inFlight = null;
|
|
2061
|
+
wrapper.style.pointerEvents = next && interactive ? "auto" : "none";
|
|
2062
|
+
if (next) {
|
|
2063
|
+
wrapper.style.visibility = "";
|
|
2064
|
+
if (animate) {
|
|
2065
|
+
inFlight = runAnchorTransition(opts.element, opts.animation, "enter");
|
|
2066
|
+
}
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
if (!animate) {
|
|
2070
|
+
wrapper.style.visibility = "hidden";
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
const handle = runAnchorTransition(opts.element, opts.animation, "exit");
|
|
2074
|
+
inFlight = handle;
|
|
2075
|
+
void handle.finished.then(() => {
|
|
2076
|
+
if (inFlight === handle && visible === false) {
|
|
2077
|
+
wrapper.style.visibility = "hidden";
|
|
2078
|
+
}
|
|
2079
|
+
});
|
|
2080
|
+
};
|
|
2081
|
+
const evaluate = (animate) => {
|
|
2082
|
+
if (deps.isDestroyed()) return;
|
|
2083
|
+
applyVisibility(shouldShow(deps.getState()), animate);
|
|
2084
|
+
};
|
|
2085
|
+
const offs = [
|
|
2086
|
+
deps.on("snap", () => evaluate(true)),
|
|
2087
|
+
deps.on("open", () => evaluate(true)),
|
|
2088
|
+
deps.on("close", () => evaluate(true))
|
|
2089
|
+
];
|
|
2090
|
+
evaluate(false);
|
|
2091
|
+
return {
|
|
2092
|
+
wrapper,
|
|
2093
|
+
detach: () => {
|
|
2094
|
+
offs.forEach((off) => off());
|
|
2095
|
+
inFlight?.cancel();
|
|
2096
|
+
inFlight = null;
|
|
2097
|
+
if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);
|
|
2098
|
+
},
|
|
2099
|
+
syncZ: (z) => {
|
|
2100
|
+
wrapper.style.zIndex = String(z);
|
|
2101
|
+
}
|
|
2102
|
+
};
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
// src/core/features/scrim-stages.ts
|
|
2106
|
+
var matchesId = (def, activeId) => {
|
|
2107
|
+
if (def.for === void 0) return false;
|
|
2108
|
+
return Array.isArray(def.for) ? def.for.includes(activeId) : def.for === activeId;
|
|
2109
|
+
};
|
|
2110
|
+
var matchesRange = (def, progress) => {
|
|
2111
|
+
if (!def.forRange) return false;
|
|
2112
|
+
const [from, to] = def.forRange;
|
|
2113
|
+
return progress >= from && progress <= to;
|
|
2114
|
+
};
|
|
2115
|
+
function installScrimStages(deps, opts) {
|
|
2116
|
+
const doc = deps.host.ownerDocument;
|
|
2117
|
+
const entries = opts.stages.map((def) => {
|
|
2118
|
+
const wrapper = doc.createElement("div");
|
|
2119
|
+
wrapper.className = "bs-scrim-stage";
|
|
2120
|
+
const ws = wrapper.style;
|
|
2121
|
+
ws.position = "absolute";
|
|
2122
|
+
applyOverlayPosition(
|
|
2123
|
+
ws,
|
|
2124
|
+
deps.mode,
|
|
2125
|
+
def.position ?? opts.position ?? "center",
|
|
2126
|
+
def.inset ?? opts.inset ?? "16px"
|
|
2127
|
+
);
|
|
2128
|
+
ws.visibility = "hidden";
|
|
2129
|
+
ws.pointerEvents = "none";
|
|
2130
|
+
wrapper.appendChild(def.element);
|
|
2131
|
+
deps.host.appendChild(wrapper);
|
|
2132
|
+
return { def, wrapper, inFlight: null };
|
|
2133
|
+
});
|
|
2134
|
+
let active = null;
|
|
2135
|
+
const resolveActive = () => {
|
|
2136
|
+
const state2 = deps.getState();
|
|
2137
|
+
if (state2.size === 0) {
|
|
2138
|
+
return entries.find((e) => matchesId(e.def, state2.activeId)) ?? null;
|
|
2139
|
+
}
|
|
2140
|
+
return entries.find((e) => matchesId(e.def, state2.activeId)) ?? entries.find((e) => matchesRange(e.def, state2.progress)) ?? null;
|
|
2141
|
+
};
|
|
2142
|
+
const hide = (entry, animate) => {
|
|
2143
|
+
entry.inFlight?.cancel();
|
|
2144
|
+
entry.wrapper.style.pointerEvents = "none";
|
|
2145
|
+
if (!animate) {
|
|
2146
|
+
entry.inFlight = null;
|
|
2147
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2148
|
+
return;
|
|
2149
|
+
}
|
|
2150
|
+
const handle = runAnchorTransition(
|
|
2151
|
+
entry.def.element,
|
|
2152
|
+
entry.def.animation ?? opts.animation,
|
|
2153
|
+
"exit"
|
|
2154
|
+
);
|
|
2155
|
+
entry.inFlight = handle;
|
|
2156
|
+
void handle.finished.then(() => {
|
|
2157
|
+
if (entry.inFlight === handle && active !== entry) {
|
|
2158
|
+
entry.wrapper.style.visibility = "hidden";
|
|
2159
|
+
}
|
|
2160
|
+
});
|
|
2161
|
+
};
|
|
2162
|
+
const show = (entry, animate) => {
|
|
2163
|
+
entry.inFlight?.cancel();
|
|
2164
|
+
entry.inFlight = null;
|
|
2165
|
+
entry.wrapper.style.visibility = "";
|
|
2166
|
+
entry.wrapper.style.pointerEvents = entry.def.interactive ?? opts.interactive ?? false ? "auto" : "none";
|
|
2167
|
+
if (animate) {
|
|
2168
|
+
entry.inFlight = runAnchorTransition(
|
|
2169
|
+
entry.def.element,
|
|
2170
|
+
entry.def.animation ?? opts.animation,
|
|
2171
|
+
"enter"
|
|
2172
|
+
);
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
const update = (animate) => {
|
|
2176
|
+
if (deps.isDestroyed()) return;
|
|
2177
|
+
const next = resolveActive();
|
|
2178
|
+
if (next === active) return;
|
|
2179
|
+
const prev = active;
|
|
2180
|
+
active = next;
|
|
2181
|
+
if (prev) hide(prev, animate);
|
|
2182
|
+
if (next) show(next, animate);
|
|
2183
|
+
};
|
|
2184
|
+
const offs = [
|
|
2185
|
+
deps.on("snap", () => update(true)),
|
|
2186
|
+
deps.on("open", () => update(true)),
|
|
2187
|
+
deps.on("close", () => update(true))
|
|
2188
|
+
];
|
|
2189
|
+
if (entries.some((e) => e.def.forRange)) {
|
|
2190
|
+
offs.push(deps.on("progress", () => update(true)));
|
|
2191
|
+
}
|
|
2192
|
+
update(false);
|
|
2193
|
+
return () => {
|
|
2194
|
+
offs.forEach((off) => off());
|
|
2195
|
+
for (const entry of entries) {
|
|
2196
|
+
entry.inFlight?.cancel();
|
|
2197
|
+
entry.inFlight = null;
|
|
2198
|
+
if (entry.wrapper.parentNode) {
|
|
2199
|
+
entry.wrapper.parentNode.removeChild(entry.wrapper);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
active = null;
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
|
|
1848
2206
|
// src/core/primitives/engine-options.ts
|
|
1849
2207
|
var DEFAULT_FLICK_VELOCITY = 0.65;
|
|
1850
2208
|
var DEFAULT_DRAG_THRESHOLD = 18;
|
|
@@ -1961,6 +2319,12 @@ var BottomSheetEngine = class {
|
|
|
1961
2319
|
__publicField(this, "linkedSheets", []);
|
|
1962
2320
|
__publicField(this, "scrollCache");
|
|
1963
2321
|
__publicField(this, "teardowns", new TeardownStack());
|
|
2322
|
+
__publicField(this, "anchors", []);
|
|
2323
|
+
__publicField(this, "anchorHost", null);
|
|
2324
|
+
__publicField(this, "stackZ", 100);
|
|
2325
|
+
__publicField(this, "detachScrimStages", null);
|
|
2326
|
+
__publicField(this, "stackEffectEnabled", false);
|
|
2327
|
+
__publicField(this, "stackEffectPrimed", false);
|
|
1964
2328
|
__publicField(this, "transformTemplate");
|
|
1965
2329
|
const resolved = resolveEngineOptions(opts, {
|
|
1966
2330
|
shouldApplyInertSiblings: () => {
|
|
@@ -1994,6 +2358,9 @@ var BottomSheetEngine = class {
|
|
|
1994
2358
|
getResolvedSnaps: () => this.snaps.getResolvedSnaps().slice(),
|
|
1995
2359
|
snapTo: (id) => {
|
|
1996
2360
|
void this.snapTo(id);
|
|
2361
|
+
},
|
|
2362
|
+
close: () => {
|
|
2363
|
+
void this.close();
|
|
1997
2364
|
}
|
|
1998
2365
|
},
|
|
1999
2366
|
resolved.scrim
|
|
@@ -2017,6 +2384,7 @@ var BottomSheetEngine = class {
|
|
|
2017
2384
|
);
|
|
2018
2385
|
this.closeOnBack = resolved.closeOnBack;
|
|
2019
2386
|
this.routedTo = opts.routedTo;
|
|
2387
|
+
this.stackEffectEnabled = opts.stackEffect ?? false;
|
|
2020
2388
|
this.snapPointsRaw = opts.snapPoints;
|
|
2021
2389
|
this.persistKey = opts.persistKey;
|
|
2022
2390
|
if (opts.linkedSheets) {
|
|
@@ -2029,7 +2397,7 @@ var BottomSheetEngine = class {
|
|
|
2029
2397
|
this.snapPointsRaw,
|
|
2030
2398
|
resolved.initialAllowed,
|
|
2031
2399
|
this.mode,
|
|
2032
|
-
() => this.handle.offsetHeight,
|
|
2400
|
+
() => layoutAxis(this.mode) === "width" ? this.handle.offsetWidth : this.handle.offsetHeight,
|
|
2033
2401
|
(maxAxisSize) => {
|
|
2034
2402
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2035
2403
|
}
|
|
@@ -2239,11 +2607,6 @@ var BottomSheetEngine = class {
|
|
|
2239
2607
|
}
|
|
2240
2608
|
setAllowed(ids, snap) {
|
|
2241
2609
|
if (this.destroyed) return;
|
|
2242
|
-
const willSnap = snap !== void 0 && ids.includes(snap) || !ids.includes(this.activeId) && ids.length > 0;
|
|
2243
|
-
if (!willSnap) {
|
|
2244
|
-
this.animation.cancel();
|
|
2245
|
-
this.newCycle();
|
|
2246
|
-
}
|
|
2247
2610
|
this.snaps.setAllowedIds(ids);
|
|
2248
2611
|
this.updateAriaSlider();
|
|
2249
2612
|
if (snap && ids.includes(snap)) {
|
|
@@ -2283,6 +2646,79 @@ var BottomSheetEngine = class {
|
|
|
2283
2646
|
setScrimOverlay(opts) {
|
|
2284
2647
|
return this.scrim.setScrimOverlay(opts);
|
|
2285
2648
|
}
|
|
2649
|
+
addAnchor(opts) {
|
|
2650
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2651
|
+
};
|
|
2652
|
+
if (!this.anchorHost) {
|
|
2653
|
+
this.anchorHost = this.rootEl ?? this.element.parentElement ?? document.body;
|
|
2654
|
+
this.anchorHost.style.setProperty("--bs-size", `${this.size}px`);
|
|
2655
|
+
this.anchorHost.style.setProperty(
|
|
2656
|
+
"--bs-progress",
|
|
2657
|
+
String(this.computeProgress(this.size))
|
|
2658
|
+
);
|
|
2659
|
+
}
|
|
2660
|
+
const handle = attachAnchor(
|
|
2661
|
+
{
|
|
2662
|
+
mode: this.mode,
|
|
2663
|
+
host: this.anchorHost,
|
|
2664
|
+
getState: () => ({
|
|
2665
|
+
activeId: this.activeId,
|
|
2666
|
+
size: this.size,
|
|
2667
|
+
progress: this.computeProgress(this.size)
|
|
2668
|
+
}),
|
|
2669
|
+
on: (event, fn) => this.on(event, fn),
|
|
2670
|
+
isDestroyed: () => this.destroyed
|
|
2671
|
+
},
|
|
2672
|
+
opts
|
|
2673
|
+
);
|
|
2674
|
+
handle.syncZ(this.stackZ + 1);
|
|
2675
|
+
this.anchors.push(handle);
|
|
2676
|
+
const detach = () => {
|
|
2677
|
+
const idx = this.anchors.indexOf(handle);
|
|
2678
|
+
if (idx === -1) return;
|
|
2679
|
+
this.anchors.splice(idx, 1);
|
|
2680
|
+
handle.detach();
|
|
2681
|
+
};
|
|
2682
|
+
this.teardowns.add(detach);
|
|
2683
|
+
return detach;
|
|
2684
|
+
}
|
|
2685
|
+
setScrimStages(opts) {
|
|
2686
|
+
if (this.destroyed || typeof document === "undefined") return () => {
|
|
2687
|
+
};
|
|
2688
|
+
this.detachScrimStages?.();
|
|
2689
|
+
this.detachScrimStages = null;
|
|
2690
|
+
if (!opts) return () => {
|
|
2691
|
+
};
|
|
2692
|
+
const host = this.screenComponent?.parentElement;
|
|
2693
|
+
if (!host) {
|
|
2694
|
+
console.warn(
|
|
2695
|
+
"[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
|
|
2696
|
+
);
|
|
2697
|
+
return () => {
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
const detachInstalled = installScrimStages(
|
|
2701
|
+
{
|
|
2702
|
+
mode: this.mode,
|
|
2703
|
+
host,
|
|
2704
|
+
getState: () => ({
|
|
2705
|
+
activeId: this.activeId,
|
|
2706
|
+
size: this.size,
|
|
2707
|
+
progress: this.computeProgress(this.size)
|
|
2708
|
+
}),
|
|
2709
|
+
on: (event, fn) => this.on(event, fn),
|
|
2710
|
+
isDestroyed: () => this.destroyed
|
|
2711
|
+
},
|
|
2712
|
+
opts
|
|
2713
|
+
);
|
|
2714
|
+
const detach = () => {
|
|
2715
|
+
if (this.detachScrimStages === detach) this.detachScrimStages = null;
|
|
2716
|
+
detachInstalled();
|
|
2717
|
+
};
|
|
2718
|
+
this.detachScrimStages = detach;
|
|
2719
|
+
this.teardowns.add(() => this.detachScrimStages?.());
|
|
2720
|
+
return detach;
|
|
2721
|
+
}
|
|
2286
2722
|
getScrimState() {
|
|
2287
2723
|
return { mode: this.scrim.scrimMode, enabled: this.scrim.scrimEnabled };
|
|
2288
2724
|
}
|
|
@@ -2369,24 +2805,45 @@ var BottomSheetEngine = class {
|
|
|
2369
2805
|
getAllowedRange() {
|
|
2370
2806
|
return this.snaps.getAllowedRange();
|
|
2371
2807
|
}
|
|
2808
|
+
allowedIdsBySize() {
|
|
2809
|
+
return this.snaps.getAllowedIds().slice().sort(
|
|
2810
|
+
(a, b) => (this.snaps.findById(a)?.size ?? 0) - (this.snaps.findById(b)?.size ?? 0)
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2372
2813
|
updateAriaSlider() {
|
|
2373
|
-
this.aria.setValue(this.
|
|
2814
|
+
this.aria.setValue(this.allowedIdsBySize(), this.activeId);
|
|
2374
2815
|
}
|
|
2375
2816
|
registerInStack() {
|
|
2376
2817
|
this.teardowns.add(sheetStack.push({
|
|
2377
2818
|
id: this.id,
|
|
2378
2819
|
setZIndex: (z) => {
|
|
2820
|
+
this.stackZ = z;
|
|
2379
2821
|
this.element.style.zIndex = String(z);
|
|
2380
2822
|
if (this.backdrop) this.backdrop.style.zIndex = String(z - 1);
|
|
2823
|
+
for (const anchor of this.anchors) anchor.syncZ(z + 1);
|
|
2381
2824
|
},
|
|
2382
2825
|
setIsTop: (isTop) => {
|
|
2383
2826
|
this.isTopSheet = isTop;
|
|
2384
2827
|
if (this.backdrop) {
|
|
2385
2828
|
this.backdrop.style.display = isTop ? "" : "none";
|
|
2386
2829
|
}
|
|
2387
|
-
}
|
|
2830
|
+
},
|
|
2831
|
+
isOpen: () => this.size > 0,
|
|
2832
|
+
setDepth: (depth) => this.applyStackDepth(depth)
|
|
2388
2833
|
}));
|
|
2389
2834
|
}
|
|
2835
|
+
applyStackDepth(depth) {
|
|
2836
|
+
if (!this.stackEffectEnabled) return;
|
|
2837
|
+
this.element.setAttribute("data-stack-depth", String(depth));
|
|
2838
|
+
if (!this.stackEffectPrimed) {
|
|
2839
|
+
this.stackEffectPrimed = true;
|
|
2840
|
+
const isVertical = this.mode === "bottom" || this.mode === "top";
|
|
2841
|
+
this.element.style.transformOrigin = isVertical ? "50% 100%" : "0% 50%";
|
|
2842
|
+
this.element.style.transition = "scale 320ms cubic-bezier(0.29, 1.04, 0.84, 0.99)";
|
|
2843
|
+
}
|
|
2844
|
+
const scale = Math.max(1 - depth * 0.04, 0.86);
|
|
2845
|
+
this.element.style.scale = scale === 1 ? "" : String(scale);
|
|
2846
|
+
}
|
|
2390
2847
|
attach() {
|
|
2391
2848
|
this.gesture = new GestureController({
|
|
2392
2849
|
handle: this.handle,
|
|
@@ -2446,7 +2903,7 @@ var BottomSheetEngine = class {
|
|
|
2446
2903
|
container: this.scrollContainer,
|
|
2447
2904
|
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2448
2905
|
isAnimating: () => this.animation.isAnimating,
|
|
2449
|
-
getAllowedIds: () => this.
|
|
2906
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2450
2907
|
getActiveId: () => this.activeId,
|
|
2451
2908
|
snapTo: (id) => {
|
|
2452
2909
|
void this.snapTo(id);
|
|
@@ -2475,11 +2932,13 @@ var BottomSheetEngine = class {
|
|
|
2475
2932
|
},
|
|
2476
2933
|
newCycle: () => {
|
|
2477
2934
|
this.newCycle();
|
|
2478
|
-
}
|
|
2935
|
+
},
|
|
2936
|
+
isAnimating: () => this.animation.isAnimating,
|
|
2937
|
+
resyncAfterCancel: () => this.resyncAfterResize()
|
|
2479
2938
|
}));
|
|
2480
2939
|
if (this.lifecycle.closeOnEscape) {
|
|
2481
2940
|
const onKey = (e) => {
|
|
2482
|
-
if (this.destroyed) return;
|
|
2941
|
+
if (this.destroyed || e.defaultPrevented) return;
|
|
2483
2942
|
if (e.key === "Escape" && this.isTopSheet && this.size > 0) {
|
|
2484
2943
|
void this.close();
|
|
2485
2944
|
}
|
|
@@ -2511,7 +2970,7 @@ var BottomSheetEngine = class {
|
|
|
2511
2970
|
handle: this.handle,
|
|
2512
2971
|
mode: this.mode,
|
|
2513
2972
|
isDestroyed: () => this.destroyed,
|
|
2514
|
-
getAllowedIds: () => this.
|
|
2973
|
+
getAllowedIds: () => this.allowedIdsBySize(),
|
|
2515
2974
|
getActiveId: () => this.activeId,
|
|
2516
2975
|
snapTo: (id) => {
|
|
2517
2976
|
void this.snapTo(id);
|
|
@@ -2532,6 +2991,7 @@ var BottomSheetEngine = class {
|
|
|
2532
2991
|
});
|
|
2533
2992
|
if (!target) return;
|
|
2534
2993
|
const previousId = this.activeId;
|
|
2994
|
+
if (target.id === previousId && target.size === this.size) return;
|
|
2535
2995
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
2536
2996
|
const restore = this.snaps.findById(previousId);
|
|
2537
2997
|
if (restore) {
|
|
@@ -2540,6 +3000,7 @@ var BottomSheetEngine = class {
|
|
|
2540
3000
|
return;
|
|
2541
3001
|
}
|
|
2542
3002
|
const previousSize = this.size;
|
|
3003
|
+
const previousSnapSize = this.snaps.findById(previousId)?.size;
|
|
2543
3004
|
this.scrollCache.cache(previousId, previousSize, target.size);
|
|
2544
3005
|
this.activeId = target.id;
|
|
2545
3006
|
void this.animation.animateTo(target.size, velocity).then(() => {
|
|
@@ -2548,9 +3009,10 @@ var BottomSheetEngine = class {
|
|
|
2548
3009
|
this.updateAriaSlider();
|
|
2549
3010
|
this.emit("snap", { id: target.id, size: target.size });
|
|
2550
3011
|
this.haptic();
|
|
2551
|
-
if (
|
|
3012
|
+
if (previousSnapSize === 0 && target.size > 0) {
|
|
2552
3013
|
this.emit("open", { id: target.id });
|
|
2553
3014
|
this.handleOpen();
|
|
3015
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
2554
3016
|
}
|
|
2555
3017
|
if (target.size === 0) {
|
|
2556
3018
|
this.emit("close", void 0);
|
|
@@ -2576,6 +3038,9 @@ var BottomSheetEngine = class {
|
|
|
2576
3038
|
if (this.scrimParent) {
|
|
2577
3039
|
this.scrimParent.style.setProperty("--bs-size", `${size}px`);
|
|
2578
3040
|
}
|
|
3041
|
+
if (this.anchorHost && this.anchorHost !== this.scrimParent) {
|
|
3042
|
+
this.anchorHost.style.setProperty("--bs-size", `${size}px`);
|
|
3043
|
+
}
|
|
2579
3044
|
}
|
|
2580
3045
|
const progress = this.computeProgress(size);
|
|
2581
3046
|
const progressChanged = this.progressWriteSentinel.shouldWrite(
|
|
@@ -2584,6 +3049,9 @@ var BottomSheetEngine = class {
|
|
|
2584
3049
|
);
|
|
2585
3050
|
if (progressChanged) {
|
|
2586
3051
|
style.setProperty("--bs-progress", String(progress));
|
|
3052
|
+
if (this.anchorHost) {
|
|
3053
|
+
this.anchorHost.style.setProperty("--bs-progress", String(progress));
|
|
3054
|
+
}
|
|
2587
3055
|
}
|
|
2588
3056
|
this.scrim.applyOpacity(progress, progressChanged);
|
|
2589
3057
|
if (progressChanged && this.bus.listenerCount("progress") > 0) {
|
|
@@ -2598,6 +3066,7 @@ var BottomSheetEngine = class {
|
|
|
2598
3066
|
return Math.min(Math.max((size - min) / (max - min), 0), 1);
|
|
2599
3067
|
}
|
|
2600
3068
|
handleOpen() {
|
|
3069
|
+
sheetStack.promote(this.id);
|
|
2601
3070
|
try {
|
|
2602
3071
|
this.lifecycle.install();
|
|
2603
3072
|
} catch (err) {
|
|
@@ -2611,8 +3080,24 @@ var BottomSheetEngine = class {
|
|
|
2611
3080
|
});
|
|
2612
3081
|
}
|
|
2613
3082
|
}
|
|
3083
|
+
resyncAfterResize() {
|
|
3084
|
+
if (this.destroyed) return;
|
|
3085
|
+
const target = this.snaps.findById(this.activeId);
|
|
3086
|
+
if (!target) return;
|
|
3087
|
+
this.updateAriaSlider();
|
|
3088
|
+
this.emit("snap", { id: target.id, size: target.size });
|
|
3089
|
+
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3090
|
+
this.emit("open", { id: target.id });
|
|
3091
|
+
this.handleOpen();
|
|
3092
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
3093
|
+
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3094
|
+
this.emit("close", void 0);
|
|
3095
|
+
this.handleClose();
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
2614
3098
|
handleClose() {
|
|
2615
3099
|
this.lifecycle.release();
|
|
3100
|
+
sheetStack.update();
|
|
2616
3101
|
}
|
|
2617
3102
|
};
|
|
2618
3103
|
|
|
@@ -2630,17 +3115,18 @@ function createBottomSheet(opts) {
|
|
|
2630
3115
|
const attach = (refs) => {
|
|
2631
3116
|
if (engine) engine.destroy();
|
|
2632
3117
|
const { onSnap, ...engineOpts } = opts;
|
|
2633
|
-
|
|
3118
|
+
const created = new BottomSheetEngine({ ...engineOpts, ...refs });
|
|
3119
|
+
engine = created;
|
|
2634
3120
|
if (onSnap) {
|
|
2635
|
-
|
|
3121
|
+
created.on("snap", (payload) => onSnap(payload.id));
|
|
2636
3122
|
}
|
|
2637
3123
|
for (const entry of pending) {
|
|
2638
|
-
entry.engineUnsub =
|
|
3124
|
+
entry.engineUnsub = created.on(entry.event, entry.fn);
|
|
2639
3125
|
}
|
|
2640
3126
|
pending.length = 0;
|
|
2641
3127
|
return () => {
|
|
2642
|
-
|
|
2643
|
-
engine = null;
|
|
3128
|
+
created.destroy();
|
|
3129
|
+
if (engine === created) engine = null;
|
|
2644
3130
|
};
|
|
2645
3131
|
};
|
|
2646
3132
|
return {
|
|
@@ -2664,6 +3150,14 @@ function createBottomSheet(opts) {
|
|
|
2664
3150
|
open: (id) => engine?.open(id) ?? Promise.resolve(),
|
|
2665
3151
|
close: () => engine?.close() ?? Promise.resolve(),
|
|
2666
3152
|
setAllowed: (ids, snap) => engine?.setAllowed(ids, snap),
|
|
3153
|
+
setSnapPoints: (points, allowed) => engine?.setSnapPoints(points, allowed),
|
|
3154
|
+
setScrim: (scrimOpts) => engine?.setScrim(scrimOpts),
|
|
3155
|
+
setScrimOverlay: (overlayOpts) => engine?.setScrimOverlay(overlayOpts) ?? (() => {
|
|
3156
|
+
}),
|
|
3157
|
+
addAnchor: (anchorOpts) => engine?.addAnchor(anchorOpts) ?? (() => {
|
|
3158
|
+
}),
|
|
3159
|
+
setScrimStages: (stagesOpts) => engine?.setScrimStages(stagesOpts) ?? (() => {
|
|
3160
|
+
}),
|
|
2667
3161
|
destroy: () => {
|
|
2668
3162
|
engine?.destroy();
|
|
2669
3163
|
engine = null;
|
|
@@ -2685,7 +3179,7 @@ function BottomSheet($$anchor, $$props) {
|
|
|
2685
3179
|
let screenEl = $2__namespace.state(void 0);
|
|
2686
3180
|
let viewState = $2__namespace.state($2__namespace.proxy({
|
|
2687
3181
|
size: 0,
|
|
2688
|
-
activeId: $$props.initial ?? $$props.snapPoints[0]?.id ?? "default",
|
|
3182
|
+
activeId: svelte.untrack(() => $$props.initial ?? $$props.snapPoints[0]?.id ?? "default"),
|
|
2689
3183
|
isDragging: false,
|
|
2690
3184
|
isAnimating: false,
|
|
2691
3185
|
progress: 0
|