@surdeddd/bottom-sheet 0.21.2 → 0.22.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.
Files changed (62) hide show
  1. package/README.md +33 -1
  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 +9 -1
  7. package/dist/core.d.cts +2 -2
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +9 -1
  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 +84 -4
  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 +84 -4
  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 +73 -2
  26. package/dist/index.d.cts +5 -5
  27. package/dist/index.d.ts +5 -5
  28. package/dist/index.js +73 -2
  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 +67 -2
  36. package/dist/qwik-lib/index.qwik.mjs +67 -2
  37. package/dist/qwik.cjs +74 -2
  38. package/dist/qwik.d.cts +3 -2
  39. package/dist/qwik.d.ts +3 -2
  40. package/dist/qwik.js +74 -2
  41. package/dist/react.cjs +73 -2
  42. package/dist/react.d.cts +3 -3
  43. package/dist/react.d.ts +3 -3
  44. package/dist/react.js +73 -2
  45. package/dist/solid.cjs +74 -2
  46. package/dist/solid.d.cts +4 -0
  47. package/dist/solid.d.ts +4 -0
  48. package/dist/solid.js +74 -2
  49. package/dist/solid.source.jsx +74 -2
  50. package/dist/styles.css +11 -0
  51. package/dist/svelte-core.cjs +73 -2
  52. package/dist/svelte-core.js +73 -2
  53. package/dist/svelte-src/BottomSheet.svelte +3 -0
  54. package/dist/svelte.cjs +74 -2
  55. package/dist/svelte.d.cts +1 -0
  56. package/dist/svelte.d.ts +1 -0
  57. package/dist/svelte.js +74 -2
  58. package/dist/vue.cjs +77 -2
  59. package/dist/vue.js +77 -2
  60. package/dist/webgl.d.cts +1 -1
  61. package/dist/webgl.d.ts +1 -1
  62. package/package.json +9 -9
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)));
@@ -2606,6 +2606,7 @@ var BottomSheetCore = class {
2606
2606
  __publicField(this, "lifecycle");
2607
2607
  __publicField(this, "closeOnBack");
2608
2608
  __publicField(this, "routedTo");
2609
+ __publicField(this, "fitContentToSnap");
2609
2610
  __publicField(this, "persistent");
2610
2611
  __publicField(this, "disableCloseFlag");
2611
2612
  __publicField(this, "disableDragFlag");
@@ -2719,6 +2720,7 @@ var BottomSheetCore = class {
2719
2720
  );
2720
2721
  this.closeOnBack = resolved.closeOnBack;
2721
2722
  this.routedTo = opts.routedTo;
2723
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2722
2724
  this.persistent = resolved.persistent;
2723
2725
  this.disableCloseFlag = resolved.disableClose;
2724
2726
  this.disableDragFlag = resolved.disableDrag;
@@ -2820,7 +2822,8 @@ var BottomSheetCore = class {
2820
2822
  closeOnBack: this.closeOnBack,
2821
2823
  closeOnRouteChange: this.closeOnRouteChange,
2822
2824
  persistKey: this.persistKey,
2823
- autoCollapseAfter
2825
+ autoCollapseAfter,
2826
+ fitContentToSnap: this.fitContentToSnap
2824
2827
  },
2825
2828
  isDestroyed: () => this.destroyed,
2826
2829
  isDragging: () => this.isDraggingAny(),
@@ -2872,6 +2875,11 @@ var BottomSheetCore = class {
2872
2875
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2873
2876
  );
2874
2877
  }
2878
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2879
+ devWarn(
2880
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2881
+ );
2882
+ }
2875
2883
  if (this.persistKey && !names.has("persist")) {
2876
2884
  devWarn(
2877
2885
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4229,6 +4237,68 @@ function visualViewportFeature() {
4229
4237
  };
4230
4238
  }
4231
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
+
4232
4302
  // src/core/default-features.ts
4233
4303
  function defaultEngineFeatures() {
4234
4304
  return [
@@ -4236,7 +4306,8 @@ function defaultEngineFeatures() {
4236
4306
  visualViewportFeature(),
4237
4307
  persistFeature(),
4238
4308
  autoCollapseFeature(),
4239
- routeFeature()
4309
+ routeFeature(),
4310
+ contentFitFeature()
4240
4311
  ];
4241
4312
  }
4242
4313
 
@@ -2604,6 +2604,7 @@ var BottomSheetCore = class {
2604
2604
  __publicField(this, "lifecycle");
2605
2605
  __publicField(this, "closeOnBack");
2606
2606
  __publicField(this, "routedTo");
2607
+ __publicField(this, "fitContentToSnap");
2607
2608
  __publicField(this, "persistent");
2608
2609
  __publicField(this, "disableCloseFlag");
2609
2610
  __publicField(this, "disableDragFlag");
@@ -2717,6 +2718,7 @@ var BottomSheetCore = class {
2717
2718
  );
2718
2719
  this.closeOnBack = resolved.closeOnBack;
2719
2720
  this.routedTo = opts.routedTo;
2721
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2720
2722
  this.persistent = resolved.persistent;
2721
2723
  this.disableCloseFlag = resolved.disableClose;
2722
2724
  this.disableDragFlag = resolved.disableDrag;
@@ -2818,7 +2820,8 @@ var BottomSheetCore = class {
2818
2820
  closeOnBack: this.closeOnBack,
2819
2821
  closeOnRouteChange: this.closeOnRouteChange,
2820
2822
  persistKey: this.persistKey,
2821
- autoCollapseAfter
2823
+ autoCollapseAfter,
2824
+ fitContentToSnap: this.fitContentToSnap
2822
2825
  },
2823
2826
  isDestroyed: () => this.destroyed,
2824
2827
  isDragging: () => this.isDraggingAny(),
@@ -2870,6 +2873,11 @@ var BottomSheetCore = class {
2870
2873
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2871
2874
  );
2872
2875
  }
2876
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2877
+ devWarn(
2878
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2879
+ );
2880
+ }
2873
2881
  if (this.persistKey && !names.has("persist")) {
2874
2882
  devWarn(
2875
2883
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4227,6 +4235,68 @@ function visualViewportFeature() {
4227
4235
  };
4228
4236
  }
4229
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
+
4230
4300
  // src/core/default-features.ts
4231
4301
  function defaultEngineFeatures() {
4232
4302
  return [
@@ -4234,7 +4304,8 @@ function defaultEngineFeatures() {
4234
4304
  visualViewportFeature(),
4235
4305
  persistFeature(),
4236
4306
  autoCollapseFeature(),
4237
- routeFeature()
4307
+ routeFeature(),
4308
+ contentFitFeature()
4238
4309
  ];
4239
4310
  }
4240
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,
package/dist/svelte.cjs CHANGED
@@ -2628,6 +2628,7 @@ var BottomSheetCore = class {
2628
2628
  __publicField(this, "lifecycle");
2629
2629
  __publicField(this, "closeOnBack");
2630
2630
  __publicField(this, "routedTo");
2631
+ __publicField(this, "fitContentToSnap");
2631
2632
  __publicField(this, "persistent");
2632
2633
  __publicField(this, "disableCloseFlag");
2633
2634
  __publicField(this, "disableDragFlag");
@@ -2741,6 +2742,7 @@ var BottomSheetCore = class {
2741
2742
  );
2742
2743
  this.closeOnBack = resolved.closeOnBack;
2743
2744
  this.routedTo = opts.routedTo;
2745
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2744
2746
  this.persistent = resolved.persistent;
2745
2747
  this.disableCloseFlag = resolved.disableClose;
2746
2748
  this.disableDragFlag = resolved.disableDrag;
@@ -2842,7 +2844,8 @@ var BottomSheetCore = class {
2842
2844
  closeOnBack: this.closeOnBack,
2843
2845
  closeOnRouteChange: this.closeOnRouteChange,
2844
2846
  persistKey: this.persistKey,
2845
- autoCollapseAfter
2847
+ autoCollapseAfter,
2848
+ fitContentToSnap: this.fitContentToSnap
2846
2849
  },
2847
2850
  isDestroyed: () => this.destroyed,
2848
2851
  isDragging: () => this.isDraggingAny(),
@@ -2894,6 +2897,11 @@ var BottomSheetCore = class {
2894
2897
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2895
2898
  );
2896
2899
  }
2900
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2901
+ devWarn(
2902
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2903
+ );
2904
+ }
2897
2905
  if (this.persistKey && !names.has("persist")) {
2898
2906
  devWarn(
2899
2907
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4251,6 +4259,68 @@ function visualViewportFeature() {
4251
4259
  };
4252
4260
  }
4253
4261
 
4262
+ // src/core/features/content-fit.ts
4263
+ var INSET_VAR = "--bs-content-inset";
4264
+ var FIT_ATTR = "data-bs-fit-content";
4265
+ function contentFitFeature() {
4266
+ return {
4267
+ name: "content-fit",
4268
+ install: (ctx) => {
4269
+ const scroller = ctx.scrollContainer;
4270
+ if (!ctx.options.fitContentToSnap || !scroller || typeof window === "undefined") {
4271
+ return;
4272
+ }
4273
+ const sheet = ctx.element;
4274
+ let inset = 0;
4275
+ let unpaddedMax = -1;
4276
+ let top = 0;
4277
+ const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4278
+ const follow = (size) => {
4279
+ if (unpaddedMax < 0) {
4280
+ unpaddedMax = scroller.scrollHeight - scroller.clientHeight - inset;
4281
+ top = scroller.scrollTop;
4282
+ }
4283
+ const limit = Math.max(0, unpaddedMax + hiddenAt(size));
4284
+ if (top > limit) {
4285
+ if (scroller.scrollTop > limit) scroller.scrollTop = limit;
4286
+ top = limit;
4287
+ }
4288
+ };
4289
+ const settle = () => {
4290
+ if (ctx.isDestroyed()) return;
4291
+ const size = ctx.getSize();
4292
+ unpaddedMax = -1;
4293
+ follow(size);
4294
+ inset = hiddenAt(size);
4295
+ sheet.style.setProperty(INSET_VAR, `${inset}px`);
4296
+ unpaddedMax = -1;
4297
+ };
4298
+ const moving = () => ctx.isAnimating() || ctx.isDragging();
4299
+ const whenIdle = () => {
4300
+ if (!moving()) settle();
4301
+ };
4302
+ sheet.setAttribute(FIT_ATTR, "");
4303
+ settle();
4304
+ const offProgress = ctx.on(
4305
+ "progress",
4306
+ (p) => moving() ? follow(p.size) : settle()
4307
+ );
4308
+ const offSnap = ctx.on("snap", settle);
4309
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4310
+ observer?.observe(document.documentElement);
4311
+ window.addEventListener("orientationchange", whenIdle);
4312
+ return () => {
4313
+ offProgress();
4314
+ offSnap();
4315
+ observer?.disconnect();
4316
+ window.removeEventListener("orientationchange", whenIdle);
4317
+ sheet.removeAttribute(FIT_ATTR);
4318
+ sheet.style.removeProperty(INSET_VAR);
4319
+ };
4320
+ }
4321
+ };
4322
+ }
4323
+
4254
4324
  // src/core/default-features.ts
4255
4325
  function defaultEngineFeatures() {
4256
4326
  return [
@@ -4258,7 +4328,8 @@ function defaultEngineFeatures() {
4258
4328
  visualViewportFeature(),
4259
4329
  persistFeature(),
4260
4330
  autoCollapseFeature(),
4261
- routeFeature()
4331
+ routeFeature(),
4332
+ contentFitFeature()
4262
4333
  ];
4263
4334
  }
4264
4335
 
@@ -4434,6 +4505,7 @@ function BottomSheet($$anchor, $$props) {
4434
4505
  disableDrag: disableDrag(),
4435
4506
  dragFrom: $$props.dragFrom,
4436
4507
  dragFromContent: $$props.dragFromContent,
4508
+ fitContentToSnap: $$props.fitContentToSnap,
4437
4509
  closeOnRouteChange: closeOnRouteChange(),
4438
4510
  stackEffect: stackEffect(),
4439
4511
  radius: $$props.radius,
package/dist/svelte.d.cts CHANGED
@@ -90,6 +90,7 @@ export type BottomSheetProps<TId extends string = string> = {
90
90
  disableDrag?: boolean;
91
91
  dragFrom?: "handle" | "sheet" | "zones";
92
92
  dragFromContent?: boolean;
93
+ fitContentToSnap?: boolean;
93
94
  closeOnRouteChange?: boolean;
94
95
  stackEffect?: boolean;
95
96
  teleport?: boolean;
package/dist/svelte.d.ts CHANGED
@@ -90,6 +90,7 @@ export type BottomSheetProps<TId extends string = string> = {
90
90
  disableDrag?: boolean;
91
91
  dragFrom?: "handle" | "sheet" | "zones";
92
92
  dragFromContent?: boolean;
93
+ fitContentToSnap?: boolean;
93
94
  closeOnRouteChange?: boolean;
94
95
  stackEffect?: boolean;
95
96
  teleport?: boolean;
package/dist/svelte.js CHANGED
@@ -2606,6 +2606,7 @@ var BottomSheetCore = class {
2606
2606
  __publicField(this, "lifecycle");
2607
2607
  __publicField(this, "closeOnBack");
2608
2608
  __publicField(this, "routedTo");
2609
+ __publicField(this, "fitContentToSnap");
2609
2610
  __publicField(this, "persistent");
2610
2611
  __publicField(this, "disableCloseFlag");
2611
2612
  __publicField(this, "disableDragFlag");
@@ -2719,6 +2720,7 @@ var BottomSheetCore = class {
2719
2720
  );
2720
2721
  this.closeOnBack = resolved.closeOnBack;
2721
2722
  this.routedTo = opts.routedTo;
2723
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2722
2724
  this.persistent = resolved.persistent;
2723
2725
  this.disableCloseFlag = resolved.disableClose;
2724
2726
  this.disableDragFlag = resolved.disableDrag;
@@ -2820,7 +2822,8 @@ var BottomSheetCore = class {
2820
2822
  closeOnBack: this.closeOnBack,
2821
2823
  closeOnRouteChange: this.closeOnRouteChange,
2822
2824
  persistKey: this.persistKey,
2823
- autoCollapseAfter
2825
+ autoCollapseAfter,
2826
+ fitContentToSnap: this.fitContentToSnap
2824
2827
  },
2825
2828
  isDestroyed: () => this.destroyed,
2826
2829
  isDragging: () => this.isDraggingAny(),
@@ -2872,6 +2875,11 @@ var BottomSheetCore = class {
2872
2875
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2873
2876
  );
2874
2877
  }
2878
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2879
+ devWarn(
2880
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2881
+ );
2882
+ }
2875
2883
  if (this.persistKey && !names.has("persist")) {
2876
2884
  devWarn(
2877
2885
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4229,6 +4237,68 @@ function visualViewportFeature() {
4229
4237
  };
4230
4238
  }
4231
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
+
4232
4302
  // src/core/default-features.ts
4233
4303
  function defaultEngineFeatures() {
4234
4304
  return [
@@ -4236,7 +4306,8 @@ function defaultEngineFeatures() {
4236
4306
  visualViewportFeature(),
4237
4307
  persistFeature(),
4238
4308
  autoCollapseFeature(),
4239
- routeFeature()
4309
+ routeFeature(),
4310
+ contentFitFeature()
4240
4311
  ];
4241
4312
  }
4242
4313
 
@@ -4412,6 +4483,7 @@ function BottomSheet($$anchor, $$props) {
4412
4483
  disableDrag: disableDrag(),
4413
4484
  dragFrom: $$props.dragFrom,
4414
4485
  dragFromContent: $$props.dragFromContent,
4486
+ fitContentToSnap: $$props.fitContentToSnap,
4415
4487
  closeOnRouteChange: closeOnRouteChange(),
4416
4488
  stackEffect: stackEffect(),
4417
4489
  radius: $$props.radius,
package/dist/vue.cjs CHANGED
@@ -2606,6 +2606,7 @@ var BottomSheetCore = class {
2606
2606
  __publicField(this, "lifecycle");
2607
2607
  __publicField(this, "closeOnBack");
2608
2608
  __publicField(this, "routedTo");
2609
+ __publicField(this, "fitContentToSnap");
2609
2610
  __publicField(this, "persistent");
2610
2611
  __publicField(this, "disableCloseFlag");
2611
2612
  __publicField(this, "disableDragFlag");
@@ -2719,6 +2720,7 @@ var BottomSheetCore = class {
2719
2720
  );
2720
2721
  this.closeOnBack = resolved.closeOnBack;
2721
2722
  this.routedTo = opts.routedTo;
2723
+ this.fitContentToSnap = opts.fitContentToSnap === true;
2722
2724
  this.persistent = resolved.persistent;
2723
2725
  this.disableCloseFlag = resolved.disableClose;
2724
2726
  this.disableDragFlag = resolved.disableDrag;
@@ -2820,7 +2822,8 @@ var BottomSheetCore = class {
2820
2822
  closeOnBack: this.closeOnBack,
2821
2823
  closeOnRouteChange: this.closeOnRouteChange,
2822
2824
  persistKey: this.persistKey,
2823
- autoCollapseAfter
2825
+ autoCollapseAfter,
2826
+ fitContentToSnap: this.fitContentToSnap
2824
2827
  },
2825
2828
  isDestroyed: () => this.destroyed,
2826
2829
  isDragging: () => this.isDraggingAny(),
@@ -2872,6 +2875,11 @@ var BottomSheetCore = class {
2872
2875
  "[BottomSheet] closeOnBack/routedTo/closeOnRouteChange need routeFeature() \u2014 option ignored"
2873
2876
  );
2874
2877
  }
2878
+ if (this.fitContentToSnap && !names.has("content-fit")) {
2879
+ devWarn(
2880
+ "[BottomSheet] fitContentToSnap needs contentFitFeature() \u2014 option ignored"
2881
+ );
2882
+ }
2875
2883
  if (this.persistKey && !names.has("persist")) {
2876
2884
  devWarn(
2877
2885
  "[BottomSheet] persistKey needs persistFeature() \u2014 snaps will not be saved"
@@ -4229,6 +4237,68 @@ function visualViewportFeature() {
4229
4237
  };
4230
4238
  }
4231
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
+
4232
4302
  // src/core/default-features.ts
4233
4303
  function defaultEngineFeatures() {
4234
4304
  return [
@@ -4236,7 +4306,8 @@ function defaultEngineFeatures() {
4236
4306
  visualViewportFeature(),
4237
4307
  persistFeature(),
4238
4308
  autoCollapseFeature(),
4239
- routeFeature()
4309
+ routeFeature(),
4310
+ contentFitFeature()
4240
4311
  ];
4241
4312
  }
4242
4313
 
@@ -4453,6 +4524,10 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
4453
4524
  type: Boolean,
4454
4525
  required: false
4455
4526
  },
4527
+ fitContentToSnap: {
4528
+ type: Boolean,
4529
+ required: false
4530
+ },
4456
4531
  rubberBand: {
4457
4532
  type: Boolean,
4458
4533
  required: false