@surdeddd/bottom-sheet 0.9.1 → 0.10.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 +108 -66
- package/dist/{BottomSheetEngine-CBRcBwV-.d.ts → BottomSheetEngine-DRjCU73e.d.ts} +6 -5
- package/dist/{BottomSheetEngine-BcyruNP1.d.cts → BottomSheetEngine-DzsIwD28.d.cts} +6 -5
- package/dist/element.cjs +161 -99
- package/dist/element.d.cts +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +161 -99
- package/dist/index.cjs +155 -115
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +155 -115
- 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 +34 -25
- package/dist/overlay.d.cts +3 -0
- package/dist/overlay.d.ts +3 -0
- package/dist/overlay.js +34 -25
- package/dist/preact.d.cts +2 -1
- package/dist/preact.d.ts +2 -1
- package/dist/qwik.cjs +179 -93
- package/dist/qwik.d.cts +11 -2
- package/dist/qwik.d.ts +11 -2
- package/dist/qwik.js +179 -93
- package/dist/react.cjs +266 -181
- package/dist/react.d.cts +26 -4
- package/dist/react.d.ts +26 -4
- package/dist/react.js +266 -181
- package/dist/solid.cjs +145 -92
- package/dist/solid.d.cts +14 -4
- package/dist/solid.d.ts +14 -4
- package/dist/solid.js +145 -92
- package/dist/solid.source.jsx +145 -92
- package/dist/styles.css +17 -1
- package/dist/svelte-core.cjs +128 -90
- package/dist/svelte-core.js +128 -90
- package/dist/svelte-src/BottomSheet.svelte +6 -0
- package/dist/svelte.cjs +130 -90
- package/dist/svelte.d.cts +2 -0
- package/dist/svelte.d.ts +2 -0
- package/dist/svelte.js +130 -90
- package/dist/teleport-7uYNiEAT.d.cts +3 -0
- package/dist/teleport-7uYNiEAT.d.ts +3 -0
- package/dist/vue.cjs +136 -91
- package/dist/vue.d.cts +3 -1
- package/dist/vue.d.ts +3 -1
- package/dist/vue.js +136 -91
- package/package.json +6 -6
package/dist/svelte.js
CHANGED
|
@@ -185,11 +185,18 @@ var resolveSnap = (point, mode, measureFit) => {
|
|
|
185
185
|
return Math.max(0, el.getBoundingClientRect().width);
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
+
// src/core/primitives/devWarn.ts
|
|
189
|
+
function devWarn(...args) {
|
|
190
|
+
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
|
|
191
|
+
console.warn(...args);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
188
195
|
// src/core/primitives/snap-points.ts
|
|
189
196
|
var resolveSnapList = (points, mode, measureFit) => points.map((p) => {
|
|
190
197
|
const raw = resolveSnap(p.size, mode, measureFit);
|
|
191
198
|
if (!Number.isFinite(raw) || raw < 0) {
|
|
192
|
-
|
|
199
|
+
devWarn(
|
|
193
200
|
`[BottomSheet] snap "${p.id}" resolved to invalid size (${String(p.size)} \u2192 ${raw}); clamped to 0.`
|
|
194
201
|
);
|
|
195
202
|
return { id: p.id, size: 0 };
|
|
@@ -201,7 +208,7 @@ var auditVhUsage = (points) => {
|
|
|
201
208
|
for (const p of points) {
|
|
202
209
|
if (typeof p.size !== "string") continue;
|
|
203
210
|
if (!VH_NOT_DVH.test(p.size)) continue;
|
|
204
|
-
|
|
211
|
+
devWarn(
|
|
205
212
|
`[BottomSheet] snap "${p.id}" uses "vh" \u2014 prefer "dvh" on mobile (iOS Safari URL bar makes vh unstable). See https://web.dev/blog/viewport-units`
|
|
206
213
|
);
|
|
207
214
|
}
|
|
@@ -255,6 +262,26 @@ var findDragSettleTarget = (input) => {
|
|
|
255
262
|
);
|
|
256
263
|
};
|
|
257
264
|
|
|
265
|
+
// src/core/primitives/cancelable-emit.ts
|
|
266
|
+
function emitCancelable(emit, base, warnLabel) {
|
|
267
|
+
let cancelled = false;
|
|
268
|
+
let frozen = false;
|
|
269
|
+
emit({
|
|
270
|
+
...base,
|
|
271
|
+
cancel: () => {
|
|
272
|
+
if (frozen) {
|
|
273
|
+
devWarn(
|
|
274
|
+
`[BottomSheet] ${warnLabel}.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener.`
|
|
275
|
+
);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
cancelled = true;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
frozen = true;
|
|
282
|
+
return cancelled;
|
|
283
|
+
}
|
|
284
|
+
|
|
258
285
|
// src/core/primitives/snap-resolver.ts
|
|
259
286
|
var SnapResolver = class {
|
|
260
287
|
constructor(raw, allowed, mode, measureFit, onMaxAxisSizeChange) {
|
|
@@ -399,7 +426,9 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
399
426
|
try {
|
|
400
427
|
if (linked.state.size === 0) continue;
|
|
401
428
|
const ids = linked.getAllowedIds();
|
|
402
|
-
const
|
|
429
|
+
const resolved = linked.getResolvedSnaps();
|
|
430
|
+
const sizeOf = (id) => resolved.find((s) => s.id === id)?.size ?? 0;
|
|
431
|
+
const target = ids.find((id) => sizeOf(id) > 0);
|
|
403
432
|
if (target && target !== linked.state.activeId) {
|
|
404
433
|
void linked.snapTo(target);
|
|
405
434
|
}
|
|
@@ -616,11 +645,15 @@ function installVisualViewport(deps) {
|
|
|
616
645
|
if (clamp < deps.getMaxAxisSize()) {
|
|
617
646
|
deps.setMaxAxisSize(clamp);
|
|
618
647
|
}
|
|
648
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
649
|
+
deps.cancelInFlight();
|
|
650
|
+
deps.newCycle();
|
|
619
651
|
const max = deps.getMaxAxisSize();
|
|
620
652
|
deps.setSize(Math.min(deps.getSize(), max));
|
|
621
653
|
const current = deps.resolveActiveSnap();
|
|
622
654
|
if (current && !deps.isDragging()) {
|
|
623
655
|
deps.applySize(Math.min(current.size, max));
|
|
656
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
624
657
|
} else {
|
|
625
658
|
deps.applySize(deps.getSize());
|
|
626
659
|
}
|
|
@@ -761,6 +794,54 @@ function installFitObserver(deps) {
|
|
|
761
794
|
};
|
|
762
795
|
}
|
|
763
796
|
|
|
797
|
+
// src/core/features/max-height-controller.ts
|
|
798
|
+
function createMaxHeightController(deps) {
|
|
799
|
+
let maxHeightCap;
|
|
800
|
+
let maxHeightRaw;
|
|
801
|
+
const resolveCap = () => {
|
|
802
|
+
const raw = maxHeightRaw;
|
|
803
|
+
if (raw === void 0) {
|
|
804
|
+
maxHeightCap = void 0;
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
if (typeof raw === "number") {
|
|
808
|
+
maxHeightCap = raw;
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
if (typeof window === "undefined") return;
|
|
812
|
+
const measured = resolveSnap(raw, deps.mode);
|
|
813
|
+
maxHeightCap = measured > 0 ? measured : void 0;
|
|
814
|
+
};
|
|
815
|
+
const clampTo = () => {
|
|
816
|
+
if (maxHeightCap === void 0) return;
|
|
817
|
+
if (deps.getMaxAxisSize() > maxHeightCap) {
|
|
818
|
+
deps.setMaxAxisSize(maxHeightCap);
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
return {
|
|
822
|
+
setRadius(r) {
|
|
823
|
+
deps.element.style.setProperty(
|
|
824
|
+
"--bs-radius",
|
|
825
|
+
typeof r === "number" ? `${r}px` : r
|
|
826
|
+
);
|
|
827
|
+
},
|
|
828
|
+
setMaxHeight(h) {
|
|
829
|
+
const value = typeof h === "number" ? `${h}px` : h;
|
|
830
|
+
const axis = layoutAxis(deps.mode);
|
|
831
|
+
deps.element.style.setProperty(
|
|
832
|
+
axis === "height" ? "max-height" : "max-width",
|
|
833
|
+
value
|
|
834
|
+
);
|
|
835
|
+
maxHeightRaw = h;
|
|
836
|
+
resolveCap();
|
|
837
|
+
deps.recompute();
|
|
838
|
+
},
|
|
839
|
+
resolveCap,
|
|
840
|
+
clampTo,
|
|
841
|
+
getCap: () => maxHeightCap
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
|
|
764
845
|
// src/core/features/fit-measurement.ts
|
|
765
846
|
var measureSheetNatural = (element, content, vertical) => {
|
|
766
847
|
if (!content) {
|
|
@@ -892,13 +973,6 @@ var WriteSentinel = class {
|
|
|
892
973
|
}
|
|
893
974
|
};
|
|
894
975
|
|
|
895
|
-
// src/core/primitives/devWarn.ts
|
|
896
|
-
function devWarn(...args) {
|
|
897
|
-
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
|
|
898
|
-
console.warn(...args);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
976
|
// src/core/primitives/overlay-position.ts
|
|
903
977
|
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
904
978
|
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
@@ -2544,8 +2618,7 @@ var BottomSheetEngine = class {
|
|
|
2544
2618
|
__publicField(this, "disableCloseFlag");
|
|
2545
2619
|
__publicField(this, "disableDragFlag");
|
|
2546
2620
|
__publicField(this, "closeOnRouteChange");
|
|
2547
|
-
__publicField(this, "
|
|
2548
|
-
__publicField(this, "maxHeightRaw");
|
|
2621
|
+
__publicField(this, "maxHeight");
|
|
2549
2622
|
__publicField(this, "snapPointsRaw");
|
|
2550
2623
|
__publicField(this, "snaps");
|
|
2551
2624
|
__publicField(this, "activeId");
|
|
@@ -2656,11 +2729,20 @@ var BottomSheetEngine = class {
|
|
|
2656
2729
|
auditVhUsage(this.snapPointsRaw);
|
|
2657
2730
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
2658
2731
|
this.rootEl = this.element.closest(".bs-root");
|
|
2732
|
+
this.maxHeight = createMaxHeightController({
|
|
2733
|
+
element: this.element,
|
|
2734
|
+
mode: this.mode,
|
|
2735
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2736
|
+
setMaxAxisSize: (size) => {
|
|
2737
|
+
this.snaps.setMaxAxisSize(size);
|
|
2738
|
+
},
|
|
2739
|
+
recompute: () => this.recompute()
|
|
2740
|
+
});
|
|
2659
2741
|
this.fitDeps = {
|
|
2660
2742
|
element: this.element,
|
|
2661
2743
|
scrollContainer: this.scrollContainer,
|
|
2662
2744
|
mode: this.mode,
|
|
2663
|
-
getMaxHeightCap: () => this.
|
|
2745
|
+
getMaxHeightCap: () => this.maxHeight.getCap()
|
|
2664
2746
|
};
|
|
2665
2747
|
this.snaps = new SnapResolver(
|
|
2666
2748
|
this.snapPointsRaw,
|
|
@@ -2771,7 +2853,7 @@ var BottomSheetEngine = class {
|
|
|
2771
2853
|
}
|
|
2772
2854
|
use(plugin) {
|
|
2773
2855
|
if (this.destroyed) {
|
|
2774
|
-
|
|
2856
|
+
devWarn(
|
|
2775
2857
|
`[BottomSheet] use("${plugin.name}") called on destroyed engine \u2014 ignored.`
|
|
2776
2858
|
);
|
|
2777
2859
|
return this;
|
|
@@ -2813,6 +2895,9 @@ var BottomSheetEngine = class {
|
|
|
2813
2895
|
getAllowedIds() {
|
|
2814
2896
|
return this.snaps.getAllowedIds().slice();
|
|
2815
2897
|
}
|
|
2898
|
+
getResolvedSnaps() {
|
|
2899
|
+
return this.snaps.getResolvedSnaps();
|
|
2900
|
+
}
|
|
2816
2901
|
async snapTo(id, velocityOrOpts = 0, _skipBeforeSnap = false) {
|
|
2817
2902
|
if (this.destroyed) return;
|
|
2818
2903
|
const opts = typeof velocityOrOpts === "object" ? velocityOrOpts : { velocity: velocityOrOpts };
|
|
@@ -2821,11 +2906,11 @@ var BottomSheetEngine = class {
|
|
|
2821
2906
|
if (externalSignal?.aborted) return;
|
|
2822
2907
|
const target = this.snaps.findById(id);
|
|
2823
2908
|
if (!target) {
|
|
2824
|
-
|
|
2909
|
+
devWarn(`[BottomSheet] unknown snap id: ${id}`);
|
|
2825
2910
|
return;
|
|
2826
2911
|
}
|
|
2827
2912
|
if (!this.snaps.getAllowedIds().includes(id)) {
|
|
2828
|
-
|
|
2913
|
+
devWarn(`[BottomSheet] snap "${id}" is not in allowed list`);
|
|
2829
2914
|
return;
|
|
2830
2915
|
}
|
|
2831
2916
|
if (!_skipBeforeSnap && this.emitBeforeSnap(target, this.activeId)) {
|
|
@@ -2957,42 +3042,11 @@ var BottomSheetEngine = class {
|
|
|
2957
3042
|
}
|
|
2958
3043
|
setRadius(r) {
|
|
2959
3044
|
if (this.destroyed) return;
|
|
2960
|
-
this.
|
|
2961
|
-
"--bs-radius",
|
|
2962
|
-
typeof r === "number" ? `${r}px` : r
|
|
2963
|
-
);
|
|
3045
|
+
this.maxHeight.setRadius(r);
|
|
2964
3046
|
}
|
|
2965
3047
|
setMaxHeight(h) {
|
|
2966
3048
|
if (this.destroyed) return;
|
|
2967
|
-
|
|
2968
|
-
const axis = layoutAxis(this.mode);
|
|
2969
|
-
this.element.style.setProperty(
|
|
2970
|
-
axis === "height" ? "max-height" : "max-width",
|
|
2971
|
-
value
|
|
2972
|
-
);
|
|
2973
|
-
this.maxHeightRaw = h;
|
|
2974
|
-
this.resolveMaxHeightCap();
|
|
2975
|
-
this.recompute();
|
|
2976
|
-
}
|
|
2977
|
-
resolveMaxHeightCap() {
|
|
2978
|
-
const raw = this.maxHeightRaw;
|
|
2979
|
-
if (raw === void 0) {
|
|
2980
|
-
this.maxHeightCap = void 0;
|
|
2981
|
-
return;
|
|
2982
|
-
}
|
|
2983
|
-
if (typeof raw === "number") {
|
|
2984
|
-
this.maxHeightCap = raw;
|
|
2985
|
-
return;
|
|
2986
|
-
}
|
|
2987
|
-
if (typeof window === "undefined") return;
|
|
2988
|
-
const measured = resolveSnap(raw, this.mode);
|
|
2989
|
-
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2990
|
-
}
|
|
2991
|
-
clampToMaxHeight() {
|
|
2992
|
-
if (this.maxHeightCap === void 0) return;
|
|
2993
|
-
if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
|
|
2994
|
-
this.snaps.setMaxAxisSize(this.maxHeightCap);
|
|
2995
|
-
}
|
|
3049
|
+
this.maxHeight.setMaxHeight(h);
|
|
2996
3050
|
}
|
|
2997
3051
|
setAllowed(ids, snap) {
|
|
2998
3052
|
if (this.destroyed) return;
|
|
@@ -3080,7 +3134,7 @@ var BottomSheetEngine = class {
|
|
|
3080
3134
|
};
|
|
3081
3135
|
const host = this.screenComponent?.parentElement;
|
|
3082
3136
|
if (!host) {
|
|
3083
|
-
|
|
3137
|
+
devWarn(
|
|
3084
3138
|
"[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
|
|
3085
3139
|
);
|
|
3086
3140
|
return () => {
|
|
@@ -3130,9 +3184,9 @@ var BottomSheetEngine = class {
|
|
|
3130
3184
|
}
|
|
3131
3185
|
recompute() {
|
|
3132
3186
|
if (this.destroyed) return;
|
|
3133
|
-
this.
|
|
3187
|
+
this.maxHeight.resolveCap();
|
|
3134
3188
|
this.snaps.recompute();
|
|
3135
|
-
this.
|
|
3189
|
+
this.maxHeight.clampTo();
|
|
3136
3190
|
this.scrim.invalidateOpacityCache();
|
|
3137
3191
|
if (this.gesture?.isDragging) return;
|
|
3138
3192
|
const current = this.snaps.findById(this.activeId);
|
|
@@ -3182,42 +3236,18 @@ var BottomSheetEngine = class {
|
|
|
3182
3236
|
return this.currentAbort.signal;
|
|
3183
3237
|
}
|
|
3184
3238
|
emitBeforeSnap(target, previousId) {
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
previousId,
|
|
3191
|
-
cancel: () => {
|
|
3192
|
-
if (frozen) {
|
|
3193
|
-
console.warn(
|
|
3194
|
-
"[BottomSheet] before-snap.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
|
|
3195
|
-
);
|
|
3196
|
-
return;
|
|
3197
|
-
}
|
|
3198
|
-
cancelled = true;
|
|
3199
|
-
}
|
|
3200
|
-
});
|
|
3201
|
-
frozen = true;
|
|
3202
|
-
return cancelled;
|
|
3239
|
+
return emitCancelable(
|
|
3240
|
+
(payload) => this.emit("before-snap", payload),
|
|
3241
|
+
{ id: target.id, size: target.size, previousId },
|
|
3242
|
+
"before-snap"
|
|
3243
|
+
);
|
|
3203
3244
|
}
|
|
3204
3245
|
emitBeforeClose(reason) {
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
if (frozen) {
|
|
3211
|
-
console.warn(
|
|
3212
|
-
"[BottomSheet] before-close.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
|
|
3213
|
-
);
|
|
3214
|
-
return;
|
|
3215
|
-
}
|
|
3216
|
-
cancelled = true;
|
|
3217
|
-
}
|
|
3218
|
-
});
|
|
3219
|
-
frozen = true;
|
|
3220
|
-
return cancelled;
|
|
3246
|
+
return emitCancelable(
|
|
3247
|
+
(payload) => this.emit("before-close", payload),
|
|
3248
|
+
{ reason },
|
|
3249
|
+
"before-close"
|
|
3250
|
+
);
|
|
3221
3251
|
}
|
|
3222
3252
|
applyAutoAriaLabelledBy() {
|
|
3223
3253
|
if (typeof document === "undefined") return;
|
|
@@ -3232,16 +3262,16 @@ var BottomSheetEngine = class {
|
|
|
3232
3262
|
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3233
3263
|
}
|
|
3234
3264
|
recomputeSnaps() {
|
|
3235
|
-
this.
|
|
3265
|
+
this.maxHeight.resolveCap();
|
|
3236
3266
|
this.snaps.setRaw(this.snapPointsRaw);
|
|
3237
|
-
this.
|
|
3267
|
+
this.maxHeight.clampTo();
|
|
3238
3268
|
this.scrim.invalidateOpacityCache();
|
|
3239
3269
|
}
|
|
3240
3270
|
auditDuplicateSnapIds(points) {
|
|
3241
3271
|
const seen = /* @__PURE__ */ new Set();
|
|
3242
3272
|
for (const p of points) {
|
|
3243
3273
|
if (seen.has(p.id)) {
|
|
3244
|
-
|
|
3274
|
+
devWarn(
|
|
3245
3275
|
`[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
|
|
3246
3276
|
);
|
|
3247
3277
|
}
|
|
@@ -3408,7 +3438,15 @@ var BottomSheetEngine = class {
|
|
|
3408
3438
|
setSize: (size) => {
|
|
3409
3439
|
this.size = size;
|
|
3410
3440
|
},
|
|
3411
|
-
applySize: (size) => this.applySize(size)
|
|
3441
|
+
applySize: (size) => this.applySize(size),
|
|
3442
|
+
cancelInFlight: () => {
|
|
3443
|
+
this.animation.cancel();
|
|
3444
|
+
},
|
|
3445
|
+
newCycle: () => {
|
|
3446
|
+
this.newCycle();
|
|
3447
|
+
},
|
|
3448
|
+
isAnimating: () => this.animation.isAnimating,
|
|
3449
|
+
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3412
3450
|
}));
|
|
3413
3451
|
}
|
|
3414
3452
|
this.teardowns.add(installSliderKeyboard({
|
|
@@ -3773,6 +3811,8 @@ function BottomSheet($$anchor, $$props) {
|
|
|
3773
3811
|
sync();
|
|
3774
3812
|
$$props.ondragend?.();
|
|
3775
3813
|
});
|
|
3814
|
+
if ($$props.ondrag) engine.on("drag", (payload) => $$props.ondrag(payload));
|
|
3815
|
+
if ($$props.onprogress) engine.on("progress", (payload) => $$props.onprogress(payload));
|
|
3776
3816
|
});
|
|
3777
3817
|
onDestroy(() => {
|
|
3778
3818
|
restoreTeleport?.();
|