@surdeddd/bottom-sheet 0.7.0 → 0.8.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/dist/qwik.js CHANGED
@@ -2358,6 +2358,7 @@ var BottomSheetEngine = class {
2358
2358
  __publicField(this, "progressWriteSentinel", new WriteSentinel());
2359
2359
  __publicField(this, "isTopSheet", true);
2360
2360
  __publicField(this, "opening", false);
2361
+ __publicField(this, "allowOvershoot", false);
2361
2362
  __publicField(this, "progressPayload", {
2362
2363
  value: 0,
2363
2364
  size: 0
@@ -2910,40 +2911,32 @@ var BottomSheetEngine = class {
2910
2911
  }
2911
2912
  return out;
2912
2913
  }
2913
- measureContentExtent(vertical) {
2914
+ measureSheetNatural(vertical) {
2915
+ const el = this.element;
2914
2916
  const content = this.scrollContainer;
2915
- if (!content) return 0;
2916
- const targets = this.contentTargets();
2917
- if (targets.length === 0) {
2918
- return vertical ? content.scrollHeight : content.scrollWidth;
2919
- }
2920
- let min = Infinity;
2921
- let max = -Infinity;
2922
- for (const el of targets) {
2923
- const r = el.getBoundingClientRect();
2924
- if (vertical) {
2925
- if (r.top < min) min = r.top;
2926
- if (r.bottom > max) max = r.bottom;
2927
- } else {
2928
- if (r.left < min) min = r.left;
2929
- if (r.right > max) max = r.right;
2930
- }
2931
- }
2932
- if (!isFinite(min) || !isFinite(max) || max <= min) {
2933
- return vertical ? content.scrollHeight : content.scrollWidth;
2934
- }
2935
- let pad = 0;
2936
- if (typeof getComputedStyle !== "undefined") {
2937
- const cs = getComputedStyle(content);
2938
- pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
2939
- }
2940
- return max - min + pad;
2917
+ if (!content) {
2918
+ return vertical ? el.offsetHeight : el.offsetWidth;
2919
+ }
2920
+ const axis = vertical ? "height" : "width";
2921
+ const sheetStyle = el.style;
2922
+ const cs = content.style;
2923
+ const prevSheet = sheetStyle[axis];
2924
+ const prevFlex = cs.flex;
2925
+ const prevContent = vertical ? cs.height : cs.width;
2926
+ sheetStyle[axis] = "auto";
2927
+ cs.flex = "none";
2928
+ if (vertical) cs.height = "auto";
2929
+ else cs.width = "auto";
2930
+ const natural = vertical ? el.offsetHeight : el.offsetWidth;
2931
+ sheetStyle[axis] = prevSheet;
2932
+ cs.flex = prevFlex;
2933
+ if (vertical) cs.height = prevContent;
2934
+ else cs.width = prevContent;
2935
+ return natural;
2941
2936
  }
2942
2937
  measureFitSize() {
2943
2938
  const vertical = layoutAxis(this.mode) === "height";
2944
- const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
2945
- const content = this.scrollContainer;
2946
- const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
2939
+ const natural = this.measureSheetNatural(vertical);
2947
2940
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2948
2941
  if (typeof window === "undefined") return capped;
2949
2942
  const viewport = vertical ? window.innerHeight : window.innerWidth;
@@ -3029,6 +3022,10 @@ var BottomSheetEngine = class {
3029
3022
  this.backdrop.style.opacity = "";
3030
3023
  this.backdrop.style.pointerEvents = "";
3031
3024
  }
3025
+ if (this.anchorHost) {
3026
+ this.anchorHost.style.removeProperty("--bs-size");
3027
+ this.anchorHost.style.removeProperty("--bs-progress");
3028
+ }
3032
3029
  if (this.screenComponent) {
3033
3030
  this.screenComponent.style.opacity = "";
3034
3031
  this.screenComponent.style.display = "";
@@ -3040,6 +3037,7 @@ var BottomSheetEngine = class {
3040
3037
  this.bus.emit(event, payload);
3041
3038
  }
3042
3039
  newCycle() {
3040
+ this.allowOvershoot = false;
3043
3041
  this.currentAbort.abort();
3044
3042
  this.currentAbort = new AbortController();
3045
3043
  return this.currentAbort.signal;
@@ -3105,6 +3103,7 @@ var BottomSheetEngine = class {
3105
3103
  seen.add(p.id);
3106
3104
  }
3107
3105
  this.snaps.setRaw(this.snapPointsRaw);
3106
+ this.clampToMaxHeight();
3108
3107
  this.scrim.invalidateOpacityCache();
3109
3108
  }
3110
3109
  getAllowedRange() {
@@ -3311,9 +3310,13 @@ var BottomSheetEngine = class {
3311
3310
  this.opening = true;
3312
3311
  sheetStack.promote(this.id);
3313
3312
  }
3314
- void this.animation.animateTo(target.size, velocity).then(() => {
3315
- this.opening = false;
3313
+ const settleCap = this.snaps.getMaxAxisSize();
3314
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3315
+ this.allowOvershoot = true;
3316
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3316
3317
  if (signal.aborted) return;
3318
+ this.allowOvershoot = false;
3319
+ this.opening = false;
3317
3320
  this.scrollCache.restore(target.id, previousSize, target.size);
3318
3321
  this.updateAriaSlider();
3319
3322
  this.emit("snap", {
@@ -3345,7 +3348,7 @@ var BottomSheetEngine = class {
3345
3348
  }
3346
3349
  applySize(size) {
3347
3350
  const cap = this.snaps.getMaxAxisSize();
3348
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3351
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3349
3352
  this.size = clamped;
3350
3353
  const offset = cap - clamped;
3351
3354
  const style = this.element.style;
@@ -3437,6 +3440,8 @@ var BottomSheet = component$((props) => {
3437
3440
  const contentRef = useSignal();
3438
3441
  const backdropRef = useSignal();
3439
3442
  const scrimRef = useSignal();
3443
+ const headerRef = useSignal();
3444
+ const footerRef = useSignal();
3440
3445
  const initialActive = props.initial ?? props.snapPoints[0]?.id ?? "default";
3441
3446
  const state = useStore({
3442
3447
  size: 0,
@@ -3471,6 +3476,11 @@ var BottomSheet = component$((props) => {
3471
3476
  lockBodyScroll: props.lockBodyScroll,
3472
3477
  rubberBand: props.rubberBand,
3473
3478
  backdropRange: props.backdropRange,
3479
+ persistent: props.persistent,
3480
+ disableClose: props.disableClose,
3481
+ disableDrag: props.disableDrag,
3482
+ closeOnRouteChange: props.closeOnRouteChange,
3483
+ returnFocusTo: props.returnFocusTo,
3474
3484
  radius: props.radius,
3475
3485
  maxHeight: props.maxHeight
3476
3486
  };
@@ -3492,7 +3502,25 @@ var BottomSheet = component$((props) => {
3492
3502
  });
3493
3503
  engine.on("dragstart", sync);
3494
3504
  engine.on("dragend", sync);
3505
+ let onBackdropClick;
3506
+ if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropRef.value) {
3507
+ onBackdropClick = () => {
3508
+ if (engine.canDismiss()) void engine.close("backdrop");
3509
+ };
3510
+ backdropRef.value.addEventListener("click", onBackdropClick);
3511
+ }
3512
+ const collapseEmpty = (el) => {
3513
+ if (!el) return;
3514
+ const empty = el.children.length === 0 && el.textContent?.trim() === "";
3515
+ if (empty) el.setAttribute("hidden", "");
3516
+ else el.removeAttribute("hidden");
3517
+ };
3518
+ collapseEmpty(headerRef.value);
3519
+ collapseEmpty(footerRef.value);
3495
3520
  cleanup(() => {
3521
+ if (onBackdropClick && backdropRef.value) {
3522
+ backdropRef.value.removeEventListener("click", onBackdropClick);
3523
+ }
3496
3524
  engineStore.engine = void 0;
3497
3525
  engine.destroy();
3498
3526
  });
@@ -3542,9 +3570,9 @@ var BottomSheet = component$((props) => {
3542
3570
  "aria-label": "Resize sheet"
3543
3571
  }
3544
3572
  ),
3545
- /* @__PURE__ */ jsx("div", { class: "bs-header", children: /* @__PURE__ */ jsx(Slot, { name: "header" }) }),
3573
+ /* @__PURE__ */ jsx("div", { class: "bs-header", ref: headerRef, children: /* @__PURE__ */ jsx(Slot, { name: "header" }) }),
3546
3574
  /* @__PURE__ */ jsx("div", { class: "bs-content", ref: contentRef, children: /* @__PURE__ */ jsx(Slot, {}) }),
3547
- /* @__PURE__ */ jsx("div", { class: "bs-footer", children: /* @__PURE__ */ jsx(Slot, { name: "footer" }) }),
3575
+ /* @__PURE__ */ jsx("div", { class: "bs-footer", ref: footerRef, children: /* @__PURE__ */ jsx(Slot, { name: "footer" }) }),
3548
3576
  /* @__PURE__ */ jsx("span", { class: "bs-sr-only", role: "status", "aria-live": "polite", children: state.activeId })
3549
3577
  ]
3550
3578
  }
package/dist/react.cjs CHANGED
@@ -2367,6 +2367,7 @@ var BottomSheetEngine = class {
2367
2367
  __publicField(this, "progressWriteSentinel", new WriteSentinel());
2368
2368
  __publicField(this, "isTopSheet", true);
2369
2369
  __publicField(this, "opening", false);
2370
+ __publicField(this, "allowOvershoot", false);
2370
2371
  __publicField(this, "progressPayload", {
2371
2372
  value: 0,
2372
2373
  size: 0
@@ -2919,40 +2920,32 @@ var BottomSheetEngine = class {
2919
2920
  }
2920
2921
  return out;
2921
2922
  }
2922
- measureContentExtent(vertical) {
2923
+ measureSheetNatural(vertical) {
2924
+ const el = this.element;
2923
2925
  const content = this.scrollContainer;
2924
- if (!content) return 0;
2925
- const targets = this.contentTargets();
2926
- if (targets.length === 0) {
2927
- return vertical ? content.scrollHeight : content.scrollWidth;
2928
- }
2929
- let min = Infinity;
2930
- let max = -Infinity;
2931
- for (const el of targets) {
2932
- const r = el.getBoundingClientRect();
2933
- if (vertical) {
2934
- if (r.top < min) min = r.top;
2935
- if (r.bottom > max) max = r.bottom;
2936
- } else {
2937
- if (r.left < min) min = r.left;
2938
- if (r.right > max) max = r.right;
2939
- }
2940
- }
2941
- if (!isFinite(min) || !isFinite(max) || max <= min) {
2942
- return vertical ? content.scrollHeight : content.scrollWidth;
2943
- }
2944
- let pad = 0;
2945
- if (typeof getComputedStyle !== "undefined") {
2946
- const cs = getComputedStyle(content);
2947
- pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
2948
- }
2949
- return max - min + pad;
2926
+ if (!content) {
2927
+ return vertical ? el.offsetHeight : el.offsetWidth;
2928
+ }
2929
+ const axis = vertical ? "height" : "width";
2930
+ const sheetStyle = el.style;
2931
+ const cs = content.style;
2932
+ const prevSheet = sheetStyle[axis];
2933
+ const prevFlex = cs.flex;
2934
+ const prevContent = vertical ? cs.height : cs.width;
2935
+ sheetStyle[axis] = "auto";
2936
+ cs.flex = "none";
2937
+ if (vertical) cs.height = "auto";
2938
+ else cs.width = "auto";
2939
+ const natural = vertical ? el.offsetHeight : el.offsetWidth;
2940
+ sheetStyle[axis] = prevSheet;
2941
+ cs.flex = prevFlex;
2942
+ if (vertical) cs.height = prevContent;
2943
+ else cs.width = prevContent;
2944
+ return natural;
2950
2945
  }
2951
2946
  measureFitSize() {
2952
2947
  const vertical = layoutAxis(this.mode) === "height";
2953
- const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
2954
- const content = this.scrollContainer;
2955
- const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
2948
+ const natural = this.measureSheetNatural(vertical);
2956
2949
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2957
2950
  if (typeof window === "undefined") return capped;
2958
2951
  const viewport = vertical ? window.innerHeight : window.innerWidth;
@@ -3038,6 +3031,10 @@ var BottomSheetEngine = class {
3038
3031
  this.backdrop.style.opacity = "";
3039
3032
  this.backdrop.style.pointerEvents = "";
3040
3033
  }
3034
+ if (this.anchorHost) {
3035
+ this.anchorHost.style.removeProperty("--bs-size");
3036
+ this.anchorHost.style.removeProperty("--bs-progress");
3037
+ }
3041
3038
  if (this.screenComponent) {
3042
3039
  this.screenComponent.style.opacity = "";
3043
3040
  this.screenComponent.style.display = "";
@@ -3049,6 +3046,7 @@ var BottomSheetEngine = class {
3049
3046
  this.bus.emit(event, payload);
3050
3047
  }
3051
3048
  newCycle() {
3049
+ this.allowOvershoot = false;
3052
3050
  this.currentAbort.abort();
3053
3051
  this.currentAbort = new AbortController();
3054
3052
  return this.currentAbort.signal;
@@ -3114,6 +3112,7 @@ var BottomSheetEngine = class {
3114
3112
  seen.add(p.id);
3115
3113
  }
3116
3114
  this.snaps.setRaw(this.snapPointsRaw);
3115
+ this.clampToMaxHeight();
3117
3116
  this.scrim.invalidateOpacityCache();
3118
3117
  }
3119
3118
  getAllowedRange() {
@@ -3320,9 +3319,13 @@ var BottomSheetEngine = class {
3320
3319
  this.opening = true;
3321
3320
  sheetStack.promote(this.id);
3322
3321
  }
3323
- void this.animation.animateTo(target.size, velocity).then(() => {
3324
- this.opening = false;
3322
+ const settleCap = this.snaps.getMaxAxisSize();
3323
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3324
+ this.allowOvershoot = true;
3325
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3325
3326
  if (signal.aborted) return;
3327
+ this.allowOvershoot = false;
3328
+ this.opening = false;
3326
3329
  this.scrollCache.restore(target.id, previousSize, target.size);
3327
3330
  this.updateAriaSlider();
3328
3331
  this.emit("snap", {
@@ -3354,7 +3357,7 @@ var BottomSheetEngine = class {
3354
3357
  }
3355
3358
  applySize(size) {
3356
3359
  const cap = this.snaps.getMaxAxisSize();
3357
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3360
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3358
3361
  this.size = clamped;
3359
3362
  const offset = cap - clamped;
3360
3363
  const style = this.element.style;
@@ -3576,6 +3579,18 @@ function useBottomSheet(opts) {
3576
3579
  engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
3577
3580
  }
3578
3581
  }, [opts.backdropOpacity]);
3582
+ react.useEffect(() => {
3583
+ if (!engineRef.current) return;
3584
+ if (opts.radius !== void 0) {
3585
+ engineRef.current.setRadius(opts.radius);
3586
+ }
3587
+ }, [opts.radius]);
3588
+ react.useEffect(() => {
3589
+ if (!engineRef.current) return;
3590
+ if (opts.maxHeight !== void 0) {
3591
+ engineRef.current.setMaxHeight(opts.maxHeight);
3592
+ }
3593
+ }, [opts.maxHeight]);
3579
3594
  const subscribe = react.useCallback((fn) => {
3580
3595
  subscribersRef.current.add(fn);
3581
3596
  return () => subscribersRef.current.delete(fn);
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as EngineOptions, E as EngineState, A as AnchorOptions, S as ScrimStagesOptions, p as ScrimStageDef, e as SheetEventMap, C as CloseReason, q as ScrimUpdate, m as ScrimOverlayOptions, B as BottomSheetEngine, a as SnapPointDef, b as SheetMode } from './BottomSheetEngine-CqiCz64W.cjs';
2
- export { d as SnapPoint } from './BottomSheetEngine-CqiCz64W.cjs';
1
+ import { c as EngineOptions, E as EngineState, A as AnchorOptions, S as ScrimStagesOptions, p as ScrimStageDef, e as SheetEventMap, C as CloseReason, q as ScrimUpdate, m as ScrimOverlayOptions, B as BottomSheetEngine, a as SnapPointDef, b as SheetMode } from './BottomSheetEngine-BD1mSExI.cjs';
2
+ export { d as SnapPoint } from './BottomSheetEngine-BD1mSExI.cjs';
3
3
  import { OverlayOptions, OverlayState, Overlay as OverlayEngine } from './overlay.cjs';
4
4
  export { OverlayEdge } from './overlay.cjs';
5
5
  import * as react from 'react';
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as EngineOptions, E as EngineState, A as AnchorOptions, S as ScrimStagesOptions, p as ScrimStageDef, e as SheetEventMap, C as CloseReason, q as ScrimUpdate, m as ScrimOverlayOptions, B as BottomSheetEngine, a as SnapPointDef, b as SheetMode } from './BottomSheetEngine-BHjKFtnM.js';
2
- export { d as SnapPoint } from './BottomSheetEngine-BHjKFtnM.js';
1
+ import { c as EngineOptions, E as EngineState, A as AnchorOptions, S as ScrimStagesOptions, p as ScrimStageDef, e as SheetEventMap, C as CloseReason, q as ScrimUpdate, m as ScrimOverlayOptions, B as BottomSheetEngine, a as SnapPointDef, b as SheetMode } from './BottomSheetEngine-BDGRWa2i.js';
2
+ export { d as SnapPoint } from './BottomSheetEngine-BDGRWa2i.js';
3
3
  import { OverlayOptions, OverlayState, Overlay as OverlayEngine } from './overlay.js';
4
4
  export { OverlayEdge } from './overlay.js';
5
5
  import * as react from 'react';
package/dist/react.js CHANGED
@@ -2365,6 +2365,7 @@ var BottomSheetEngine = class {
2365
2365
  __publicField(this, "progressWriteSentinel", new WriteSentinel());
2366
2366
  __publicField(this, "isTopSheet", true);
2367
2367
  __publicField(this, "opening", false);
2368
+ __publicField(this, "allowOvershoot", false);
2368
2369
  __publicField(this, "progressPayload", {
2369
2370
  value: 0,
2370
2371
  size: 0
@@ -2917,40 +2918,32 @@ var BottomSheetEngine = class {
2917
2918
  }
2918
2919
  return out;
2919
2920
  }
2920
- measureContentExtent(vertical) {
2921
+ measureSheetNatural(vertical) {
2922
+ const el = this.element;
2921
2923
  const content = this.scrollContainer;
2922
- if (!content) return 0;
2923
- const targets = this.contentTargets();
2924
- if (targets.length === 0) {
2925
- return vertical ? content.scrollHeight : content.scrollWidth;
2926
- }
2927
- let min = Infinity;
2928
- let max = -Infinity;
2929
- for (const el of targets) {
2930
- const r = el.getBoundingClientRect();
2931
- if (vertical) {
2932
- if (r.top < min) min = r.top;
2933
- if (r.bottom > max) max = r.bottom;
2934
- } else {
2935
- if (r.left < min) min = r.left;
2936
- if (r.right > max) max = r.right;
2937
- }
2938
- }
2939
- if (!isFinite(min) || !isFinite(max) || max <= min) {
2940
- return vertical ? content.scrollHeight : content.scrollWidth;
2941
- }
2942
- let pad = 0;
2943
- if (typeof getComputedStyle !== "undefined") {
2944
- const cs = getComputedStyle(content);
2945
- pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
2946
- }
2947
- return max - min + pad;
2924
+ if (!content) {
2925
+ return vertical ? el.offsetHeight : el.offsetWidth;
2926
+ }
2927
+ const axis = vertical ? "height" : "width";
2928
+ const sheetStyle = el.style;
2929
+ const cs = content.style;
2930
+ const prevSheet = sheetStyle[axis];
2931
+ const prevFlex = cs.flex;
2932
+ const prevContent = vertical ? cs.height : cs.width;
2933
+ sheetStyle[axis] = "auto";
2934
+ cs.flex = "none";
2935
+ if (vertical) cs.height = "auto";
2936
+ else cs.width = "auto";
2937
+ const natural = vertical ? el.offsetHeight : el.offsetWidth;
2938
+ sheetStyle[axis] = prevSheet;
2939
+ cs.flex = prevFlex;
2940
+ if (vertical) cs.height = prevContent;
2941
+ else cs.width = prevContent;
2942
+ return natural;
2948
2943
  }
2949
2944
  measureFitSize() {
2950
2945
  const vertical = layoutAxis(this.mode) === "height";
2951
- const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
2952
- const content = this.scrollContainer;
2953
- const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
2946
+ const natural = this.measureSheetNatural(vertical);
2954
2947
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2955
2948
  if (typeof window === "undefined") return capped;
2956
2949
  const viewport = vertical ? window.innerHeight : window.innerWidth;
@@ -3036,6 +3029,10 @@ var BottomSheetEngine = class {
3036
3029
  this.backdrop.style.opacity = "";
3037
3030
  this.backdrop.style.pointerEvents = "";
3038
3031
  }
3032
+ if (this.anchorHost) {
3033
+ this.anchorHost.style.removeProperty("--bs-size");
3034
+ this.anchorHost.style.removeProperty("--bs-progress");
3035
+ }
3039
3036
  if (this.screenComponent) {
3040
3037
  this.screenComponent.style.opacity = "";
3041
3038
  this.screenComponent.style.display = "";
@@ -3047,6 +3044,7 @@ var BottomSheetEngine = class {
3047
3044
  this.bus.emit(event, payload);
3048
3045
  }
3049
3046
  newCycle() {
3047
+ this.allowOvershoot = false;
3050
3048
  this.currentAbort.abort();
3051
3049
  this.currentAbort = new AbortController();
3052
3050
  return this.currentAbort.signal;
@@ -3112,6 +3110,7 @@ var BottomSheetEngine = class {
3112
3110
  seen.add(p.id);
3113
3111
  }
3114
3112
  this.snaps.setRaw(this.snapPointsRaw);
3113
+ this.clampToMaxHeight();
3115
3114
  this.scrim.invalidateOpacityCache();
3116
3115
  }
3117
3116
  getAllowedRange() {
@@ -3318,9 +3317,13 @@ var BottomSheetEngine = class {
3318
3317
  this.opening = true;
3319
3318
  sheetStack.promote(this.id);
3320
3319
  }
3321
- void this.animation.animateTo(target.size, velocity).then(() => {
3322
- this.opening = false;
3320
+ const settleCap = this.snaps.getMaxAxisSize();
3321
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3322
+ this.allowOvershoot = true;
3323
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3323
3324
  if (signal.aborted) return;
3325
+ this.allowOvershoot = false;
3326
+ this.opening = false;
3324
3327
  this.scrollCache.restore(target.id, previousSize, target.size);
3325
3328
  this.updateAriaSlider();
3326
3329
  this.emit("snap", {
@@ -3352,7 +3355,7 @@ var BottomSheetEngine = class {
3352
3355
  }
3353
3356
  applySize(size) {
3354
3357
  const cap = this.snaps.getMaxAxisSize();
3355
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3358
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3356
3359
  this.size = clamped;
3357
3360
  const offset = cap - clamped;
3358
3361
  const style = this.element.style;
@@ -3574,6 +3577,18 @@ function useBottomSheet(opts) {
3574
3577
  engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
3575
3578
  }
3576
3579
  }, [opts.backdropOpacity]);
3580
+ useEffect(() => {
3581
+ if (!engineRef.current) return;
3582
+ if (opts.radius !== void 0) {
3583
+ engineRef.current.setRadius(opts.radius);
3584
+ }
3585
+ }, [opts.radius]);
3586
+ useEffect(() => {
3587
+ if (!engineRef.current) return;
3588
+ if (opts.maxHeight !== void 0) {
3589
+ engineRef.current.setMaxHeight(opts.maxHeight);
3590
+ }
3591
+ }, [opts.maxHeight]);
3577
3592
  const subscribe = useCallback((fn) => {
3578
3593
  subscribersRef.current.add(fn);
3579
3594
  return () => subscribersRef.current.delete(fn);
package/dist/solid.cjs CHANGED
@@ -2360,6 +2360,7 @@ var BottomSheetEngine = class {
2360
2360
  __publicField(this, "progressWriteSentinel", new WriteSentinel());
2361
2361
  __publicField(this, "isTopSheet", true);
2362
2362
  __publicField(this, "opening", false);
2363
+ __publicField(this, "allowOvershoot", false);
2363
2364
  __publicField(this, "progressPayload", {
2364
2365
  value: 0,
2365
2366
  size: 0
@@ -2912,40 +2913,32 @@ var BottomSheetEngine = class {
2912
2913
  }
2913
2914
  return out;
2914
2915
  }
2915
- measureContentExtent(vertical) {
2916
+ measureSheetNatural(vertical) {
2917
+ const el = this.element;
2916
2918
  const content = this.scrollContainer;
2917
- if (!content) return 0;
2918
- const targets = this.contentTargets();
2919
- if (targets.length === 0) {
2920
- return vertical ? content.scrollHeight : content.scrollWidth;
2921
- }
2922
- let min = Infinity;
2923
- let max = -Infinity;
2924
- for (const el of targets) {
2925
- const r = el.getBoundingClientRect();
2926
- if (vertical) {
2927
- if (r.top < min) min = r.top;
2928
- if (r.bottom > max) max = r.bottom;
2929
- } else {
2930
- if (r.left < min) min = r.left;
2931
- if (r.right > max) max = r.right;
2932
- }
2933
- }
2934
- if (!isFinite(min) || !isFinite(max) || max <= min) {
2935
- return vertical ? content.scrollHeight : content.scrollWidth;
2936
- }
2937
- let pad = 0;
2938
- if (typeof getComputedStyle !== "undefined") {
2939
- const cs = getComputedStyle(content);
2940
- pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
2941
- }
2942
- return max - min + pad;
2919
+ if (!content) {
2920
+ return vertical ? el.offsetHeight : el.offsetWidth;
2921
+ }
2922
+ const axis = vertical ? "height" : "width";
2923
+ const sheetStyle = el.style;
2924
+ const cs = content.style;
2925
+ const prevSheet = sheetStyle[axis];
2926
+ const prevFlex = cs.flex;
2927
+ const prevContent = vertical ? cs.height : cs.width;
2928
+ sheetStyle[axis] = "auto";
2929
+ cs.flex = "none";
2930
+ if (vertical) cs.height = "auto";
2931
+ else cs.width = "auto";
2932
+ const natural = vertical ? el.offsetHeight : el.offsetWidth;
2933
+ sheetStyle[axis] = prevSheet;
2934
+ cs.flex = prevFlex;
2935
+ if (vertical) cs.height = prevContent;
2936
+ else cs.width = prevContent;
2937
+ return natural;
2943
2938
  }
2944
2939
  measureFitSize() {
2945
2940
  const vertical = layoutAxis(this.mode) === "height";
2946
- const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
2947
- const content = this.scrollContainer;
2948
- const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
2941
+ const natural = this.measureSheetNatural(vertical);
2949
2942
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2950
2943
  if (typeof window === "undefined") return capped;
2951
2944
  const viewport = vertical ? window.innerHeight : window.innerWidth;
@@ -3031,6 +3024,10 @@ var BottomSheetEngine = class {
3031
3024
  this.backdrop.style.opacity = "";
3032
3025
  this.backdrop.style.pointerEvents = "";
3033
3026
  }
3027
+ if (this.anchorHost) {
3028
+ this.anchorHost.style.removeProperty("--bs-size");
3029
+ this.anchorHost.style.removeProperty("--bs-progress");
3030
+ }
3034
3031
  if (this.screenComponent) {
3035
3032
  this.screenComponent.style.opacity = "";
3036
3033
  this.screenComponent.style.display = "";
@@ -3042,6 +3039,7 @@ var BottomSheetEngine = class {
3042
3039
  this.bus.emit(event, payload);
3043
3040
  }
3044
3041
  newCycle() {
3042
+ this.allowOvershoot = false;
3045
3043
  this.currentAbort.abort();
3046
3044
  this.currentAbort = new AbortController();
3047
3045
  return this.currentAbort.signal;
@@ -3107,6 +3105,7 @@ var BottomSheetEngine = class {
3107
3105
  seen.add(p.id);
3108
3106
  }
3109
3107
  this.snaps.setRaw(this.snapPointsRaw);
3108
+ this.clampToMaxHeight();
3110
3109
  this.scrim.invalidateOpacityCache();
3111
3110
  }
3112
3111
  getAllowedRange() {
@@ -3313,9 +3312,13 @@ var BottomSheetEngine = class {
3313
3312
  this.opening = true;
3314
3313
  sheetStack.promote(this.id);
3315
3314
  }
3316
- void this.animation.animateTo(target.size, velocity).then(() => {
3317
- this.opening = false;
3315
+ const settleCap = this.snaps.getMaxAxisSize();
3316
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3317
+ this.allowOvershoot = true;
3318
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3318
3319
  if (signal.aborted) return;
3320
+ this.allowOvershoot = false;
3321
+ this.opening = false;
3319
3322
  this.scrollCache.restore(target.id, previousSize, target.size);
3320
3323
  this.updateAriaSlider();
3321
3324
  this.emit("snap", {
@@ -3347,7 +3350,7 @@ var BottomSheetEngine = class {
3347
3350
  }
3348
3351
  applySize(size) {
3349
3352
  const cap = this.snaps.getMaxAxisSize();
3350
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3353
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3351
3354
  this.size = clamped;
3352
3355
  const offset = cap - clamped;
3353
3356
  const style = this.element.style;
@@ -3475,7 +3478,12 @@ var BottomSheet = (props) => {
3475
3478
  rubberBand: props.rubberBand,
3476
3479
  backdropRange: props.backdropRange,
3477
3480
  radius: props.radius,
3478
- maxHeight: props.maxHeight
3481
+ maxHeight: props.maxHeight,
3482
+ persistent: props.persistent,
3483
+ disableClose: props.disableClose,
3484
+ disableDrag: props.disableDrag,
3485
+ closeOnRouteChange: props.closeOnRouteChange,
3486
+ returnFocusTo: props.returnFocusTo
3479
3487
  };
3480
3488
  engine = new BottomSheetEngine(engineOpts);
3481
3489
  props.engineRef?.(engine);
@@ -3496,7 +3504,7 @@ var BottomSheet = (props) => {
3496
3504
  engine.on("dragend", sync);
3497
3505
  if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropEl) {
3498
3506
  const onBackdropClick = () => {
3499
- void engine?.close();
3507
+ if (engine?.canDismiss()) void engine.close("backdrop");
3500
3508
  };
3501
3509
  backdropEl.addEventListener("click", onBackdropClick);
3502
3510
  solidJs.onCleanup(() => {
package/dist/solid.d.cts CHANGED
@@ -216,6 +216,7 @@ declare class BottomSheetEngine {
216
216
  private progressWriteSentinel;
217
217
  private isTopSheet;
218
218
  private opening;
219
+ private allowOvershoot;
219
220
  private progressPayload;
220
221
  private dragContextBuf;
221
222
  private bus;
@@ -274,7 +275,7 @@ declare class BottomSheetEngine {
274
275
  setSnapPoints(points: EngineOptions["snapPoints"], allowed?: string[]): void;
275
276
  recompute(): void;
276
277
  private contentTargets;
277
- private measureContentExtent;
278
+ private measureSheetNatural;
278
279
  private measureFitSize;
279
280
  private installFitObserver;
280
281
  destroy(): void;
@@ -321,6 +322,11 @@ type BottomSheetProps<TId extends string = string> = {
321
322
  backdropRange?: [number, number];
322
323
  radius?: string | number;
323
324
  maxHeight?: string | number;
325
+ persistent?: boolean;
326
+ disableClose?: boolean;
327
+ disableDrag?: boolean;
328
+ closeOnRouteChange?: boolean;
329
+ returnFocusTo?: string;
324
330
  backdrop?: boolean;
325
331
  closeOnBackdrop?: boolean;
326
332
  ariaLabel?: string;