@surdeddd/bottom-sheet 0.6.1 → 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
@@ -2648,8 +2649,8 @@ var BottomSheetEngine = class {
2648
2649
  this.updateAriaSlider();
2649
2650
  this.emit("snap", {
2650
2651
  id,
2651
- size: target.size,
2652
- progress: this.computeProgress(target.size)
2652
+ size: this.size,
2653
+ progress: this.computeProgress(this.size)
2653
2654
  });
2654
2655
  if (wasClosed && target.size > 0) {
2655
2656
  this.emit("open", { id });
@@ -2728,12 +2729,12 @@ var BottomSheetEngine = class {
2728
2729
  const value = typeof h === "number" ? `${h}px` : h;
2729
2730
  const axis = layoutAxis(this.mode);
2730
2731
  this.element.style.setProperty(
2731
- axis === "height" ? "maxHeight" : "maxWidth",
2732
+ axis === "height" ? "max-height" : "max-width",
2732
2733
  value
2733
2734
  );
2734
2735
  if (typeof h === "number") {
2735
2736
  this.maxHeightCap = h;
2736
- this.clampToMaxHeight();
2737
+ this.recompute();
2737
2738
  } else if (typeof window !== "undefined") {
2738
2739
  const probe2 = document.createElement("div");
2739
2740
  probe2.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;${axis === "height" ? "height" : "width"}:${value};`;
@@ -2741,7 +2742,7 @@ var BottomSheetEngine = class {
2741
2742
  const measured = axis === "height" ? probe2.offsetHeight : probe2.offsetWidth;
2742
2743
  probe2.remove();
2743
2744
  this.maxHeightCap = measured > 0 ? measured : void 0;
2744
- this.clampToMaxHeight();
2745
+ this.recompute();
2745
2746
  }
2746
2747
  }
2747
2748
  clampToMaxHeight() {
@@ -2749,9 +2750,6 @@ var BottomSheetEngine = class {
2749
2750
  if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
2750
2751
  this.snaps.setMaxAxisSize(this.maxHeightCap);
2751
2752
  }
2752
- if (this.size > this.maxHeightCap && !this.gesture?.isDragging) {
2753
- this.applySize(this.maxHeightCap);
2754
- }
2755
2753
  }
2756
2754
  setAllowed(ids, snap) {
2757
2755
  if (this.destroyed) return;
@@ -2889,6 +2887,7 @@ var BottomSheetEngine = class {
2889
2887
  recompute() {
2890
2888
  if (this.destroyed) return;
2891
2889
  this.snaps.recompute();
2890
+ this.clampToMaxHeight();
2892
2891
  this.scrim.invalidateOpacityCache();
2893
2892
  if (this.gesture?.isDragging) return;
2894
2893
  const current = this.snaps.findById(this.activeId);
@@ -2912,43 +2911,36 @@ var BottomSheetEngine = class {
2912
2911
  }
2913
2912
  return out;
2914
2913
  }
2915
- measureContentExtent(vertical) {
2914
+ measureSheetNatural(vertical) {
2915
+ const el = this.element;
2916
2916
  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;
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;
2943
2936
  }
2944
2937
  measureFitSize() {
2945
2938
  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;
2949
- if (typeof window === "undefined") return natural;
2939
+ const natural = this.measureSheetNatural(vertical);
2940
+ const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2941
+ if (typeof window === "undefined") return capped;
2950
2942
  const viewport = vertical ? window.innerHeight : window.innerWidth;
2951
- return viewport > 0 ? Math.min(natural, viewport) : natural;
2943
+ return viewport > 0 ? Math.min(capped, viewport) : capped;
2952
2944
  }
2953
2945
  installFitObserver() {
2954
2946
  if (typeof ResizeObserver === "undefined") return;
@@ -3030,6 +3022,10 @@ var BottomSheetEngine = class {
3030
3022
  this.backdrop.style.opacity = "";
3031
3023
  this.backdrop.style.pointerEvents = "";
3032
3024
  }
3025
+ if (this.anchorHost) {
3026
+ this.anchorHost.style.removeProperty("--bs-size");
3027
+ this.anchorHost.style.removeProperty("--bs-progress");
3028
+ }
3033
3029
  if (this.screenComponent) {
3034
3030
  this.screenComponent.style.opacity = "";
3035
3031
  this.screenComponent.style.display = "";
@@ -3041,6 +3037,7 @@ var BottomSheetEngine = class {
3041
3037
  this.bus.emit(event, payload);
3042
3038
  }
3043
3039
  newCycle() {
3040
+ this.allowOvershoot = false;
3044
3041
  this.currentAbort.abort();
3045
3042
  this.currentAbort = new AbortController();
3046
3043
  return this.currentAbort.signal;
@@ -3106,6 +3103,7 @@ var BottomSheetEngine = class {
3106
3103
  seen.add(p.id);
3107
3104
  }
3108
3105
  this.snaps.setRaw(this.snapPointsRaw);
3106
+ this.clampToMaxHeight();
3109
3107
  this.scrim.invalidateOpacityCache();
3110
3108
  }
3111
3109
  getAllowedRange() {
@@ -3312,15 +3310,19 @@ var BottomSheetEngine = class {
3312
3310
  this.opening = true;
3313
3311
  sheetStack.promote(this.id);
3314
3312
  }
3315
- void this.animation.animateTo(target.size, velocity).then(() => {
3316
- 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(() => {
3317
3317
  if (signal.aborted) return;
3318
+ this.allowOvershoot = false;
3319
+ this.opening = false;
3318
3320
  this.scrollCache.restore(target.id, previousSize, target.size);
3319
3321
  this.updateAriaSlider();
3320
3322
  this.emit("snap", {
3321
3323
  id: target.id,
3322
- size: target.size,
3323
- progress: this.computeProgress(target.size)
3324
+ size: this.size,
3325
+ progress: this.computeProgress(this.size)
3324
3326
  });
3325
3327
  this.haptic();
3326
3328
  if (previousSnapSize === 0 && target.size > 0) {
@@ -3345,23 +3347,25 @@ var BottomSheetEngine = class {
3345
3347
  }
3346
3348
  }
3347
3349
  applySize(size) {
3348
- this.size = size;
3349
- const offset = this.snaps.getMaxAxisSize() - size;
3350
+ const cap = this.snaps.getMaxAxisSize();
3351
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3352
+ this.size = clamped;
3353
+ const offset = cap - clamped;
3350
3354
  const style = this.element.style;
3351
3355
  style.transform = this.transformTemplate(offset);
3352
- if (this.sizeWriteSentinel.shouldWrite(size, SIZE_WRITE_EPSILON)) {
3353
- style.setProperty("--bs-size", `${size}px`);
3356
+ if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
3357
+ style.setProperty("--bs-size", `${clamped}px`);
3354
3358
  if (this.scrimParent) {
3355
- this.scrimParent.style.setProperty("--bs-size", `${size}px`);
3359
+ this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
3356
3360
  }
3357
3361
  if (this.anchorHost && this.anchorHost !== this.scrimParent) {
3358
- this.anchorHost.style.setProperty("--bs-size", `${size}px`);
3362
+ this.anchorHost.style.setProperty("--bs-size", `${clamped}px`);
3359
3363
  }
3360
3364
  if (this.rootEl && this.rootEl !== this.scrimParent && this.rootEl !== this.anchorHost) {
3361
- this.rootEl.style.setProperty("--bs-size", `${size}px`);
3365
+ this.rootEl.style.setProperty("--bs-size", `${clamped}px`);
3362
3366
  }
3363
3367
  }
3364
- const progress = this.computeProgress(size);
3368
+ const progress = this.computeProgress(clamped);
3365
3369
  const progressChanged = this.progressWriteSentinel.shouldWrite(
3366
3370
  progress,
3367
3371
  OPACITY_WRITE_EPSILON
@@ -3378,14 +3382,15 @@ var BottomSheetEngine = class {
3378
3382
  this.scrim.applyOpacity(progress, progressChanged);
3379
3383
  if (progressChanged && this.bus.listenerCount("progress") > 0) {
3380
3384
  this.progressPayload.value = progress;
3381
- this.progressPayload.size = size;
3385
+ this.progressPayload.size = clamped;
3382
3386
  this.emit("progress", this.progressPayload);
3383
3387
  }
3384
3388
  }
3385
3389
  computeProgress(size) {
3386
3390
  const { min, max } = this.getAllowedRange();
3387
- if (max <= min) return 0;
3388
- return Math.min(Math.max((size - min) / (max - min), 0), 1);
3391
+ const reachableMax = Math.min(max, this.snaps.getMaxAxisSize());
3392
+ if (reachableMax <= min) return 0;
3393
+ return Math.min(Math.max((size - min) / (reachableMax - min), 0), 1);
3389
3394
  }
3390
3395
  handleOpen() {
3391
3396
  sheetStack.promote(this.id);
@@ -3409,8 +3414,8 @@ var BottomSheetEngine = class {
3409
3414
  this.updateAriaSlider();
3410
3415
  this.emit("snap", {
3411
3416
  id: target.id,
3412
- size: target.size,
3413
- progress: this.computeProgress(target.size)
3417
+ size: this.size,
3418
+ progress: this.computeProgress(this.size)
3414
3419
  });
3415
3420
  if (target.size > 0 && !this.lifecycle.isInstalled) {
3416
3421
  this.emit("open", { id: target.id });
@@ -3435,6 +3440,8 @@ var BottomSheet = component$((props) => {
3435
3440
  const contentRef = useSignal();
3436
3441
  const backdropRef = useSignal();
3437
3442
  const scrimRef = useSignal();
3443
+ const headerRef = useSignal();
3444
+ const footerRef = useSignal();
3438
3445
  const initialActive = props.initial ?? props.snapPoints[0]?.id ?? "default";
3439
3446
  const state = useStore({
3440
3447
  size: 0,
@@ -3469,6 +3476,11 @@ var BottomSheet = component$((props) => {
3469
3476
  lockBodyScroll: props.lockBodyScroll,
3470
3477
  rubberBand: props.rubberBand,
3471
3478
  backdropRange: props.backdropRange,
3479
+ persistent: props.persistent,
3480
+ disableClose: props.disableClose,
3481
+ disableDrag: props.disableDrag,
3482
+ closeOnRouteChange: props.closeOnRouteChange,
3483
+ returnFocusTo: props.returnFocusTo,
3472
3484
  radius: props.radius,
3473
3485
  maxHeight: props.maxHeight
3474
3486
  };
@@ -3490,7 +3502,25 @@ var BottomSheet = component$((props) => {
3490
3502
  });
3491
3503
  engine.on("dragstart", sync);
3492
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);
3493
3520
  cleanup(() => {
3521
+ if (onBackdropClick && backdropRef.value) {
3522
+ backdropRef.value.removeEventListener("click", onBackdropClick);
3523
+ }
3494
3524
  engineStore.engine = void 0;
3495
3525
  engine.destroy();
3496
3526
  });
@@ -3540,9 +3570,9 @@ var BottomSheet = component$((props) => {
3540
3570
  "aria-label": "Resize sheet"
3541
3571
  }
3542
3572
  ),
3543
- /* @__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" }) }),
3544
3574
  /* @__PURE__ */ jsx("div", { class: "bs-content", ref: contentRef, children: /* @__PURE__ */ jsx(Slot, {}) }),
3545
- /* @__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" }) }),
3546
3576
  /* @__PURE__ */ jsx("span", { class: "bs-sr-only", role: "status", "aria-live": "polite", children: state.activeId })
3547
3577
  ]
3548
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
@@ -2657,8 +2658,8 @@ var BottomSheetEngine = class {
2657
2658
  this.updateAriaSlider();
2658
2659
  this.emit("snap", {
2659
2660
  id,
2660
- size: target.size,
2661
- progress: this.computeProgress(target.size)
2661
+ size: this.size,
2662
+ progress: this.computeProgress(this.size)
2662
2663
  });
2663
2664
  if (wasClosed && target.size > 0) {
2664
2665
  this.emit("open", { id });
@@ -2737,12 +2738,12 @@ var BottomSheetEngine = class {
2737
2738
  const value = typeof h === "number" ? `${h}px` : h;
2738
2739
  const axis = layoutAxis(this.mode);
2739
2740
  this.element.style.setProperty(
2740
- axis === "height" ? "maxHeight" : "maxWidth",
2741
+ axis === "height" ? "max-height" : "max-width",
2741
2742
  value
2742
2743
  );
2743
2744
  if (typeof h === "number") {
2744
2745
  this.maxHeightCap = h;
2745
- this.clampToMaxHeight();
2746
+ this.recompute();
2746
2747
  } else if (typeof window !== "undefined") {
2747
2748
  const probe2 = document.createElement("div");
2748
2749
  probe2.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;${axis === "height" ? "height" : "width"}:${value};`;
@@ -2750,7 +2751,7 @@ var BottomSheetEngine = class {
2750
2751
  const measured = axis === "height" ? probe2.offsetHeight : probe2.offsetWidth;
2751
2752
  probe2.remove();
2752
2753
  this.maxHeightCap = measured > 0 ? measured : void 0;
2753
- this.clampToMaxHeight();
2754
+ this.recompute();
2754
2755
  }
2755
2756
  }
2756
2757
  clampToMaxHeight() {
@@ -2758,9 +2759,6 @@ var BottomSheetEngine = class {
2758
2759
  if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
2759
2760
  this.snaps.setMaxAxisSize(this.maxHeightCap);
2760
2761
  }
2761
- if (this.size > this.maxHeightCap && !this.gesture?.isDragging) {
2762
- this.applySize(this.maxHeightCap);
2763
- }
2764
2762
  }
2765
2763
  setAllowed(ids, snap) {
2766
2764
  if (this.destroyed) return;
@@ -2898,6 +2896,7 @@ var BottomSheetEngine = class {
2898
2896
  recompute() {
2899
2897
  if (this.destroyed) return;
2900
2898
  this.snaps.recompute();
2899
+ this.clampToMaxHeight();
2901
2900
  this.scrim.invalidateOpacityCache();
2902
2901
  if (this.gesture?.isDragging) return;
2903
2902
  const current = this.snaps.findById(this.activeId);
@@ -2921,43 +2920,36 @@ var BottomSheetEngine = class {
2921
2920
  }
2922
2921
  return out;
2923
2922
  }
2924
- measureContentExtent(vertical) {
2923
+ measureSheetNatural(vertical) {
2924
+ const el = this.element;
2925
2925
  const content = this.scrollContainer;
2926
- if (!content) return 0;
2927
- const targets = this.contentTargets();
2928
- if (targets.length === 0) {
2929
- return vertical ? content.scrollHeight : content.scrollWidth;
2930
- }
2931
- let min = Infinity;
2932
- let max = -Infinity;
2933
- for (const el of targets) {
2934
- const r = el.getBoundingClientRect();
2935
- if (vertical) {
2936
- if (r.top < min) min = r.top;
2937
- if (r.bottom > max) max = r.bottom;
2938
- } else {
2939
- if (r.left < min) min = r.left;
2940
- if (r.right > max) max = r.right;
2941
- }
2942
- }
2943
- if (!isFinite(min) || !isFinite(max) || max <= min) {
2944
- return vertical ? content.scrollHeight : content.scrollWidth;
2945
- }
2946
- let pad = 0;
2947
- if (typeof getComputedStyle !== "undefined") {
2948
- const cs = getComputedStyle(content);
2949
- pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
2950
- }
2951
- 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;
2952
2945
  }
2953
2946
  measureFitSize() {
2954
2947
  const vertical = layoutAxis(this.mode) === "height";
2955
- const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
2956
- const content = this.scrollContainer;
2957
- const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
2958
- if (typeof window === "undefined") return natural;
2948
+ const natural = this.measureSheetNatural(vertical);
2949
+ const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2950
+ if (typeof window === "undefined") return capped;
2959
2951
  const viewport = vertical ? window.innerHeight : window.innerWidth;
2960
- return viewport > 0 ? Math.min(natural, viewport) : natural;
2952
+ return viewport > 0 ? Math.min(capped, viewport) : capped;
2961
2953
  }
2962
2954
  installFitObserver() {
2963
2955
  if (typeof ResizeObserver === "undefined") return;
@@ -3039,6 +3031,10 @@ var BottomSheetEngine = class {
3039
3031
  this.backdrop.style.opacity = "";
3040
3032
  this.backdrop.style.pointerEvents = "";
3041
3033
  }
3034
+ if (this.anchorHost) {
3035
+ this.anchorHost.style.removeProperty("--bs-size");
3036
+ this.anchorHost.style.removeProperty("--bs-progress");
3037
+ }
3042
3038
  if (this.screenComponent) {
3043
3039
  this.screenComponent.style.opacity = "";
3044
3040
  this.screenComponent.style.display = "";
@@ -3050,6 +3046,7 @@ var BottomSheetEngine = class {
3050
3046
  this.bus.emit(event, payload);
3051
3047
  }
3052
3048
  newCycle() {
3049
+ this.allowOvershoot = false;
3053
3050
  this.currentAbort.abort();
3054
3051
  this.currentAbort = new AbortController();
3055
3052
  return this.currentAbort.signal;
@@ -3115,6 +3112,7 @@ var BottomSheetEngine = class {
3115
3112
  seen.add(p.id);
3116
3113
  }
3117
3114
  this.snaps.setRaw(this.snapPointsRaw);
3115
+ this.clampToMaxHeight();
3118
3116
  this.scrim.invalidateOpacityCache();
3119
3117
  }
3120
3118
  getAllowedRange() {
@@ -3321,15 +3319,19 @@ var BottomSheetEngine = class {
3321
3319
  this.opening = true;
3322
3320
  sheetStack.promote(this.id);
3323
3321
  }
3324
- void this.animation.animateTo(target.size, velocity).then(() => {
3325
- 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(() => {
3326
3326
  if (signal.aborted) return;
3327
+ this.allowOvershoot = false;
3328
+ this.opening = false;
3327
3329
  this.scrollCache.restore(target.id, previousSize, target.size);
3328
3330
  this.updateAriaSlider();
3329
3331
  this.emit("snap", {
3330
3332
  id: target.id,
3331
- size: target.size,
3332
- progress: this.computeProgress(target.size)
3333
+ size: this.size,
3334
+ progress: this.computeProgress(this.size)
3333
3335
  });
3334
3336
  this.haptic();
3335
3337
  if (previousSnapSize === 0 && target.size > 0) {
@@ -3354,23 +3356,25 @@ var BottomSheetEngine = class {
3354
3356
  }
3355
3357
  }
3356
3358
  applySize(size) {
3357
- this.size = size;
3358
- const offset = this.snaps.getMaxAxisSize() - size;
3359
+ const cap = this.snaps.getMaxAxisSize();
3360
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3361
+ this.size = clamped;
3362
+ const offset = cap - clamped;
3359
3363
  const style = this.element.style;
3360
3364
  style.transform = this.transformTemplate(offset);
3361
- if (this.sizeWriteSentinel.shouldWrite(size, SIZE_WRITE_EPSILON)) {
3362
- style.setProperty("--bs-size", `${size}px`);
3365
+ if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
3366
+ style.setProperty("--bs-size", `${clamped}px`);
3363
3367
  if (this.scrimParent) {
3364
- this.scrimParent.style.setProperty("--bs-size", `${size}px`);
3368
+ this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
3365
3369
  }
3366
3370
  if (this.anchorHost && this.anchorHost !== this.scrimParent) {
3367
- this.anchorHost.style.setProperty("--bs-size", `${size}px`);
3371
+ this.anchorHost.style.setProperty("--bs-size", `${clamped}px`);
3368
3372
  }
3369
3373
  if (this.rootEl && this.rootEl !== this.scrimParent && this.rootEl !== this.anchorHost) {
3370
- this.rootEl.style.setProperty("--bs-size", `${size}px`);
3374
+ this.rootEl.style.setProperty("--bs-size", `${clamped}px`);
3371
3375
  }
3372
3376
  }
3373
- const progress = this.computeProgress(size);
3377
+ const progress = this.computeProgress(clamped);
3374
3378
  const progressChanged = this.progressWriteSentinel.shouldWrite(
3375
3379
  progress,
3376
3380
  OPACITY_WRITE_EPSILON
@@ -3387,14 +3391,15 @@ var BottomSheetEngine = class {
3387
3391
  this.scrim.applyOpacity(progress, progressChanged);
3388
3392
  if (progressChanged && this.bus.listenerCount("progress") > 0) {
3389
3393
  this.progressPayload.value = progress;
3390
- this.progressPayload.size = size;
3394
+ this.progressPayload.size = clamped;
3391
3395
  this.emit("progress", this.progressPayload);
3392
3396
  }
3393
3397
  }
3394
3398
  computeProgress(size) {
3395
3399
  const { min, max } = this.getAllowedRange();
3396
- if (max <= min) return 0;
3397
- return Math.min(Math.max((size - min) / (max - min), 0), 1);
3400
+ const reachableMax = Math.min(max, this.snaps.getMaxAxisSize());
3401
+ if (reachableMax <= min) return 0;
3402
+ return Math.min(Math.max((size - min) / (reachableMax - min), 0), 1);
3398
3403
  }
3399
3404
  handleOpen() {
3400
3405
  sheetStack.promote(this.id);
@@ -3418,8 +3423,8 @@ var BottomSheetEngine = class {
3418
3423
  this.updateAriaSlider();
3419
3424
  this.emit("snap", {
3420
3425
  id: target.id,
3421
- size: target.size,
3422
- progress: this.computeProgress(target.size)
3426
+ size: this.size,
3427
+ progress: this.computeProgress(this.size)
3423
3428
  });
3424
3429
  if (target.size > 0 && !this.lifecycle.isInstalled) {
3425
3430
  this.emit("open", { id: target.id });
@@ -3574,6 +3579,18 @@ function useBottomSheet(opts) {
3574
3579
  engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
3575
3580
  }
3576
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]);
3577
3594
  const subscribe = react.useCallback((fn) => {
3578
3595
  subscribersRef.current.add(fn);
3579
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';