@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/react.cjs
CHANGED
|
@@ -193,11 +193,18 @@ var resolveSnap = (point, mode, measureFit) => {
|
|
|
193
193
|
return Math.max(0, el.getBoundingClientRect().width);
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
+
// src/core/primitives/devWarn.ts
|
|
197
|
+
function devWarn(...args) {
|
|
198
|
+
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
|
|
199
|
+
console.warn(...args);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
196
203
|
// src/core/primitives/snap-points.ts
|
|
197
204
|
var resolveSnapList = (points, mode, measureFit) => points.map((p) => {
|
|
198
205
|
const raw = resolveSnap(p.size, mode, measureFit);
|
|
199
206
|
if (!Number.isFinite(raw) || raw < 0) {
|
|
200
|
-
|
|
207
|
+
devWarn(
|
|
201
208
|
`[BottomSheet] snap "${p.id}" resolved to invalid size (${String(p.size)} \u2192 ${raw}); clamped to 0.`
|
|
202
209
|
);
|
|
203
210
|
return { id: p.id, size: 0 };
|
|
@@ -209,7 +216,7 @@ var auditVhUsage = (points) => {
|
|
|
209
216
|
for (const p of points) {
|
|
210
217
|
if (typeof p.size !== "string") continue;
|
|
211
218
|
if (!VH_NOT_DVH.test(p.size)) continue;
|
|
212
|
-
|
|
219
|
+
devWarn(
|
|
213
220
|
`[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`
|
|
214
221
|
);
|
|
215
222
|
}
|
|
@@ -263,6 +270,26 @@ var findDragSettleTarget = (input) => {
|
|
|
263
270
|
);
|
|
264
271
|
};
|
|
265
272
|
|
|
273
|
+
// src/core/primitives/cancelable-emit.ts
|
|
274
|
+
function emitCancelable(emit, base, warnLabel) {
|
|
275
|
+
let cancelled = false;
|
|
276
|
+
let frozen = false;
|
|
277
|
+
emit({
|
|
278
|
+
...base,
|
|
279
|
+
cancel: () => {
|
|
280
|
+
if (frozen) {
|
|
281
|
+
devWarn(
|
|
282
|
+
`[BottomSheet] ${warnLabel}.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener.`
|
|
283
|
+
);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
cancelled = true;
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
frozen = true;
|
|
290
|
+
return cancelled;
|
|
291
|
+
}
|
|
292
|
+
|
|
266
293
|
// src/core/primitives/snap-resolver.ts
|
|
267
294
|
var SnapResolver = class {
|
|
268
295
|
constructor(raw, allowed, mode, measureFit, onMaxAxisSizeChange) {
|
|
@@ -407,7 +434,9 @@ function notifyLinkedSheets(sheets, self) {
|
|
|
407
434
|
try {
|
|
408
435
|
if (linked.state.size === 0) continue;
|
|
409
436
|
const ids = linked.getAllowedIds();
|
|
410
|
-
const
|
|
437
|
+
const resolved = linked.getResolvedSnaps();
|
|
438
|
+
const sizeOf = (id) => resolved.find((s) => s.id === id)?.size ?? 0;
|
|
439
|
+
const target = ids.find((id) => sizeOf(id) > 0);
|
|
411
440
|
if (target && target !== linked.state.activeId) {
|
|
412
441
|
void linked.snapTo(target);
|
|
413
442
|
}
|
|
@@ -624,11 +653,15 @@ function installVisualViewport(deps) {
|
|
|
624
653
|
if (clamp < deps.getMaxAxisSize()) {
|
|
625
654
|
deps.setMaxAxisSize(clamp);
|
|
626
655
|
}
|
|
656
|
+
const wasAnimating = deps.isAnimating?.() ?? false;
|
|
657
|
+
deps.cancelInFlight();
|
|
658
|
+
deps.newCycle();
|
|
627
659
|
const max = deps.getMaxAxisSize();
|
|
628
660
|
deps.setSize(Math.min(deps.getSize(), max));
|
|
629
661
|
const current = deps.resolveActiveSnap();
|
|
630
662
|
if (current && !deps.isDragging()) {
|
|
631
663
|
deps.applySize(Math.min(current.size, max));
|
|
664
|
+
if (wasAnimating) deps.resyncAfterCancel?.();
|
|
632
665
|
} else {
|
|
633
666
|
deps.applySize(deps.getSize());
|
|
634
667
|
}
|
|
@@ -769,6 +802,54 @@ function installFitObserver(deps) {
|
|
|
769
802
|
};
|
|
770
803
|
}
|
|
771
804
|
|
|
805
|
+
// src/core/features/max-height-controller.ts
|
|
806
|
+
function createMaxHeightController(deps) {
|
|
807
|
+
let maxHeightCap;
|
|
808
|
+
let maxHeightRaw;
|
|
809
|
+
const resolveCap = () => {
|
|
810
|
+
const raw = maxHeightRaw;
|
|
811
|
+
if (raw === void 0) {
|
|
812
|
+
maxHeightCap = void 0;
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
if (typeof raw === "number") {
|
|
816
|
+
maxHeightCap = raw;
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
if (typeof window === "undefined") return;
|
|
820
|
+
const measured = resolveSnap(raw, deps.mode);
|
|
821
|
+
maxHeightCap = measured > 0 ? measured : void 0;
|
|
822
|
+
};
|
|
823
|
+
const clampTo = () => {
|
|
824
|
+
if (maxHeightCap === void 0) return;
|
|
825
|
+
if (deps.getMaxAxisSize() > maxHeightCap) {
|
|
826
|
+
deps.setMaxAxisSize(maxHeightCap);
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
return {
|
|
830
|
+
setRadius(r) {
|
|
831
|
+
deps.element.style.setProperty(
|
|
832
|
+
"--bs-radius",
|
|
833
|
+
typeof r === "number" ? `${r}px` : r
|
|
834
|
+
);
|
|
835
|
+
},
|
|
836
|
+
setMaxHeight(h) {
|
|
837
|
+
const value = typeof h === "number" ? `${h}px` : h;
|
|
838
|
+
const axis = layoutAxis(deps.mode);
|
|
839
|
+
deps.element.style.setProperty(
|
|
840
|
+
axis === "height" ? "max-height" : "max-width",
|
|
841
|
+
value
|
|
842
|
+
);
|
|
843
|
+
maxHeightRaw = h;
|
|
844
|
+
resolveCap();
|
|
845
|
+
deps.recompute();
|
|
846
|
+
},
|
|
847
|
+
resolveCap,
|
|
848
|
+
clampTo,
|
|
849
|
+
getCap: () => maxHeightCap
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
|
|
772
853
|
// src/core/features/fit-measurement.ts
|
|
773
854
|
var measureSheetNatural = (element, content, vertical) => {
|
|
774
855
|
if (!content) {
|
|
@@ -900,13 +981,6 @@ var WriteSentinel = class {
|
|
|
900
981
|
}
|
|
901
982
|
};
|
|
902
983
|
|
|
903
|
-
// src/core/primitives/devWarn.ts
|
|
904
|
-
function devWarn(...args) {
|
|
905
|
-
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
|
|
906
|
-
console.warn(...args);
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
|
|
910
984
|
// src/core/primitives/overlay-position.ts
|
|
911
985
|
function resolveSheetAnchoredStyle(mode, position, inset) {
|
|
912
986
|
const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
|
|
@@ -2552,8 +2626,7 @@ var BottomSheetEngine = class {
|
|
|
2552
2626
|
__publicField(this, "disableCloseFlag");
|
|
2553
2627
|
__publicField(this, "disableDragFlag");
|
|
2554
2628
|
__publicField(this, "closeOnRouteChange");
|
|
2555
|
-
__publicField(this, "
|
|
2556
|
-
__publicField(this, "maxHeightRaw");
|
|
2629
|
+
__publicField(this, "maxHeight");
|
|
2557
2630
|
__publicField(this, "snapPointsRaw");
|
|
2558
2631
|
__publicField(this, "snaps");
|
|
2559
2632
|
__publicField(this, "activeId");
|
|
@@ -2664,11 +2737,20 @@ var BottomSheetEngine = class {
|
|
|
2664
2737
|
auditVhUsage(this.snapPointsRaw);
|
|
2665
2738
|
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
2666
2739
|
this.rootEl = this.element.closest(".bs-root");
|
|
2740
|
+
this.maxHeight = createMaxHeightController({
|
|
2741
|
+
element: this.element,
|
|
2742
|
+
mode: this.mode,
|
|
2743
|
+
getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
|
|
2744
|
+
setMaxAxisSize: (size) => {
|
|
2745
|
+
this.snaps.setMaxAxisSize(size);
|
|
2746
|
+
},
|
|
2747
|
+
recompute: () => this.recompute()
|
|
2748
|
+
});
|
|
2667
2749
|
this.fitDeps = {
|
|
2668
2750
|
element: this.element,
|
|
2669
2751
|
scrollContainer: this.scrollContainer,
|
|
2670
2752
|
mode: this.mode,
|
|
2671
|
-
getMaxHeightCap: () => this.
|
|
2753
|
+
getMaxHeightCap: () => this.maxHeight.getCap()
|
|
2672
2754
|
};
|
|
2673
2755
|
this.snaps = new SnapResolver(
|
|
2674
2756
|
this.snapPointsRaw,
|
|
@@ -2779,7 +2861,7 @@ var BottomSheetEngine = class {
|
|
|
2779
2861
|
}
|
|
2780
2862
|
use(plugin) {
|
|
2781
2863
|
if (this.destroyed) {
|
|
2782
|
-
|
|
2864
|
+
devWarn(
|
|
2783
2865
|
`[BottomSheet] use("${plugin.name}") called on destroyed engine \u2014 ignored.`
|
|
2784
2866
|
);
|
|
2785
2867
|
return this;
|
|
@@ -2821,6 +2903,9 @@ var BottomSheetEngine = class {
|
|
|
2821
2903
|
getAllowedIds() {
|
|
2822
2904
|
return this.snaps.getAllowedIds().slice();
|
|
2823
2905
|
}
|
|
2906
|
+
getResolvedSnaps() {
|
|
2907
|
+
return this.snaps.getResolvedSnaps();
|
|
2908
|
+
}
|
|
2824
2909
|
async snapTo(id, velocityOrOpts = 0, _skipBeforeSnap = false) {
|
|
2825
2910
|
if (this.destroyed) return;
|
|
2826
2911
|
const opts = typeof velocityOrOpts === "object" ? velocityOrOpts : { velocity: velocityOrOpts };
|
|
@@ -2829,11 +2914,11 @@ var BottomSheetEngine = class {
|
|
|
2829
2914
|
if (externalSignal?.aborted) return;
|
|
2830
2915
|
const target = this.snaps.findById(id);
|
|
2831
2916
|
if (!target) {
|
|
2832
|
-
|
|
2917
|
+
devWarn(`[BottomSheet] unknown snap id: ${id}`);
|
|
2833
2918
|
return;
|
|
2834
2919
|
}
|
|
2835
2920
|
if (!this.snaps.getAllowedIds().includes(id)) {
|
|
2836
|
-
|
|
2921
|
+
devWarn(`[BottomSheet] snap "${id}" is not in allowed list`);
|
|
2837
2922
|
return;
|
|
2838
2923
|
}
|
|
2839
2924
|
if (!_skipBeforeSnap && this.emitBeforeSnap(target, this.activeId)) {
|
|
@@ -2965,42 +3050,11 @@ var BottomSheetEngine = class {
|
|
|
2965
3050
|
}
|
|
2966
3051
|
setRadius(r) {
|
|
2967
3052
|
if (this.destroyed) return;
|
|
2968
|
-
this.
|
|
2969
|
-
"--bs-radius",
|
|
2970
|
-
typeof r === "number" ? `${r}px` : r
|
|
2971
|
-
);
|
|
3053
|
+
this.maxHeight.setRadius(r);
|
|
2972
3054
|
}
|
|
2973
3055
|
setMaxHeight(h) {
|
|
2974
3056
|
if (this.destroyed) return;
|
|
2975
|
-
|
|
2976
|
-
const axis = layoutAxis(this.mode);
|
|
2977
|
-
this.element.style.setProperty(
|
|
2978
|
-
axis === "height" ? "max-height" : "max-width",
|
|
2979
|
-
value
|
|
2980
|
-
);
|
|
2981
|
-
this.maxHeightRaw = h;
|
|
2982
|
-
this.resolveMaxHeightCap();
|
|
2983
|
-
this.recompute();
|
|
2984
|
-
}
|
|
2985
|
-
resolveMaxHeightCap() {
|
|
2986
|
-
const raw = this.maxHeightRaw;
|
|
2987
|
-
if (raw === void 0) {
|
|
2988
|
-
this.maxHeightCap = void 0;
|
|
2989
|
-
return;
|
|
2990
|
-
}
|
|
2991
|
-
if (typeof raw === "number") {
|
|
2992
|
-
this.maxHeightCap = raw;
|
|
2993
|
-
return;
|
|
2994
|
-
}
|
|
2995
|
-
if (typeof window === "undefined") return;
|
|
2996
|
-
const measured = resolveSnap(raw, this.mode);
|
|
2997
|
-
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2998
|
-
}
|
|
2999
|
-
clampToMaxHeight() {
|
|
3000
|
-
if (this.maxHeightCap === void 0) return;
|
|
3001
|
-
if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
|
|
3002
|
-
this.snaps.setMaxAxisSize(this.maxHeightCap);
|
|
3003
|
-
}
|
|
3057
|
+
this.maxHeight.setMaxHeight(h);
|
|
3004
3058
|
}
|
|
3005
3059
|
setAllowed(ids, snap) {
|
|
3006
3060
|
if (this.destroyed) return;
|
|
@@ -3088,7 +3142,7 @@ var BottomSheetEngine = class {
|
|
|
3088
3142
|
};
|
|
3089
3143
|
const host = this.screenComponent?.parentElement;
|
|
3090
3144
|
if (!host) {
|
|
3091
|
-
|
|
3145
|
+
devWarn(
|
|
3092
3146
|
"[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
|
|
3093
3147
|
);
|
|
3094
3148
|
return () => {
|
|
@@ -3138,9 +3192,9 @@ var BottomSheetEngine = class {
|
|
|
3138
3192
|
}
|
|
3139
3193
|
recompute() {
|
|
3140
3194
|
if (this.destroyed) return;
|
|
3141
|
-
this.
|
|
3195
|
+
this.maxHeight.resolveCap();
|
|
3142
3196
|
this.snaps.recompute();
|
|
3143
|
-
this.
|
|
3197
|
+
this.maxHeight.clampTo();
|
|
3144
3198
|
this.scrim.invalidateOpacityCache();
|
|
3145
3199
|
if (this.gesture?.isDragging) return;
|
|
3146
3200
|
const current = this.snaps.findById(this.activeId);
|
|
@@ -3190,42 +3244,18 @@ var BottomSheetEngine = class {
|
|
|
3190
3244
|
return this.currentAbort.signal;
|
|
3191
3245
|
}
|
|
3192
3246
|
emitBeforeSnap(target, previousId) {
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
previousId,
|
|
3199
|
-
cancel: () => {
|
|
3200
|
-
if (frozen) {
|
|
3201
|
-
console.warn(
|
|
3202
|
-
"[BottomSheet] before-snap.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
|
|
3203
|
-
);
|
|
3204
|
-
return;
|
|
3205
|
-
}
|
|
3206
|
-
cancelled = true;
|
|
3207
|
-
}
|
|
3208
|
-
});
|
|
3209
|
-
frozen = true;
|
|
3210
|
-
return cancelled;
|
|
3247
|
+
return emitCancelable(
|
|
3248
|
+
(payload) => this.emit("before-snap", payload),
|
|
3249
|
+
{ id: target.id, size: target.size, previousId },
|
|
3250
|
+
"before-snap"
|
|
3251
|
+
);
|
|
3211
3252
|
}
|
|
3212
3253
|
emitBeforeClose(reason) {
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
if (frozen) {
|
|
3219
|
-
console.warn(
|
|
3220
|
-
"[BottomSheet] before-close.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
|
|
3221
|
-
);
|
|
3222
|
-
return;
|
|
3223
|
-
}
|
|
3224
|
-
cancelled = true;
|
|
3225
|
-
}
|
|
3226
|
-
});
|
|
3227
|
-
frozen = true;
|
|
3228
|
-
return cancelled;
|
|
3254
|
+
return emitCancelable(
|
|
3255
|
+
(payload) => this.emit("before-close", payload),
|
|
3256
|
+
{ reason },
|
|
3257
|
+
"before-close"
|
|
3258
|
+
);
|
|
3229
3259
|
}
|
|
3230
3260
|
applyAutoAriaLabelledBy() {
|
|
3231
3261
|
if (typeof document === "undefined") return;
|
|
@@ -3240,16 +3270,16 @@ var BottomSheetEngine = class {
|
|
|
3240
3270
|
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3241
3271
|
}
|
|
3242
3272
|
recomputeSnaps() {
|
|
3243
|
-
this.
|
|
3273
|
+
this.maxHeight.resolveCap();
|
|
3244
3274
|
this.snaps.setRaw(this.snapPointsRaw);
|
|
3245
|
-
this.
|
|
3275
|
+
this.maxHeight.clampTo();
|
|
3246
3276
|
this.scrim.invalidateOpacityCache();
|
|
3247
3277
|
}
|
|
3248
3278
|
auditDuplicateSnapIds(points) {
|
|
3249
3279
|
const seen = /* @__PURE__ */ new Set();
|
|
3250
3280
|
for (const p of points) {
|
|
3251
3281
|
if (seen.has(p.id)) {
|
|
3252
|
-
|
|
3282
|
+
devWarn(
|
|
3253
3283
|
`[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
|
|
3254
3284
|
);
|
|
3255
3285
|
}
|
|
@@ -3416,7 +3446,15 @@ var BottomSheetEngine = class {
|
|
|
3416
3446
|
setSize: (size) => {
|
|
3417
3447
|
this.size = size;
|
|
3418
3448
|
},
|
|
3419
|
-
applySize: (size) => this.applySize(size)
|
|
3449
|
+
applySize: (size) => this.applySize(size),
|
|
3450
|
+
cancelInFlight: () => {
|
|
3451
|
+
this.animation.cancel();
|
|
3452
|
+
},
|
|
3453
|
+
newCycle: () => {
|
|
3454
|
+
this.newCycle();
|
|
3455
|
+
},
|
|
3456
|
+
isAnimating: () => this.animation.isAnimating,
|
|
3457
|
+
resyncAfterCancel: () => this.resyncAfterResize()
|
|
3420
3458
|
}));
|
|
3421
3459
|
}
|
|
3422
3460
|
this.teardowns.add(installSliderKeyboard({
|
|
@@ -3577,6 +3615,72 @@ var BottomSheetEngine = class {
|
|
|
3577
3615
|
sheetStack.update();
|
|
3578
3616
|
}
|
|
3579
3617
|
};
|
|
3618
|
+
function useEnginePropSync(engineRef, opts) {
|
|
3619
|
+
const optsRef = react.useRef(opts);
|
|
3620
|
+
optsRef.current = opts;
|
|
3621
|
+
const allowedKey = (opts.allowed ?? opts.snapPoints.map((p) => p.id)).join(
|
|
3622
|
+
"\0"
|
|
3623
|
+
);
|
|
3624
|
+
const defKey = opts.snapPoints.map((p) => `${p.id}${String(p.size)}`).join("\0");
|
|
3625
|
+
const defApplied = react.useRef(false);
|
|
3626
|
+
react.useEffect(() => {
|
|
3627
|
+
if (!defApplied.current) {
|
|
3628
|
+
defApplied.current = true;
|
|
3629
|
+
return;
|
|
3630
|
+
}
|
|
3631
|
+
const engine = engineRef.current;
|
|
3632
|
+
if (!engine) return;
|
|
3633
|
+
const current = optsRef.current;
|
|
3634
|
+
engine.setSnapPoints(
|
|
3635
|
+
current.snapPoints,
|
|
3636
|
+
current.allowed ? Array.from(current.allowed) : void 0
|
|
3637
|
+
);
|
|
3638
|
+
}, [defKey]);
|
|
3639
|
+
react.useEffect(() => {
|
|
3640
|
+
if (!engineRef.current) return;
|
|
3641
|
+
const ids = opts.allowed ? Array.from(opts.allowed) : opts.snapPoints.map((p) => p.id);
|
|
3642
|
+
engineRef.current.setAllowed(ids);
|
|
3643
|
+
}, [allowedKey]);
|
|
3644
|
+
react.useEffect(() => {
|
|
3645
|
+
if (!engineRef.current) return;
|
|
3646
|
+
if (opts.backdropColor !== void 0) {
|
|
3647
|
+
engineRef.current.setScrimColor(opts.backdropColor);
|
|
3648
|
+
}
|
|
3649
|
+
}, [opts.backdropColor]);
|
|
3650
|
+
react.useEffect(() => {
|
|
3651
|
+
if (!engineRef.current) return;
|
|
3652
|
+
if (opts.backdropOpacity !== void 0) {
|
|
3653
|
+
engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
|
|
3654
|
+
}
|
|
3655
|
+
}, [opts.backdropOpacity]);
|
|
3656
|
+
react.useEffect(() => {
|
|
3657
|
+
if (!engineRef.current) return;
|
|
3658
|
+
if (opts.radius !== void 0) {
|
|
3659
|
+
engineRef.current.setRadius(opts.radius);
|
|
3660
|
+
}
|
|
3661
|
+
}, [opts.radius]);
|
|
3662
|
+
react.useEffect(() => {
|
|
3663
|
+
if (!engineRef.current) return;
|
|
3664
|
+
if (opts.maxHeight !== void 0) {
|
|
3665
|
+
engineRef.current.setMaxHeight(opts.maxHeight);
|
|
3666
|
+
}
|
|
3667
|
+
}, [opts.maxHeight]);
|
|
3668
|
+
react.useEffect(() => {
|
|
3669
|
+
if (opts.persistent !== void 0) {
|
|
3670
|
+
engineRef.current?.setPersistent(opts.persistent);
|
|
3671
|
+
}
|
|
3672
|
+
}, [opts.persistent]);
|
|
3673
|
+
react.useEffect(() => {
|
|
3674
|
+
if (opts.disableClose !== void 0) {
|
|
3675
|
+
engineRef.current?.setDisableClose(opts.disableClose);
|
|
3676
|
+
}
|
|
3677
|
+
}, [opts.disableClose]);
|
|
3678
|
+
react.useEffect(() => {
|
|
3679
|
+
if (opts.disableDrag !== void 0) {
|
|
3680
|
+
engineRef.current?.setDisableDrag(opts.disableDrag);
|
|
3681
|
+
}
|
|
3682
|
+
}, [opts.disableDrag]);
|
|
3683
|
+
}
|
|
3580
3684
|
|
|
3581
3685
|
// src/core/features/teleport.ts
|
|
3582
3686
|
var resolveTeleportTarget = (target) => {
|
|
@@ -3671,6 +3775,12 @@ function useBottomSheet(opts) {
|
|
|
3671
3775
|
engine.on("before-close", (payload) => {
|
|
3672
3776
|
optsRef.current.onBeforeClose?.(payload);
|
|
3673
3777
|
}),
|
|
3778
|
+
engine.on("open", (payload) => {
|
|
3779
|
+
optsRef.current.onOpen?.(payload.id);
|
|
3780
|
+
}),
|
|
3781
|
+
engine.on("close", () => {
|
|
3782
|
+
optsRef.current.onClose?.();
|
|
3783
|
+
}),
|
|
3674
3784
|
engine.on("opened", (payload) => {
|
|
3675
3785
|
optsRef.current.onOpened?.(payload.id);
|
|
3676
3786
|
}),
|
|
@@ -3686,6 +3796,20 @@ function useBottomSheet(opts) {
|
|
|
3686
3796
|
optsRef.current.onDragEnd?.(payload);
|
|
3687
3797
|
})
|
|
3688
3798
|
];
|
|
3799
|
+
if (optsRef.current.onDrag) {
|
|
3800
|
+
offs.push(
|
|
3801
|
+
engine.on("drag", (payload) => {
|
|
3802
|
+
optsRef.current.onDrag?.(payload);
|
|
3803
|
+
})
|
|
3804
|
+
);
|
|
3805
|
+
}
|
|
3806
|
+
if (optsRef.current.onProgress) {
|
|
3807
|
+
offs.push(
|
|
3808
|
+
engine.on("progress", (payload) => {
|
|
3809
|
+
optsRef.current.onProgress?.(payload);
|
|
3810
|
+
})
|
|
3811
|
+
);
|
|
3812
|
+
}
|
|
3689
3813
|
return () => {
|
|
3690
3814
|
offs.forEach((off) => off());
|
|
3691
3815
|
restoreTeleport?.();
|
|
@@ -3695,68 +3819,17 @@ function useBottomSheet(opts) {
|
|
|
3695
3819
|
setMounted((n) => n + 1);
|
|
3696
3820
|
};
|
|
3697
3821
|
}, []);
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
if (!engine) return;
|
|
3710
|
-
const current = optsRef.current;
|
|
3711
|
-
engine.setSnapPoints(
|
|
3712
|
-
current.snapPoints,
|
|
3713
|
-
current.allowed ? Array.from(current.allowed) : void 0
|
|
3714
|
-
);
|
|
3715
|
-
}, [defKey]);
|
|
3716
|
-
react.useEffect(() => {
|
|
3717
|
-
if (!engineRef.current) return;
|
|
3718
|
-
const ids = opts.allowed ? Array.from(opts.allowed) : opts.snapPoints.map((p) => p.id);
|
|
3719
|
-
engineRef.current.setAllowed(ids);
|
|
3720
|
-
}, [allowedKey]);
|
|
3721
|
-
react.useEffect(() => {
|
|
3722
|
-
if (!engineRef.current) return;
|
|
3723
|
-
if (opts.backdropColor !== void 0) {
|
|
3724
|
-
engineRef.current.setScrimColor(opts.backdropColor);
|
|
3725
|
-
}
|
|
3726
|
-
}, [opts.backdropColor]);
|
|
3727
|
-
react.useEffect(() => {
|
|
3728
|
-
if (!engineRef.current) return;
|
|
3729
|
-
if (opts.backdropOpacity !== void 0) {
|
|
3730
|
-
engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
|
|
3731
|
-
}
|
|
3732
|
-
}, [opts.backdropOpacity]);
|
|
3733
|
-
react.useEffect(() => {
|
|
3734
|
-
if (!engineRef.current) return;
|
|
3735
|
-
if (opts.radius !== void 0) {
|
|
3736
|
-
engineRef.current.setRadius(opts.radius);
|
|
3737
|
-
}
|
|
3738
|
-
}, [opts.radius]);
|
|
3739
|
-
react.useEffect(() => {
|
|
3740
|
-
if (!engineRef.current) return;
|
|
3741
|
-
if (opts.maxHeight !== void 0) {
|
|
3742
|
-
engineRef.current.setMaxHeight(opts.maxHeight);
|
|
3743
|
-
}
|
|
3744
|
-
}, [opts.maxHeight]);
|
|
3745
|
-
react.useEffect(() => {
|
|
3746
|
-
if (opts.persistent !== void 0) {
|
|
3747
|
-
engineRef.current?.setPersistent(opts.persistent);
|
|
3748
|
-
}
|
|
3749
|
-
}, [opts.persistent]);
|
|
3750
|
-
react.useEffect(() => {
|
|
3751
|
-
if (opts.disableClose !== void 0) {
|
|
3752
|
-
engineRef.current?.setDisableClose(opts.disableClose);
|
|
3753
|
-
}
|
|
3754
|
-
}, [opts.disableClose]);
|
|
3755
|
-
react.useEffect(() => {
|
|
3756
|
-
if (opts.disableDrag !== void 0) {
|
|
3757
|
-
engineRef.current?.setDisableDrag(opts.disableDrag);
|
|
3758
|
-
}
|
|
3759
|
-
}, [opts.disableDrag]);
|
|
3822
|
+
useEnginePropSync(engineRef, {
|
|
3823
|
+
snapPoints: opts.snapPoints,
|
|
3824
|
+
allowed: opts.allowed,
|
|
3825
|
+
backdropColor: opts.backdropColor,
|
|
3826
|
+
backdropOpacity: opts.backdropOpacity,
|
|
3827
|
+
radius: opts.radius,
|
|
3828
|
+
maxHeight: opts.maxHeight,
|
|
3829
|
+
persistent: opts.persistent,
|
|
3830
|
+
disableClose: opts.disableClose,
|
|
3831
|
+
disableDrag: opts.disableDrag
|
|
3832
|
+
});
|
|
3760
3833
|
const subscribe = react.useCallback((fn) => {
|
|
3761
3834
|
subscribersRef.current.add(fn);
|
|
3762
3835
|
return () => subscribersRef.current.delete(fn);
|
|
@@ -3865,10 +3938,14 @@ var BottomSheet = react.forwardRef(
|
|
|
3865
3938
|
scrimStages,
|
|
3866
3939
|
onChange,
|
|
3867
3940
|
onBeforeClose,
|
|
3941
|
+
onOpen,
|
|
3942
|
+
onClose,
|
|
3868
3943
|
onOpened,
|
|
3869
3944
|
onClosed,
|
|
3870
3945
|
onDragStart,
|
|
3871
3946
|
onDragEnd,
|
|
3947
|
+
onDrag,
|
|
3948
|
+
onProgress,
|
|
3872
3949
|
ariaLabel = "Bottom sheet",
|
|
3873
3950
|
ariaLabelledBy,
|
|
3874
3951
|
noSSR = false,
|
|
@@ -3894,10 +3971,14 @@ var BottomSheet = react.forwardRef(
|
|
|
3894
3971
|
} = useBottomSheet({
|
|
3895
3972
|
...engineOpts,
|
|
3896
3973
|
onBeforeClose,
|
|
3974
|
+
onOpen,
|
|
3975
|
+
onClose,
|
|
3897
3976
|
onOpened,
|
|
3898
3977
|
onClosed,
|
|
3899
3978
|
onDragStart,
|
|
3900
|
-
onDragEnd
|
|
3979
|
+
onDragEnd,
|
|
3980
|
+
onDrag,
|
|
3981
|
+
onProgress
|
|
3901
3982
|
});
|
|
3902
3983
|
const ariaModal = engineOpts.focusTrap === true;
|
|
3903
3984
|
const lastAnnouncedRef = react.useRef("");
|
|
@@ -4181,7 +4262,7 @@ function installOverlaySwipe(deps) {
|
|
|
4181
4262
|
};
|
|
4182
4263
|
}
|
|
4183
4264
|
|
|
4184
|
-
// src/core/overlay.ts
|
|
4265
|
+
// src/core/overlay-options.ts
|
|
4185
4266
|
var OVERLAY_PRESETS = Object.freeze({
|
|
4186
4267
|
sheet: Object.freeze({
|
|
4187
4268
|
enterAnimation: "slide",
|
|
@@ -4212,6 +4293,8 @@ var OVERLAY_PRESETS = Object.freeze({
|
|
|
4212
4293
|
swipeToClose: false
|
|
4213
4294
|
})
|
|
4214
4295
|
});
|
|
4296
|
+
|
|
4297
|
+
// src/core/overlay.ts
|
|
4215
4298
|
var OverlayEngine = class {
|
|
4216
4299
|
constructor(opts) {
|
|
4217
4300
|
__publicField(this, "id", nextInstanceId("ovl"));
|
|
@@ -4288,7 +4371,7 @@ var OverlayEngine = class {
|
|
|
4288
4371
|
this.onOpenCb = opts.onOpen;
|
|
4289
4372
|
this.onCloseCb = opts.onClose;
|
|
4290
4373
|
if (this.peekRaw !== void 0 && this.edge !== "bottom") {
|
|
4291
|
-
|
|
4374
|
+
devWarn(
|
|
4292
4375
|
"[OverlayEngine] `peek` is only supported on edge: 'bottom' \u2014 ignoring."
|
|
4293
4376
|
);
|
|
4294
4377
|
this.peekRaw = void 0;
|
|
@@ -4355,10 +4438,9 @@ var OverlayEngine = class {
|
|
|
4355
4438
|
this.element.style.opacity = "1";
|
|
4356
4439
|
if (this.backdrop) {
|
|
4357
4440
|
this.backdrop.style.opacity = String(this.backdropOpacity);
|
|
4358
|
-
this.
|
|
4441
|
+
this.syncBackdropPointerEvents();
|
|
4359
4442
|
if (this.backdropFilter) {
|
|
4360
|
-
this.
|
|
4361
|
-
this.backdrop.style.webkitBackdropFilter = this.backdropFilter;
|
|
4443
|
+
this.applyBackdropFilter(this.backdropFilter);
|
|
4362
4444
|
}
|
|
4363
4445
|
}
|
|
4364
4446
|
try {
|
|
@@ -4378,8 +4460,7 @@ var OverlayEngine = class {
|
|
|
4378
4460
|
this.backdrop.style.opacity = "0";
|
|
4379
4461
|
this.backdrop.style.pointerEvents = "none";
|
|
4380
4462
|
if (this.backdropFilter) {
|
|
4381
|
-
this.
|
|
4382
|
-
this.backdrop.style.webkitBackdropFilter = "";
|
|
4463
|
+
this.applyBackdropFilter(void 0);
|
|
4383
4464
|
}
|
|
4384
4465
|
}
|
|
4385
4466
|
this.element.setAttribute("data-state", "closed");
|
|
@@ -4437,8 +4518,7 @@ var OverlayEngine = class {
|
|
|
4437
4518
|
this.backdrop.style.opacity = "0";
|
|
4438
4519
|
this.backdrop.style.pointerEvents = "none";
|
|
4439
4520
|
if (this.backdropFilter) {
|
|
4440
|
-
this.
|
|
4441
|
-
this.backdrop.style.webkitBackdropFilter = "";
|
|
4521
|
+
this.applyBackdropFilter(void 0);
|
|
4442
4522
|
}
|
|
4443
4523
|
}
|
|
4444
4524
|
this.releaseInteractiveListeners();
|
|
@@ -4486,20 +4566,14 @@ var OverlayEngine = class {
|
|
|
4486
4566
|
this.backdropOpacity = opacity;
|
|
4487
4567
|
if (this.isOpen_ && this.backdrop) {
|
|
4488
4568
|
this.backdrop.style.opacity = String(opacity);
|
|
4569
|
+
this.syncBackdropPointerEvents();
|
|
4489
4570
|
}
|
|
4490
4571
|
}
|
|
4491
4572
|
setBackdropFilter(filter) {
|
|
4492
4573
|
if (this.destroyed) return;
|
|
4493
4574
|
this.backdropFilter = filter;
|
|
4494
4575
|
if (!this.isOpen_ || !this.backdrop) return;
|
|
4495
|
-
|
|
4496
|
-
if (filter) {
|
|
4497
|
-
this.backdrop.style.backdropFilter = filter;
|
|
4498
|
-
style.webkitBackdropFilter = filter;
|
|
4499
|
-
} else {
|
|
4500
|
-
this.backdrop.style.backdropFilter = "";
|
|
4501
|
-
style.webkitBackdropFilter = "";
|
|
4502
|
-
}
|
|
4576
|
+
this.applyBackdropFilter(filter);
|
|
4503
4577
|
}
|
|
4504
4578
|
setSwipeToClose(config) {
|
|
4505
4579
|
if (this.destroyed) return;
|
|
@@ -4568,16 +4642,10 @@ var OverlayEngine = class {
|
|
|
4568
4642
|
if (this.isOpen_ && this.backdrop) {
|
|
4569
4643
|
if (merged.backdropOpacity !== void 0) {
|
|
4570
4644
|
this.backdrop.style.opacity = String(this.backdropOpacity);
|
|
4645
|
+
this.syncBackdropPointerEvents();
|
|
4571
4646
|
}
|
|
4572
4647
|
if (merged.backdropFilter !== void 0) {
|
|
4573
|
-
|
|
4574
|
-
if (this.backdropFilter) {
|
|
4575
|
-
this.backdrop.style.backdropFilter = this.backdropFilter;
|
|
4576
|
-
style.webkitBackdropFilter = this.backdropFilter;
|
|
4577
|
-
} else {
|
|
4578
|
-
this.backdrop.style.backdropFilter = "";
|
|
4579
|
-
style.webkitBackdropFilter = "";
|
|
4580
|
-
}
|
|
4648
|
+
this.applyBackdropFilter(this.backdropFilter);
|
|
4581
4649
|
}
|
|
4582
4650
|
}
|
|
4583
4651
|
if (opts.duration !== void 0) this.duration = opts.duration;
|
|
@@ -4712,6 +4780,21 @@ var OverlayEngine = class {
|
|
|
4712
4780
|
this.backdrop.style.pointerEvents = "none";
|
|
4713
4781
|
}
|
|
4714
4782
|
}
|
|
4783
|
+
syncBackdropPointerEvents() {
|
|
4784
|
+
if (!this.backdrop) return;
|
|
4785
|
+
this.backdrop.style.pointerEvents = this.backdropOpacity > 0 ? "auto" : "none";
|
|
4786
|
+
}
|
|
4787
|
+
applyBackdropFilter(filter) {
|
|
4788
|
+
if (!this.backdrop) return;
|
|
4789
|
+
const style = this.backdrop.style;
|
|
4790
|
+
if (filter) {
|
|
4791
|
+
this.backdrop.style.backdropFilter = filter;
|
|
4792
|
+
style.webkitBackdropFilter = filter;
|
|
4793
|
+
} else {
|
|
4794
|
+
this.backdrop.style.backdropFilter = "";
|
|
4795
|
+
style.webkitBackdropFilter = "";
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4715
4798
|
setWillChange(on) {
|
|
4716
4799
|
this.element.style.willChange = on ? "transform, opacity" : "";
|
|
4717
4800
|
if (this.backdrop) {
|
|
@@ -4944,6 +5027,8 @@ var Overlay = react.forwardRef(function Overlay2(props, ref) {
|
|
|
4944
5027
|
)
|
|
4945
5028
|
] });
|
|
4946
5029
|
});
|
|
5030
|
+
|
|
5031
|
+
// src/react/config-validation.ts
|
|
4947
5032
|
var SUPPORTED_VERSION = 1;
|
|
4948
5033
|
var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
4949
5034
|
"version",
|
|
@@ -4968,7 +5053,7 @@ var warnUnknownKeys = (obj, allowed, context) => {
|
|
|
4968
5053
|
if (!obj || typeof obj !== "object") return;
|
|
4969
5054
|
const unknown = Object.keys(obj).filter((k) => !allowed.has(k));
|
|
4970
5055
|
if (unknown.length === 0) return;
|
|
4971
|
-
|
|
5056
|
+
devWarn(
|
|
4972
5057
|
`[BottomSheetFromConfig] Unknown ${unknown.length === 1 ? "key" : "keys"} in ${context}: ${unknown.map((k) => `"${k}"`).join(", ")}. Allowed: ${[...allowed].join(", ")}. Likely a typo \u2014 values ignored.`
|
|
4973
5058
|
);
|
|
4974
5059
|
};
|
|
@@ -4978,7 +5063,7 @@ function validateConfig(config) {
|
|
|
4978
5063
|
validatedConfigs.add(config);
|
|
4979
5064
|
let ok = true;
|
|
4980
5065
|
if (config.version !== SUPPORTED_VERSION) {
|
|
4981
|
-
|
|
5066
|
+
devWarn(
|
|
4982
5067
|
`[BottomSheetFromConfig] Unsupported config version ${String(
|
|
4983
5068
|
config.version
|
|
4984
5069
|
)}; expected ${SUPPORTED_VERSION}. Falling back to defaults.`
|
|
@@ -4986,7 +5071,7 @@ function validateConfig(config) {
|
|
|
4986
5071
|
return false;
|
|
4987
5072
|
}
|
|
4988
5073
|
if (!Array.isArray(config.snapPoints) || config.snapPoints.length === 0) {
|
|
4989
|
-
|
|
5074
|
+
devWarn(
|
|
4990
5075
|
"[BottomSheetFromConfig] config.snapPoints is missing or empty; using a single full-height fallback snap."
|
|
4991
5076
|
);
|
|
4992
5077
|
ok = false;
|