@surdeddd/bottom-sheet 0.7.0 → 0.8.1

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/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,45 +2913,52 @@ 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 poked = vertical ? el.offsetHeight : el.offsetWidth;
2933
+ const contentBox = vertical ? content.clientHeight : content.clientWidth;
2934
+ const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
2935
+ const natural = Math.max(poked, poked - contentBox + contentScroll);
2936
+ sheetStyle[axis] = prevSheet;
2937
+ cs.flex = prevFlex;
2938
+ if (vertical) cs.height = prevContent;
2939
+ else cs.width = prevContent;
2940
+ return natural;
2943
2941
  }
2944
2942
  measureFitSize() {
2945
2943
  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;
2944
+ const natural = this.measureSheetNatural(vertical);
2949
2945
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2950
2946
  if (typeof window === "undefined") return capped;
2951
- const viewport = vertical ? window.innerHeight : window.innerWidth;
2947
+ const viewport = this.containingExtent(vertical);
2952
2948
  return viewport > 0 ? Math.min(capped, viewport) : capped;
2953
2949
  }
2950
+ // The fit cap is the sheet's containing block, not always the window: a
2951
+ // position:fixed sheet nested under a transform/filter/will-change ancestor
2952
+ // is clipped to that ancestor, so capping by window.innerHeight oversizes the
2953
+ // sheet and the content/footer get clipped. offsetParent resolves to that
2954
+ // ancestor when present, and is null (→ viewport) for a plain fixed sheet.
2955
+ containingExtent(vertical) {
2956
+ const op = this.element.offsetParent;
2957
+ if (op && op !== document.body && op !== document.documentElement) {
2958
+ return vertical ? op.clientHeight : op.clientWidth;
2959
+ }
2960
+ return vertical ? window.innerHeight : window.innerWidth;
2961
+ }
2954
2962
  installFitObserver() {
2955
2963
  if (typeof ResizeObserver === "undefined") return;
2956
2964
  if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
@@ -3031,6 +3039,10 @@ var BottomSheetEngine = class {
3031
3039
  this.backdrop.style.opacity = "";
3032
3040
  this.backdrop.style.pointerEvents = "";
3033
3041
  }
3042
+ if (this.anchorHost) {
3043
+ this.anchorHost.style.removeProperty("--bs-size");
3044
+ this.anchorHost.style.removeProperty("--bs-progress");
3045
+ }
3034
3046
  if (this.screenComponent) {
3035
3047
  this.screenComponent.style.opacity = "";
3036
3048
  this.screenComponent.style.display = "";
@@ -3042,6 +3054,7 @@ var BottomSheetEngine = class {
3042
3054
  this.bus.emit(event, payload);
3043
3055
  }
3044
3056
  newCycle() {
3057
+ this.allowOvershoot = false;
3045
3058
  this.currentAbort.abort();
3046
3059
  this.currentAbort = new AbortController();
3047
3060
  return this.currentAbort.signal;
@@ -3107,6 +3120,7 @@ var BottomSheetEngine = class {
3107
3120
  seen.add(p.id);
3108
3121
  }
3109
3122
  this.snaps.setRaw(this.snapPointsRaw);
3123
+ this.clampToMaxHeight();
3110
3124
  this.scrim.invalidateOpacityCache();
3111
3125
  }
3112
3126
  getAllowedRange() {
@@ -3313,9 +3327,13 @@ var BottomSheetEngine = class {
3313
3327
  this.opening = true;
3314
3328
  sheetStack.promote(this.id);
3315
3329
  }
3316
- void this.animation.animateTo(target.size, velocity).then(() => {
3317
- this.opening = false;
3330
+ const settleCap = this.snaps.getMaxAxisSize();
3331
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3332
+ this.allowOvershoot = true;
3333
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3318
3334
  if (signal.aborted) return;
3335
+ this.allowOvershoot = false;
3336
+ this.opening = false;
3319
3337
  this.scrollCache.restore(target.id, previousSize, target.size);
3320
3338
  this.updateAriaSlider();
3321
3339
  this.emit("snap", {
@@ -3347,7 +3365,7 @@ var BottomSheetEngine = class {
3347
3365
  }
3348
3366
  applySize(size) {
3349
3367
  const cap = this.snaps.getMaxAxisSize();
3350
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3368
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3351
3369
  this.size = clamped;
3352
3370
  const offset = cap - clamped;
3353
3371
  const style = this.element.style;
@@ -3475,7 +3493,12 @@ var BottomSheet = (props) => {
3475
3493
  rubberBand: props.rubberBand,
3476
3494
  backdropRange: props.backdropRange,
3477
3495
  radius: props.radius,
3478
- maxHeight: props.maxHeight
3496
+ maxHeight: props.maxHeight,
3497
+ persistent: props.persistent,
3498
+ disableClose: props.disableClose,
3499
+ disableDrag: props.disableDrag,
3500
+ closeOnRouteChange: props.closeOnRouteChange,
3501
+ returnFocusTo: props.returnFocusTo
3479
3502
  };
3480
3503
  engine = new BottomSheetEngine(engineOpts);
3481
3504
  props.engineRef?.(engine);
@@ -3496,7 +3519,7 @@ var BottomSheet = (props) => {
3496
3519
  engine.on("dragend", sync);
3497
3520
  if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropEl) {
3498
3521
  const onBackdropClick = () => {
3499
- void engine?.close();
3522
+ if (engine?.canDismiss()) void engine.close("backdrop");
3500
3523
  };
3501
3524
  backdropEl.addEventListener("click", onBackdropClick);
3502
3525
  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,8 +275,9 @@ 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;
280
+ private containingExtent;
279
281
  private installFitObserver;
280
282
  destroy(): void;
281
283
  private emit;
@@ -321,6 +323,11 @@ type BottomSheetProps<TId extends string = string> = {
321
323
  backdropRange?: [number, number];
322
324
  radius?: string | number;
323
325
  maxHeight?: string | number;
326
+ persistent?: boolean;
327
+ disableClose?: boolean;
328
+ disableDrag?: boolean;
329
+ closeOnRouteChange?: boolean;
330
+ returnFocusTo?: string;
324
331
  backdrop?: boolean;
325
332
  closeOnBackdrop?: boolean;
326
333
  ariaLabel?: string;
package/dist/solid.d.ts 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,8 +275,9 @@ 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;
280
+ private containingExtent;
279
281
  private installFitObserver;
280
282
  destroy(): void;
281
283
  private emit;
@@ -321,6 +323,11 @@ type BottomSheetProps<TId extends string = string> = {
321
323
  backdropRange?: [number, number];
322
324
  radius?: string | number;
323
325
  maxHeight?: string | number;
326
+ persistent?: boolean;
327
+ disableClose?: boolean;
328
+ disableDrag?: boolean;
329
+ closeOnRouteChange?: boolean;
330
+ returnFocusTo?: string;
324
331
  backdrop?: boolean;
325
332
  closeOnBackdrop?: boolean;
326
333
  ariaLabel?: string;
package/dist/solid.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,45 +2911,52 @@ 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 poked = vertical ? el.offsetHeight : el.offsetWidth;
2931
+ const contentBox = vertical ? content.clientHeight : content.clientWidth;
2932
+ const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
2933
+ const natural = Math.max(poked, poked - contentBox + contentScroll);
2934
+ sheetStyle[axis] = prevSheet;
2935
+ cs.flex = prevFlex;
2936
+ if (vertical) cs.height = prevContent;
2937
+ else cs.width = prevContent;
2938
+ return natural;
2941
2939
  }
2942
2940
  measureFitSize() {
2943
2941
  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;
2942
+ const natural = this.measureSheetNatural(vertical);
2947
2943
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2948
2944
  if (typeof window === "undefined") return capped;
2949
- const viewport = vertical ? window.innerHeight : window.innerWidth;
2945
+ const viewport = this.containingExtent(vertical);
2950
2946
  return viewport > 0 ? Math.min(capped, viewport) : capped;
2951
2947
  }
2948
+ // The fit cap is the sheet's containing block, not always the window: a
2949
+ // position:fixed sheet nested under a transform/filter/will-change ancestor
2950
+ // is clipped to that ancestor, so capping by window.innerHeight oversizes the
2951
+ // sheet and the content/footer get clipped. offsetParent resolves to that
2952
+ // ancestor when present, and is null (→ viewport) for a plain fixed sheet.
2953
+ containingExtent(vertical) {
2954
+ const op = this.element.offsetParent;
2955
+ if (op && op !== document.body && op !== document.documentElement) {
2956
+ return vertical ? op.clientHeight : op.clientWidth;
2957
+ }
2958
+ return vertical ? window.innerHeight : window.innerWidth;
2959
+ }
2952
2960
  installFitObserver() {
2953
2961
  if (typeof ResizeObserver === "undefined") return;
2954
2962
  if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
@@ -3029,6 +3037,10 @@ var BottomSheetEngine = class {
3029
3037
  this.backdrop.style.opacity = "";
3030
3038
  this.backdrop.style.pointerEvents = "";
3031
3039
  }
3040
+ if (this.anchorHost) {
3041
+ this.anchorHost.style.removeProperty("--bs-size");
3042
+ this.anchorHost.style.removeProperty("--bs-progress");
3043
+ }
3032
3044
  if (this.screenComponent) {
3033
3045
  this.screenComponent.style.opacity = "";
3034
3046
  this.screenComponent.style.display = "";
@@ -3040,6 +3052,7 @@ var BottomSheetEngine = class {
3040
3052
  this.bus.emit(event, payload);
3041
3053
  }
3042
3054
  newCycle() {
3055
+ this.allowOvershoot = false;
3043
3056
  this.currentAbort.abort();
3044
3057
  this.currentAbort = new AbortController();
3045
3058
  return this.currentAbort.signal;
@@ -3105,6 +3118,7 @@ var BottomSheetEngine = class {
3105
3118
  seen.add(p.id);
3106
3119
  }
3107
3120
  this.snaps.setRaw(this.snapPointsRaw);
3121
+ this.clampToMaxHeight();
3108
3122
  this.scrim.invalidateOpacityCache();
3109
3123
  }
3110
3124
  getAllowedRange() {
@@ -3311,9 +3325,13 @@ var BottomSheetEngine = class {
3311
3325
  this.opening = true;
3312
3326
  sheetStack.promote(this.id);
3313
3327
  }
3314
- void this.animation.animateTo(target.size, velocity).then(() => {
3315
- this.opening = false;
3328
+ const settleCap = this.snaps.getMaxAxisSize();
3329
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3330
+ this.allowOvershoot = true;
3331
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3316
3332
  if (signal.aborted) return;
3333
+ this.allowOvershoot = false;
3334
+ this.opening = false;
3317
3335
  this.scrollCache.restore(target.id, previousSize, target.size);
3318
3336
  this.updateAriaSlider();
3319
3337
  this.emit("snap", {
@@ -3345,7 +3363,7 @@ var BottomSheetEngine = class {
3345
3363
  }
3346
3364
  applySize(size) {
3347
3365
  const cap = this.snaps.getMaxAxisSize();
3348
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3366
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3349
3367
  this.size = clamped;
3350
3368
  const offset = cap - clamped;
3351
3369
  const style = this.element.style;
@@ -3473,7 +3491,12 @@ var BottomSheet = (props) => {
3473
3491
  rubberBand: props.rubberBand,
3474
3492
  backdropRange: props.backdropRange,
3475
3493
  radius: props.radius,
3476
- maxHeight: props.maxHeight
3494
+ maxHeight: props.maxHeight,
3495
+ persistent: props.persistent,
3496
+ disableClose: props.disableClose,
3497
+ disableDrag: props.disableDrag,
3498
+ closeOnRouteChange: props.closeOnRouteChange,
3499
+ returnFocusTo: props.returnFocusTo
3477
3500
  };
3478
3501
  engine = new BottomSheetEngine(engineOpts);
3479
3502
  props.engineRef?.(engine);
@@ -3494,7 +3517,7 @@ var BottomSheet = (props) => {
3494
3517
  engine.on("dragend", sync);
3495
3518
  if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropEl) {
3496
3519
  const onBackdropClick = () => {
3497
- void engine?.close();
3520
+ if (engine?.canDismiss()) void engine.close("backdrop");
3498
3521
  };
3499
3522
  backdropEl.addEventListener("click", onBackdropClick);
3500
3523
  onCleanup(() => {
@@ -2359,6 +2359,7 @@ var BottomSheetEngine = class {
2359
2359
  progressWriteSentinel = new WriteSentinel();
2360
2360
  isTopSheet = true;
2361
2361
  opening = false;
2362
+ allowOvershoot = false;
2362
2363
  progressPayload = {
2363
2364
  value: 0,
2364
2365
  size: 0
@@ -2912,45 +2913,52 @@ 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 poked = vertical ? el.offsetHeight : el.offsetWidth;
2933
+ const contentBox = vertical ? content.clientHeight : content.clientWidth;
2934
+ const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
2935
+ const natural = Math.max(poked, poked - contentBox + contentScroll);
2936
+ sheetStyle[axis] = prevSheet;
2937
+ cs.flex = prevFlex;
2938
+ if (vertical) cs.height = prevContent;
2939
+ else cs.width = prevContent;
2940
+ return natural;
2943
2941
  }
2944
2942
  measureFitSize() {
2945
2943
  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;
2944
+ const natural = this.measureSheetNatural(vertical);
2949
2945
  const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2950
2946
  if (typeof window === "undefined") return capped;
2951
- const viewport = vertical ? window.innerHeight : window.innerWidth;
2947
+ const viewport = this.containingExtent(vertical);
2952
2948
  return viewport > 0 ? Math.min(capped, viewport) : capped;
2953
2949
  }
2950
+ // The fit cap is the sheet's containing block, not always the window: a
2951
+ // position:fixed sheet nested under a transform/filter/will-change ancestor
2952
+ // is clipped to that ancestor, so capping by window.innerHeight oversizes the
2953
+ // sheet and the content/footer get clipped. offsetParent resolves to that
2954
+ // ancestor when present, and is null (→ viewport) for a plain fixed sheet.
2955
+ containingExtent(vertical) {
2956
+ const op = this.element.offsetParent;
2957
+ if (op && op !== document.body && op !== document.documentElement) {
2958
+ return vertical ? op.clientHeight : op.clientWidth;
2959
+ }
2960
+ return vertical ? window.innerHeight : window.innerWidth;
2961
+ }
2954
2962
  installFitObserver() {
2955
2963
  if (typeof ResizeObserver === "undefined") return;
2956
2964
  if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
@@ -3031,6 +3039,10 @@ var BottomSheetEngine = class {
3031
3039
  this.backdrop.style.opacity = "";
3032
3040
  this.backdrop.style.pointerEvents = "";
3033
3041
  }
3042
+ if (this.anchorHost) {
3043
+ this.anchorHost.style.removeProperty("--bs-size");
3044
+ this.anchorHost.style.removeProperty("--bs-progress");
3045
+ }
3034
3046
  if (this.screenComponent) {
3035
3047
  this.screenComponent.style.opacity = "";
3036
3048
  this.screenComponent.style.display = "";
@@ -3042,6 +3054,7 @@ var BottomSheetEngine = class {
3042
3054
  this.bus.emit(event, payload);
3043
3055
  }
3044
3056
  newCycle() {
3057
+ this.allowOvershoot = false;
3045
3058
  this.currentAbort.abort();
3046
3059
  this.currentAbort = new AbortController();
3047
3060
  return this.currentAbort.signal;
@@ -3107,6 +3120,7 @@ var BottomSheetEngine = class {
3107
3120
  seen.add(p.id);
3108
3121
  }
3109
3122
  this.snaps.setRaw(this.snapPointsRaw);
3123
+ this.clampToMaxHeight();
3110
3124
  this.scrim.invalidateOpacityCache();
3111
3125
  }
3112
3126
  getAllowedRange() {
@@ -3313,9 +3327,13 @@ var BottomSheetEngine = class {
3313
3327
  this.opening = true;
3314
3328
  sheetStack.promote(this.id);
3315
3329
  }
3316
- void this.animation.animateTo(target.size, velocity).then(() => {
3317
- this.opening = false;
3330
+ const settleCap = this.snaps.getMaxAxisSize();
3331
+ const settleSize = settleCap > 0 ? Math.min(target.size, settleCap) : target.size;
3332
+ this.allowOvershoot = true;
3333
+ void this.animation.animateTo(settleSize, velocity).then(() => {
3318
3334
  if (signal.aborted) return;
3335
+ this.allowOvershoot = false;
3336
+ this.opening = false;
3319
3337
  this.scrollCache.restore(target.id, previousSize, target.size);
3320
3338
  this.updateAriaSlider();
3321
3339
  this.emit("snap", {
@@ -3347,7 +3365,7 @@ var BottomSheetEngine = class {
3347
3365
  }
3348
3366
  applySize(size) {
3349
3367
  const cap = this.snaps.getMaxAxisSize();
3350
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging ? cap : size;
3368
+ const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3351
3369
  this.size = clamped;
3352
3370
  const offset = cap - clamped;
3353
3371
  const style = this.element.style;
@@ -3471,7 +3489,12 @@ var BottomSheet = (props) => {
3471
3489
  rubberBand: props.rubberBand,
3472
3490
  backdropRange: props.backdropRange,
3473
3491
  radius: props.radius,
3474
- maxHeight: props.maxHeight
3492
+ maxHeight: props.maxHeight,
3493
+ persistent: props.persistent,
3494
+ disableClose: props.disableClose,
3495
+ disableDrag: props.disableDrag,
3496
+ closeOnRouteChange: props.closeOnRouteChange,
3497
+ returnFocusTo: props.returnFocusTo
3475
3498
  };
3476
3499
  engine = new BottomSheetEngine(engineOpts);
3477
3500
  props.engineRef?.(engine);
@@ -3490,7 +3513,7 @@ var BottomSheet = (props) => {
3490
3513
  engine.on("dragend", sync);
3491
3514
  if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropEl) {
3492
3515
  const onBackdropClick = () => {
3493
- void engine?.close();
3516
+ if (engine?.canDismiss()) void engine.close("backdrop");
3494
3517
  };
3495
3518
  backdropEl.addEventListener("click", onBackdropClick);
3496
3519
  onCleanup(() => {