@surdeddd/bottom-sheet 0.21.1 → 0.22.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.
Files changed (62) hide show
  1. package/README.md +32 -0
  2. package/dist/{BottomSheetCore-CK_mq14p.d.ts → BottomSheetCore-9i-Uh6T3.d.ts} +4 -1
  3. package/dist/{BottomSheetCore-BHv6LPmS.d.cts → BottomSheetCore-CQStdVy2.d.cts} +4 -1
  4. package/dist/{BottomSheetEngine-mmFzIK1Z.d.cts → BottomSheetEngine-CsQWHLNb.d.cts} +1 -1
  5. package/dist/{BottomSheetEngine-wLn6Q2kA.d.ts → BottomSheetEngine-Dn6h-7gF.d.ts} +1 -1
  6. package/dist/core.cjs +25 -7
  7. package/dist/core.d.cts +2 -2
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +25 -7
  10. package/dist/debug.d.cts +1 -1
  11. package/dist/debug.d.ts +1 -1
  12. package/dist/default-features-C3cilcW9.d.ts +11 -0
  13. package/dist/default-features-DkG9aho0.d.cts +11 -0
  14. package/dist/element.cjs +106 -15
  15. package/dist/element.d.cts +2 -2
  16. package/dist/element.d.ts +2 -2
  17. package/dist/element.iife.global.js +2 -2
  18. package/dist/element.js +106 -15
  19. package/dist/features.cjs +65 -1
  20. package/dist/features.d.cts +5 -10
  21. package/dist/features.d.ts +5 -10
  22. package/dist/features.js +65 -2
  23. package/dist/{index-juAyT76E.d.cts → index-CVGC5B5D.d.cts} +1 -1
  24. package/dist/{index-CWKv1Xy4.d.ts → index-CnsJQZp2.d.ts} +1 -1
  25. package/dist/index.cjs +89 -8
  26. package/dist/index.d.cts +5 -5
  27. package/dist/index.d.ts +5 -5
  28. package/dist/index.js +89 -8
  29. package/dist/integrations/formik.d.cts +1 -1
  30. package/dist/integrations/formik.d.ts +1 -1
  31. package/dist/integrations/react-hook-form.d.cts +1 -1
  32. package/dist/integrations/react-hook-form.d.ts +1 -1
  33. package/dist/preact.d.cts +2 -2
  34. package/dist/preact.d.ts +2 -2
  35. package/dist/qwik-lib/index.qwik.cjs +84 -6
  36. package/dist/qwik-lib/index.qwik.mjs +84 -6
  37. package/dist/qwik.cjs +90 -8
  38. package/dist/qwik.d.cts +3 -2
  39. package/dist/qwik.d.ts +3 -2
  40. package/dist/qwik.js +90 -8
  41. package/dist/react.cjs +89 -8
  42. package/dist/react.d.cts +3 -3
  43. package/dist/react.d.ts +3 -3
  44. package/dist/react.js +89 -8
  45. package/dist/solid.cjs +90 -8
  46. package/dist/solid.d.cts +4 -0
  47. package/dist/solid.d.ts +4 -0
  48. package/dist/solid.js +90 -8
  49. package/dist/solid.source.jsx +90 -8
  50. package/dist/styles.css +11 -0
  51. package/dist/svelte-core.cjs +89 -8
  52. package/dist/svelte-core.js +89 -8
  53. package/dist/svelte-src/BottomSheet.svelte +3 -0
  54. package/dist/svelte.cjs +90 -8
  55. package/dist/svelte.d.cts +1 -0
  56. package/dist/svelte.d.ts +1 -0
  57. package/dist/svelte.js +90 -8
  58. package/dist/vue.cjs +93 -8
  59. package/dist/vue.js +93 -8
  60. package/dist/webgl.d.cts +1 -1
  61. package/dist/webgl.d.ts +1 -1
  62. package/package.json +9 -9
@@ -381,14 +381,26 @@ function notifyLinkedSheets(sheets, self) {
381
381
  }
382
382
  }
383
383
 
384
+ // src/core/primitives/hot-path-thresholds.ts
385
+ var SIZE_WRITE_EPSILON = 0.5;
386
+ var OPACITY_WRITE_EPSILON = 5e-3;
387
+ var POINTER_EVENTS_OPACITY_THRESHOLD = 0.05;
388
+ var RANGE_DIVISION_EPSILON = 1e-4;
389
+
384
390
  // src/core/features/resize-observer.ts
385
391
  function installResizeObserver(deps) {
386
392
  if (typeof window === "undefined") {
387
393
  return () => {
388
394
  };
389
395
  }
396
+ const seatFor = () => {
397
+ const snap = deps.resolveActiveSnap();
398
+ const max = deps.getMaxAxisSize();
399
+ return { target: snap ? Math.min(snap.size, max) : null, max };
400
+ };
390
401
  const onResize = () => {
391
402
  if (deps.isDestroyed()) return;
403
+ const before = seatFor();
392
404
  deps.recomputeSnaps();
393
405
  const mode = deps.getMode();
394
406
  const isVerticalAxis = mode === "bottom" || mode === "top";
@@ -397,6 +409,10 @@ function installResizeObserver(deps) {
397
409
  if (viewportSize2 > 0 && viewportSize2 < max) {
398
410
  deps.setMaxAxisSize(viewportSize2);
399
411
  }
412
+ const after = seatFor();
413
+ if (before.target !== null && after.target !== null && Math.abs(after.target - before.target) < SIZE_WRITE_EPSILON && Math.abs(after.max - before.max) < SIZE_WRITE_EPSILON) {
414
+ return;
415
+ }
400
416
  const wasAnimating = deps.isAnimating?.() ?? false;
401
417
  deps.cancelInFlight();
402
418
  deps.newCycle();
@@ -665,12 +681,6 @@ var SCRIM_PRESETS = Object.freeze({
665
681
  }
666
682
  });
667
683
 
668
- // src/core/primitives/hot-path-thresholds.ts
669
- var SIZE_WRITE_EPSILON = 0.5;
670
- var OPACITY_WRITE_EPSILON = 5e-3;
671
- var POINTER_EVENTS_OPACITY_THRESHOLD = 0.05;
672
- var RANGE_DIVISION_EPSILON = 1e-4;
673
-
674
684
  // src/core/primitives/opacity-dedup.ts
675
685
  var WriteSentinel = class {
676
686
  last = -1;
@@ -2596,6 +2606,7 @@ var BottomSheetCore = class {
2596
2606
  lifecycle;
2597
2607
  closeOnBack;
2598
2608
  routedTo;
2609
+ fitContentToSnap;
2599
2610
  persistent;
2600
2611
  disableCloseFlag;
2601
2612
  disableDragFlag;
@@ -2710,6 +2721,7 @@ var BottomSheetCore = class {
2710
2721
  );
2711
2722
  this.closeOnBack = resolved.closeOnBack;
2712
2723
  this.routedTo = opts.routedTo;
2724
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2713
2725
  this.persistent = resolved.persistent;
2714
2726
  this.disableCloseFlag = resolved.disableClose;
2715
2727
  this.disableDragFlag = resolved.disableDrag;
@@ -2811,7 +2823,8 @@ var BottomSheetCore = class {
2811
2823
  closeOnBack: this.closeOnBack,
2812
2824
  closeOnRouteChange: this.closeOnRouteChange,
2813
2825
  persistKey: this.persistKey,
2814
- autoCollapseAfter
2826
+ autoCollapseAfter,
2827
+ fitContentToSnap: this.fitContentToSnap
2815
2828
  },
2816
2829
  isDestroyed: () => this.destroyed,
2817
2830
  isDragging: () => this.isDraggingAny(),
@@ -2863,6 +2876,11 @@ var BottomSheetCore = class {
2863
2876
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2864
2877
  );
2865
2878
  }
2879
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2880
+ devWarn(
2881
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2882
+ );
2883
+ }
2866
2884
  if (this.persistKey && !names.has("persist")) {
2867
2885
  devWarn(
2868
2886
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4220,6 +4238,68 @@ function visualViewportFeature() {
4220
4238
  };
4221
4239
  }
4222
4240
 
4241
+ // src/core/features/content-fit.ts
4242
+ var INSET_VAR = "--bs-content-inset";
4243
+ var FIT_ATTR = "data-bs-fit-content";
4244
+ function contentFitFeature() {
4245
+ return {
4246
+ name: "content-fit",
4247
+ install: (ctx) => {
4248
+ const scroller = ctx.scrollContainer;
4249
+ if (!ctx.options.fitContentToSnap || !scroller || typeof window === "undefined") {
4250
+ return;
4251
+ }
4252
+ const sheet = ctx.element;
4253
+ let inset = 0;
4254
+ let unpaddedMax = -1;
4255
+ let top = 0;
4256
+ const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4257
+ const follow = (size) => {
4258
+ if (unpaddedMax < 0) {
4259
+ unpaddedMax = scroller.scrollHeight - scroller.clientHeight - inset;
4260
+ top = scroller.scrollTop;
4261
+ }
4262
+ const limit = Math.max(0, unpaddedMax + hiddenAt(size));
4263
+ if (top > limit) {
4264
+ if (scroller.scrollTop > limit) scroller.scrollTop = limit;
4265
+ top = limit;
4266
+ }
4267
+ };
4268
+ const settle = () => {
4269
+ if (ctx.isDestroyed()) return;
4270
+ const size = ctx.getSize();
4271
+ unpaddedMax = -1;
4272
+ follow(size);
4273
+ inset = hiddenAt(size);
4274
+ sheet.style.setProperty(INSET_VAR, `${inset}px`);
4275
+ unpaddedMax = -1;
4276
+ };
4277
+ const moving = () => ctx.isAnimating() || ctx.isDragging();
4278
+ const whenIdle = () => {
4279
+ if (!moving()) settle();
4280
+ };
4281
+ sheet.setAttribute(FIT_ATTR, "");
4282
+ settle();
4283
+ const offProgress = ctx.on(
4284
+ "progress",
4285
+ (p) => moving() ? follow(p.size) : settle()
4286
+ );
4287
+ const offSnap = ctx.on("snap", settle);
4288
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4289
+ observer?.observe(document.documentElement);
4290
+ window.addEventListener("orientationchange", whenIdle);
4291
+ return () => {
4292
+ offProgress();
4293
+ offSnap();
4294
+ observer?.disconnect();
4295
+ window.removeEventListener("orientationchange", whenIdle);
4296
+ sheet.removeAttribute(FIT_ATTR);
4297
+ sheet.style.removeProperty(INSET_VAR);
4298
+ };
4299
+ }
4300
+ };
4301
+ }
4302
+
4223
4303
  // src/core/default-features.ts
4224
4304
  function defaultEngineFeatures() {
4225
4305
  return [
@@ -4227,7 +4307,8 @@ function defaultEngineFeatures() {
4227
4307
  visualViewportFeature(),
4228
4308
  persistFeature(),
4229
4309
  autoCollapseFeature(),
4230
- routeFeature()
4310
+ routeFeature(),
4311
+ contentFitFeature()
4231
4312
  ];
4232
4313
  }
4233
4314
 
@@ -4317,6 +4398,7 @@ var BottomSheet = (props) => {
4317
4398
  disableDrag: props.disableDrag,
4318
4399
  dragFrom: props.dragFrom,
4319
4400
  dragFromContent: props.dragFromContent,
4401
+ fitContentToSnap: props.fitContentToSnap,
4320
4402
  closeOnRouteChange: props.closeOnRouteChange,
4321
4403
  stackEffect: props.stackEffect,
4322
4404
  returnFocusTo: props.returnFocusTo
package/dist/styles.css CHANGED
@@ -280,6 +280,17 @@
280
280
  padding: var(--bs-content-padding, 0 16px 16px);
281
281
  }
282
282
 
283
+ .bs-sheet[data-bs-fit-content] .bs-content {
284
+ scroll-padding-bottom: var(--bs-content-inset, 0px);
285
+ }
286
+
287
+ .bs-sheet[data-bs-fit-content] .bs-content::after {
288
+ content: "";
289
+ display: block;
290
+ flex: none;
291
+ height: var(--bs-content-inset, 0px);
292
+ }
293
+
283
294
  .bs-footer {
284
295
  flex: 0 0 auto;
285
296
  padding: var(--bs-footer-padding, 12px 16px calc(12px + env(safe-area-inset-bottom)));
@@ -377,14 +377,26 @@ function notifyLinkedSheets(sheets, self) {
377
377
  }
378
378
  }
379
379
 
380
+ // src/core/primitives/hot-path-thresholds.ts
381
+ var SIZE_WRITE_EPSILON = 0.5;
382
+ var OPACITY_WRITE_EPSILON = 5e-3;
383
+ var POINTER_EVENTS_OPACITY_THRESHOLD = 0.05;
384
+ var RANGE_DIVISION_EPSILON = 1e-4;
385
+
380
386
  // src/core/features/resize-observer.ts
381
387
  function installResizeObserver(deps) {
382
388
  if (typeof window === "undefined") {
383
389
  return () => {
384
390
  };
385
391
  }
392
+ const seatFor = () => {
393
+ const snap = deps.resolveActiveSnap();
394
+ const max = deps.getMaxAxisSize();
395
+ return { target: snap ? Math.min(snap.size, max) : null, max };
396
+ };
386
397
  const onResize = () => {
387
398
  if (deps.isDestroyed()) return;
399
+ const before = seatFor();
388
400
  deps.recomputeSnaps();
389
401
  const mode = deps.getMode();
390
402
  const isVerticalAxis = mode === "bottom" || mode === "top";
@@ -393,6 +405,10 @@ function installResizeObserver(deps) {
393
405
  if (viewportSize2 > 0 && viewportSize2 < max) {
394
406
  deps.setMaxAxisSize(viewportSize2);
395
407
  }
408
+ const after = seatFor();
409
+ if (before.target !== null && after.target !== null && Math.abs(after.target - before.target) < SIZE_WRITE_EPSILON && Math.abs(after.max - before.max) < SIZE_WRITE_EPSILON) {
410
+ return;
411
+ }
396
412
  const wasAnimating = deps.isAnimating?.() ?? false;
397
413
  deps.cancelInFlight();
398
414
  deps.newCycle();
@@ -661,12 +677,6 @@ var SCRIM_PRESETS = Object.freeze({
661
677
  }
662
678
  });
663
679
 
664
- // src/core/primitives/hot-path-thresholds.ts
665
- var SIZE_WRITE_EPSILON = 0.5;
666
- var OPACITY_WRITE_EPSILON = 5e-3;
667
- var POINTER_EVENTS_OPACITY_THRESHOLD = 0.05;
668
- var RANGE_DIVISION_EPSILON = 1e-4;
669
-
670
680
  // src/core/primitives/opacity-dedup.ts
671
681
  var WriteSentinel = class {
672
682
  constructor() {
@@ -2596,6 +2606,7 @@ var BottomSheetCore = class {
2596
2606
  __publicField(this, "lifecycle");
2597
2607
  __publicField(this, "closeOnBack");
2598
2608
  __publicField(this, "routedTo");
2609
+ __publicField(this, "fitContentToSnap");
2599
2610
  __publicField(this, "persistent");
2600
2611
  __publicField(this, "disableCloseFlag");
2601
2612
  __publicField(this, "disableDragFlag");
@@ -2709,6 +2720,7 @@ var BottomSheetCore = class {
2709
2720
  );
2710
2721
  this.closeOnBack = resolved.closeOnBack;
2711
2722
  this.routedTo = opts.routedTo;
2723
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2712
2724
  this.persistent = resolved.persistent;
2713
2725
  this.disableCloseFlag = resolved.disableClose;
2714
2726
  this.disableDragFlag = resolved.disableDrag;
@@ -2810,7 +2822,8 @@ var BottomSheetCore = class {
2810
2822
  closeOnBack: this.closeOnBack,
2811
2823
  closeOnRouteChange: this.closeOnRouteChange,
2812
2824
  persistKey: this.persistKey,
2813
- autoCollapseAfter
2825
+ autoCollapseAfter,
2826
+ fitContentToSnap: this.fitContentToSnap
2814
2827
  },
2815
2828
  isDestroyed: () => this.destroyed,
2816
2829
  isDragging: () => this.isDraggingAny(),
@@ -2862,6 +2875,11 @@ var BottomSheetCore = class {
2862
2875
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2863
2876
  );
2864
2877
  }
2878
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2879
+ devWarn(
2880
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2881
+ );
2882
+ }
2865
2883
  if (this.persistKey && !names.has("persist")) {
2866
2884
  devWarn(
2867
2885
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4219,6 +4237,68 @@ function visualViewportFeature() {
4219
4237
  };
4220
4238
  }
4221
4239
 
4240
+ // src/core/features/content-fit.ts
4241
+ var INSET_VAR = "--bs-content-inset";
4242
+ var FIT_ATTR = "data-bs-fit-content";
4243
+ function contentFitFeature() {
4244
+ return {
4245
+ name: "content-fit",
4246
+ install: (ctx) => {
4247
+ const scroller = ctx.scrollContainer;
4248
+ if (!ctx.options.fitContentToSnap || !scroller || typeof window === "undefined") {
4249
+ return;
4250
+ }
4251
+ const sheet = ctx.element;
4252
+ let inset = 0;
4253
+ let unpaddedMax = -1;
4254
+ let top = 0;
4255
+ const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4256
+ const follow = (size) => {
4257
+ if (unpaddedMax < 0) {
4258
+ unpaddedMax = scroller.scrollHeight - scroller.clientHeight - inset;
4259
+ top = scroller.scrollTop;
4260
+ }
4261
+ const limit = Math.max(0, unpaddedMax + hiddenAt(size));
4262
+ if (top > limit) {
4263
+ if (scroller.scrollTop > limit) scroller.scrollTop = limit;
4264
+ top = limit;
4265
+ }
4266
+ };
4267
+ const settle = () => {
4268
+ if (ctx.isDestroyed()) return;
4269
+ const size = ctx.getSize();
4270
+ unpaddedMax = -1;
4271
+ follow(size);
4272
+ inset = hiddenAt(size);
4273
+ sheet.style.setProperty(INSET_VAR, `${inset}px`);
4274
+ unpaddedMax = -1;
4275
+ };
4276
+ const moving = () => ctx.isAnimating() || ctx.isDragging();
4277
+ const whenIdle = () => {
4278
+ if (!moving()) settle();
4279
+ };
4280
+ sheet.setAttribute(FIT_ATTR, "");
4281
+ settle();
4282
+ const offProgress = ctx.on(
4283
+ "progress",
4284
+ (p) => moving() ? follow(p.size) : settle()
4285
+ );
4286
+ const offSnap = ctx.on("snap", settle);
4287
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4288
+ observer?.observe(document.documentElement);
4289
+ window.addEventListener("orientationchange", whenIdle);
4290
+ return () => {
4291
+ offProgress();
4292
+ offSnap();
4293
+ observer?.disconnect();
4294
+ window.removeEventListener("orientationchange", whenIdle);
4295
+ sheet.removeAttribute(FIT_ATTR);
4296
+ sheet.style.removeProperty(INSET_VAR);
4297
+ };
4298
+ }
4299
+ };
4300
+ }
4301
+
4222
4302
  // src/core/default-features.ts
4223
4303
  function defaultEngineFeatures() {
4224
4304
  return [
@@ -4226,7 +4306,8 @@ function defaultEngineFeatures() {
4226
4306
  visualViewportFeature(),
4227
4307
  persistFeature(),
4228
4308
  autoCollapseFeature(),
4229
- routeFeature()
4309
+ routeFeature(),
4310
+ contentFitFeature()
4230
4311
  ];
4231
4312
  }
4232
4313
 
@@ -375,14 +375,26 @@ function notifyLinkedSheets(sheets, self) {
375
375
  }
376
376
  }
377
377
 
378
+ // src/core/primitives/hot-path-thresholds.ts
379
+ var SIZE_WRITE_EPSILON = 0.5;
380
+ var OPACITY_WRITE_EPSILON = 5e-3;
381
+ var POINTER_EVENTS_OPACITY_THRESHOLD = 0.05;
382
+ var RANGE_DIVISION_EPSILON = 1e-4;
383
+
378
384
  // src/core/features/resize-observer.ts
379
385
  function installResizeObserver(deps) {
380
386
  if (typeof window === "undefined") {
381
387
  return () => {
382
388
  };
383
389
  }
390
+ const seatFor = () => {
391
+ const snap = deps.resolveActiveSnap();
392
+ const max = deps.getMaxAxisSize();
393
+ return { target: snap ? Math.min(snap.size, max) : null, max };
394
+ };
384
395
  const onResize = () => {
385
396
  if (deps.isDestroyed()) return;
397
+ const before = seatFor();
386
398
  deps.recomputeSnaps();
387
399
  const mode = deps.getMode();
388
400
  const isVerticalAxis = mode === "bottom" || mode === "top";
@@ -391,6 +403,10 @@ function installResizeObserver(deps) {
391
403
  if (viewportSize2 > 0 && viewportSize2 < max) {
392
404
  deps.setMaxAxisSize(viewportSize2);
393
405
  }
406
+ const after = seatFor();
407
+ if (before.target !== null && after.target !== null && Math.abs(after.target - before.target) < SIZE_WRITE_EPSILON && Math.abs(after.max - before.max) < SIZE_WRITE_EPSILON) {
408
+ return;
409
+ }
394
410
  const wasAnimating = deps.isAnimating?.() ?? false;
395
411
  deps.cancelInFlight();
396
412
  deps.newCycle();
@@ -659,12 +675,6 @@ var SCRIM_PRESETS = Object.freeze({
659
675
  }
660
676
  });
661
677
 
662
- // src/core/primitives/hot-path-thresholds.ts
663
- var SIZE_WRITE_EPSILON = 0.5;
664
- var OPACITY_WRITE_EPSILON = 5e-3;
665
- var POINTER_EVENTS_OPACITY_THRESHOLD = 0.05;
666
- var RANGE_DIVISION_EPSILON = 1e-4;
667
-
668
678
  // src/core/primitives/opacity-dedup.ts
669
679
  var WriteSentinel = class {
670
680
  constructor() {
@@ -2594,6 +2604,7 @@ var BottomSheetCore = class {
2594
2604
  __publicField(this, "lifecycle");
2595
2605
  __publicField(this, "closeOnBack");
2596
2606
  __publicField(this, "routedTo");
2607
+ __publicField(this, "fitContentToSnap");
2597
2608
  __publicField(this, "persistent");
2598
2609
  __publicField(this, "disableCloseFlag");
2599
2610
  __publicField(this, "disableDragFlag");
@@ -2707,6 +2718,7 @@ var BottomSheetCore = class {
2707
2718
  );
2708
2719
  this.closeOnBack = resolved.closeOnBack;
2709
2720
  this.routedTo = opts.routedTo;
2721
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2710
2722
  this.persistent = resolved.persistent;
2711
2723
  this.disableCloseFlag = resolved.disableClose;
2712
2724
  this.disableDragFlag = resolved.disableDrag;
@@ -2808,7 +2820,8 @@ var BottomSheetCore = class {
2808
2820
  closeOnBack: this.closeOnBack,
2809
2821
  closeOnRouteChange: this.closeOnRouteChange,
2810
2822
  persistKey: this.persistKey,
2811
- autoCollapseAfter
2823
+ autoCollapseAfter,
2824
+ fitContentToSnap: this.fitContentToSnap
2812
2825
  },
2813
2826
  isDestroyed: () => this.destroyed,
2814
2827
  isDragging: () => this.isDraggingAny(),
@@ -2860,6 +2873,11 @@ var BottomSheetCore = class {
2860
2873
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2861
2874
  );
2862
2875
  }
2876
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2877
+ devWarn(
2878
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2879
+ );
2880
+ }
2863
2881
  if (this.persistKey && !names.has("persist")) {
2864
2882
  devWarn(
2865
2883
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4217,6 +4235,68 @@ function visualViewportFeature() {
4217
4235
  };
4218
4236
  }
4219
4237
 
4238
+ // src/core/features/content-fit.ts
4239
+ var INSET_VAR = "--bs-content-inset";
4240
+ var FIT_ATTR = "data-bs-fit-content";
4241
+ function contentFitFeature() {
4242
+ return {
4243
+ name: "content-fit",
4244
+ install: (ctx) => {
4245
+ const scroller = ctx.scrollContainer;
4246
+ if (!ctx.options.fitContentToSnap || !scroller || typeof window === "undefined") {
4247
+ return;
4248
+ }
4249
+ const sheet = ctx.element;
4250
+ let inset = 0;
4251
+ let unpaddedMax = -1;
4252
+ let top = 0;
4253
+ const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4254
+ const follow = (size) => {
4255
+ if (unpaddedMax < 0) {
4256
+ unpaddedMax = scroller.scrollHeight - scroller.clientHeight - inset;
4257
+ top = scroller.scrollTop;
4258
+ }
4259
+ const limit = Math.max(0, unpaddedMax + hiddenAt(size));
4260
+ if (top > limit) {
4261
+ if (scroller.scrollTop > limit) scroller.scrollTop = limit;
4262
+ top = limit;
4263
+ }
4264
+ };
4265
+ const settle = () => {
4266
+ if (ctx.isDestroyed()) return;
4267
+ const size = ctx.getSize();
4268
+ unpaddedMax = -1;
4269
+ follow(size);
4270
+ inset = hiddenAt(size);
4271
+ sheet.style.setProperty(INSET_VAR, `${inset}px`);
4272
+ unpaddedMax = -1;
4273
+ };
4274
+ const moving = () => ctx.isAnimating() || ctx.isDragging();
4275
+ const whenIdle = () => {
4276
+ if (!moving()) settle();
4277
+ };
4278
+ sheet.setAttribute(FIT_ATTR, "");
4279
+ settle();
4280
+ const offProgress = ctx.on(
4281
+ "progress",
4282
+ (p) => moving() ? follow(p.size) : settle()
4283
+ );
4284
+ const offSnap = ctx.on("snap", settle);
4285
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4286
+ observer?.observe(document.documentElement);
4287
+ window.addEventListener("orientationchange", whenIdle);
4288
+ return () => {
4289
+ offProgress();
4290
+ offSnap();
4291
+ observer?.disconnect();
4292
+ window.removeEventListener("orientationchange", whenIdle);
4293
+ sheet.removeAttribute(FIT_ATTR);
4294
+ sheet.style.removeProperty(INSET_VAR);
4295
+ };
4296
+ }
4297
+ };
4298
+ }
4299
+
4220
4300
  // src/core/default-features.ts
4221
4301
  function defaultEngineFeatures() {
4222
4302
  return [
@@ -4224,7 +4304,8 @@ function defaultEngineFeatures() {
4224
4304
  visualViewportFeature(),
4225
4305
  persistFeature(),
4226
4306
  autoCollapseFeature(),
4227
- routeFeature()
4307
+ routeFeature(),
4308
+ contentFitFeature()
4228
4309
  ];
4229
4310
  }
4230
4311
 
@@ -36,6 +36,7 @@
36
36
  disableDrag?: boolean;
37
37
  dragFrom?: EngineOptions["dragFrom"];
38
38
  dragFromContent?: boolean;
39
+ fitContentToSnap?: boolean;
39
40
  closeOnRouteChange?: boolean;
40
41
  stackEffect?: boolean;
41
42
  teleport?: boolean;
@@ -88,6 +89,7 @@
88
89
  disableDrag = false,
89
90
  dragFrom,
90
91
  dragFromContent,
92
+ fitContentToSnap,
91
93
  closeOnRouteChange = false,
92
94
  stackEffect = false,
93
95
  teleport = false,
@@ -164,6 +166,7 @@
164
166
  disableDrag,
165
167
  dragFrom,
166
168
  dragFromContent,
169
+ fitContentToSnap,
167
170
  closeOnRouteChange,
168
171
  stackEffect,
169
172
  radius,