@surdeddd/bottom-sheet 0.22.1 → 0.23.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/element.js CHANGED
@@ -1628,13 +1628,17 @@ var init_animation_runner = __esm({
1628
1628
  });
1629
1629
  let stopped = false;
1630
1630
  let auxRaf = 0;
1631
- const start = performance.now();
1632
1631
  const lastIdx = samples.values.length - 1;
1633
1632
  const auxTick = () => {
1634
1633
  if (stopped) return;
1635
- const elapsed = performance.now() - start;
1636
- const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
1637
- applyAux(samples.values[idx]);
1634
+ const at = Math.min(
1635
+ (Number(anim.currentTime) || 0) / samples.stepMs,
1636
+ lastIdx
1637
+ );
1638
+ const idx = Math.floor(at);
1639
+ const from = samples.values[idx];
1640
+ const to = samples.values[Math.min(idx + 1, lastIdx)];
1641
+ applyAux(from + (to - from) * (at - idx));
1638
1642
  auxRaf = requestAnimationFrame(auxTick);
1639
1643
  };
1640
1644
  auxRaf = requestAnimationFrame(auxTick);
@@ -2982,7 +2986,11 @@ var init_BottomSheetCore = __esm({
2982
2986
  getSize: () => this.size,
2983
2987
  isDragging: () => this.isDraggingAny(),
2984
2988
  applyAux: (size) => this.applySize(size, true),
2985
- getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2989
+ getTransformFor: (size) => {
2990
+ const cap = this.snaps.getMaxAxisSize();
2991
+ const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2992
+ return this.transformTemplate(cap - shown);
2993
+ }
2986
2994
  },
2987
2995
  resolved.animation
2988
2996
  );
@@ -4564,6 +4572,8 @@ function contentFitFeature() {
4564
4572
  let inset = 0;
4565
4573
  let unpaddedMax = -1;
4566
4574
  let top = 0;
4575
+ let resting = false;
4576
+ const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4567
4577
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4568
4578
  const follow = (size) => {
4569
4579
  if (unpaddedMax < 0) {
@@ -4579,21 +4589,36 @@ function contentFitFeature() {
4579
4589
  const settle = () => {
4580
4590
  if (ctx.isDestroyed()) return;
4581
4591
  const size = ctx.getSize();
4582
- unpaddedMax = -1;
4583
- follow(size);
4592
+ if (!resting) {
4593
+ unpaddedMax = -1;
4594
+ follow(size);
4595
+ }
4584
4596
  inset = hiddenAt(size);
4585
- sheet.style.setProperty(INSET_VAR, `${inset}px`);
4597
+ put(INSET_VAR, inset);
4598
+ put(SIZE_VAR, size);
4599
+ put(CAP_VAR, ctx.getMaxAxisSize());
4600
+ if (!resting) {
4601
+ resting = true;
4602
+ sheet.setAttribute(FIT_ATTR, "rest");
4603
+ }
4586
4604
  unpaddedMax = -1;
4587
4605
  };
4606
+ const move = (size) => {
4607
+ if (resting) {
4608
+ resting = false;
4609
+ sheet.setAttribute(FIT_ATTR, "moving");
4610
+ put(LIFT_VAR, scroller.offsetHeight);
4611
+ }
4612
+ follow(size);
4613
+ };
4588
4614
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4589
4615
  const whenIdle = () => {
4590
4616
  if (!moving()) settle();
4591
4617
  };
4592
- sheet.setAttribute(FIT_ATTR, "");
4593
4618
  settle();
4594
4619
  const offProgress = ctx.on(
4595
4620
  "progress",
4596
- (p) => moving() ? follow(p.size) : settle()
4621
+ (p) => moving() ? move(p.size) : settle()
4597
4622
  );
4598
4623
  const offSnap = ctx.on("snap", settle);
4599
4624
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
@@ -4605,15 +4630,20 @@ function contentFitFeature() {
4605
4630
  observer?.disconnect();
4606
4631
  window.removeEventListener("orientationchange", whenIdle);
4607
4632
  sheet.removeAttribute(FIT_ATTR);
4608
- sheet.style.removeProperty(INSET_VAR);
4633
+ for (const name of [INSET_VAR, CAP_VAR, LIFT_VAR]) {
4634
+ sheet.style.removeProperty(name);
4635
+ }
4609
4636
  };
4610
4637
  }
4611
4638
  };
4612
4639
  }
4613
- var INSET_VAR, FIT_ATTR;
4640
+ var INSET_VAR, SIZE_VAR, CAP_VAR, LIFT_VAR, FIT_ATTR;
4614
4641
  var init_content_fit = __esm({
4615
4642
  "src/core/features/content-fit.ts"() {
4616
4643
  INSET_VAR = "--bs-content-inset";
4644
+ SIZE_VAR = "--bs-size";
4645
+ CAP_VAR = "--bs-max-size";
4646
+ LIFT_VAR = "--bs-footer-lift-max";
4617
4647
  FIT_ATTR = "data-bs-fit-content";
4618
4648
  }
4619
4649
  });
@@ -4657,7 +4687,7 @@ var init_BottomSheetEngine = __esm({
4657
4687
  var baseStyles;
4658
4688
  var init_baseStyles = __esm({
4659
4689
  "src/web-component/baseStyles.ts"() {
4660
- baseStyles = `:where(.bs-root){--bs-surface-d:#ffffff;--bs-surface-border-d:rgba(225,227,237,1);--bs-radius-d:20px;--bs-handle-color-d:rgba(26,22,20,0.3);--bs-handle-width:40px;--bs-handle-height:5px;--bs-z-backdrop:90;--bs-z-sheet:100;--bs-backdrop-color-d:rgba(0,0,0,0.5);--bs-scrim-color-d:transparent;--bs-scrim-blur:0px;--bs-z-scrim:calc(var(--bs-z-sheet) - 1);--bs-size:0px;--bs-progress:0}.bs-backdrop{position:fixed;inset:0;background:var(--bs-backdrop-color,var(--bs-backdrop-color-d));opacity:0;pointer-events:none;z-index:var(--bs-z-backdrop);transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-backdrop,.bs-root[data-animating="true"] .bs-backdrop{transition:none}.bs-sheet{position:fixed;background:var(--bs-surface,var(--bs-surface-d));box-shadow:var(--bs-shadow,var(--bs-shadow-auto,none));--bs-shadow-fade:clamp(0,calc(var(--bs-progress,0) * 8),1);z-index:var(--bs-z-sheet);pointer-events:auto;overflow:hidden;display:flex;flex-direction:column;-webkit-tap-highlight-color:transparent;user-select:none;overscroll-behavior:contain}.bs-sheet[data-mode="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));padding-bottom:env(safe-area-inset-bottom);--bs-shadow-auto:0 calc(var(--bs-progress,0) * -2px - 3px) calc(var(--bs-progress,0) * 18px + 12px) rgba( 0,0,0,calc(var(--bs-shadow-fade) * (var(--bs-progress,0) * 0.15 + 0.12)) )}.bs-sheet[data-mode="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom:1px solid var(--bs-surface-border,var(--bs-surface-border-d));flex-direction:column-reverse;--bs-shadow-auto:0 3px 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12));padding-top:env(safe-area-inset-top)}.bs-sheet[data-mode="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:3px 0 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12))}.bs-sheet[data-mode="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:-3px 0 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12))}.bs-sheet[data-bs-rest="closed"]{box-shadow:none;visibility:hidden}.bs-sheet[data-bs-webgl="on"],.bs-sheet[data-bs-webgl="on"] .bs-handle,.bs-sheet[data-bs-webgl="on"] .bs-header,.bs-sheet[data-bs-webgl="on"] .bs-footer{background:transparent;box-shadow:none}.bs-sheet[data-mode="left"] .bs-content{padding-right:36px}.bs-sheet[data-mode="right"] .bs-content{padding-left:36px}.bs-handle{flex-shrink:0;min-height:44px;display:flex;flex-direction:column;justify-content:center;padding:var(--bs-handle-padding,8px 16px 4px);cursor:grab;touch-action:none;user-select:none;background:var(--bs-surface,var(--bs-surface-d));-webkit-tap-highlight-color:transparent;outline:none;position:relative}.bs-handle:active{cursor:grabbing}.bs-handle:focus-visible{outline:2px solid currentColor;outline-offset:-2px;border-radius:var(--bs-radius,var(--bs-radius-d))}.bs-handle::before{content:"";display:block;width:var(--bs-handle-width);height:var(--bs-handle-height);background:var(--bs-handle-color,var(--bs-handle-color-d));border-radius:calc(var(--bs-handle-height) / 2);margin:0 auto 8px;transition:width 0.15s ease,background 0.15s ease,transform 0.15s ease;pointer-events:none}.bs-sheet[data-mode="left"] .bs-handle,.bs-sheet[data-mode="right"] .bs-handle{position:absolute;top:0;bottom:0;width:28px;min-width:0;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0;background:var(--bs-surface,var(--bs-surface-d));z-index:1;overflow:hidden}.bs-sheet[data-mode="left"] .bs-handle>*,.bs-sheet[data-mode="right"] .bs-handle>*{display:none}.bs-sheet[data-mode="left"] .bs-handle{right:0;border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="right"] .bs-handle{left:0;border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="left"] .bs-handle::before,.bs-sheet[data-mode="right"] .bs-handle::before{width:var(--bs-handle-height);height:var(--bs-handle-width);margin:0}.bs-sheet:hover .bs-handle::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 15%)}.bs-handle:active::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 35%);transform:scaleX(1.15)}.bs-handle.bs-handle--ticks::after{content:"";display:block;position:absolute;left:50%;bottom:6px;transform:translateX(-50%);width:calc(var(--bs-handle-width) * 2);height:3px;background-image:radial-gradient( circle,var(--bs-handle-color,var(--bs-handle-color-d)) 0 1.5px,transparent 1.6px );background-size:8px 3px;background-repeat:repeat-x;background-position:center;opacity:0;transition:opacity 0.18s ease-out;pointer-events:none}.bs-root[data-dragging="true"] .bs-handle.bs-handle--ticks::after{opacity:0.4}.bs-sheet[data-mode="top"] .bs-handle.bs-handle--ticks::after{bottom:auto;top:6px}.bs-sheet[data-mode="left"] .bs-handle.bs-handle--ticks::after,.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{left:50%;top:50%;bottom:auto;transform:translate(-50%,-50%);width:3px;height:calc(var(--bs-handle-width) * 2);background-size:3px 8px;background-repeat:repeat-y;margin-left:calc(var(--bs-handle-height) + 6px)}.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{margin-left:calc(-1 * (var(--bs-handle-height) + 6px))}.bs-header{flex:0 0 auto;min-height:var(--bs-header-min-height,0px);padding:var(--bs-header-padding,0 16px 8px);background:var(--bs-surface,var(--bs-surface-d))}.bs-content{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;user-select:text;padding:var(--bs-content-padding,0 16px 16px)}.bs-sheet[data-bs-fit-content] .bs-content{scroll-padding-bottom:var(--bs-content-inset,0px)}.bs-sheet[data-bs-fit-content] .bs-content::after{content:"";display:block;flex:none;height:var(--bs-content-inset,0px)}.bs-footer{flex:0 0 auto;padding:var(--bs-footer-padding,12px 16px calc(12px + env(safe-area-inset-bottom)));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));background:var(--bs-surface,var(--bs-surface-d))}.bs-sheet[data-mode="bottom"]:has(.bs-footer:not([hidden]):has(*)){padding-bottom:0}.bs-header:not(:has(*)),.bs-footer:not(:has(*)),.bs-header[hidden],.bs-footer[hidden]{display:none}.bs-screen{position:absolute;inset:0;pointer-events:none;z-index:var(--bs-z-scrim);background:var(--bs-scrim-color,var(--bs-scrim-color-d));backdrop-filter:blur(var(--bs-scrim-blur,0px));-webkit-backdrop-filter:blur(var(--bs-scrim-blur,0px));transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-screen,.bs-root[data-animating="true"] .bs-screen{transition:none}.bs-scrim-overlay{z-index:calc(var(--bs-z-sheet) + 1);pointer-events:none}.bs-button-slot{position:fixed;z-index:calc(var(--bs-z-sheet) + 1);pointer-events:auto}.bs-button-slot[data-side="left"]{left:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-side="right"]{right:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="top"]{bottom:auto;top:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="left"]{left:calc(var(--bs-size,0px) + 12px);right:auto;bottom:auto;top:16px}.bs-button-slot[data-mode="right"]{right:calc(var(--bs-size,0px) + 12px);left:auto;bottom:auto;top:16px}@media (prefers-reduced-motion:reduce){.bs-backdrop,.bs-handle::before,.bs-button-slot[data-side="left"],.bs-button-slot[data-side="right"]{transition:none !important}}@media (prefers-color-scheme:dark){:where(.bs-root){--bs-surface-d:#1a1a1d;--bs-surface-border-d:rgba(255,255,255,0.08);--bs-handle-color-d:rgba(255,255,255,0.45);--bs-shadow-auto:0 -3px 16px rgba(0,0,0,0.5)}}@media (forced-colors:active){.bs-sheet{border:1px solid CanvasText}.bs-handle::before{background:CanvasText;forced-color-adjust:none}.bs-backdrop,.bs-screen{forced-color-adjust:none}}.bs-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:where(.ovl-root){--ovl-surface:var(--bs-surface,var(--bs-surface-d,#ffffff));--ovl-surface-border:var(--bs-surface-border,var(--bs-surface-border-d,rgba(0,0,0,0.08)));--ovl-shadow:0 -8px 40px rgba(0,0,0,0.35);--ovl-radius:var(--bs-radius,var(--bs-radius-d,20px));--ovl-backdrop-color:rgba(0,0,0,0.5);--ovl-z-backdrop:200;--ovl-z-panel:201}.ovl-backdrop{position:fixed;inset:0;background:var(--ovl-backdrop-color);opacity:0;pointer-events:none;z-index:var(--ovl-z-backdrop)}.ovl-panel{position:fixed;background:var(--ovl-surface);box-shadow:var(--ovl-shadow);z-index:var(--ovl-z-panel);-webkit-tap-highlight-color:transparent;outline:none;transition:transform 0.32s cubic-bezier(0.29,1.24,0.84,0.99),opacity 0.32s ease-out}.ovl-panel[data-state="open"]{transform:translate3d(0,0,0);opacity:1}@starting-style{.ovl-panel[data-edge="bottom"][data-state="open"]{transform:translate3d(0,100%,0);opacity:0}.ovl-panel[data-edge="top"][data-state="open"]{transform:translate3d(0,-100%,0);opacity:0}.ovl-panel[data-edge="left"][data-state="open"]{transform:translate3d(-100%,0,0);opacity:0}.ovl-panel[data-edge="right"][data-state="open"]{transform:translate3d(100%,0,0);opacity:0}}.ovl-panel[data-edge="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--ovl-radius);border-top-right-radius:var(--ovl-radius);border-top:1px solid var(--ovl-surface-border);padding-bottom:env(safe-area-inset-bottom)}.ovl-panel[data-edge="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-bottom:1px solid var(--ovl-surface-border);padding-top:env(safe-area-inset-top)}.ovl-panel[data-edge="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-right:1px solid var(--ovl-surface-border)}.ovl-panel[data-edge="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--ovl-radius);border-bottom-left-radius:var(--ovl-radius);border-left:1px solid var(--ovl-surface-border)}@media (prefers-reduced-motion:reduce){.ovl-panel,.ovl-backdrop{transition:none !important}}`;
4690
+ baseStyles = `:where(.bs-root){--bs-surface-d:#ffffff;--bs-surface-border-d:rgba(225,227,237,1);--bs-radius-d:20px;--bs-handle-color-d:rgba(26,22,20,0.3);--bs-handle-width:40px;--bs-handle-height:5px;--bs-z-backdrop:90;--bs-z-sheet:100;--bs-backdrop-color-d:rgba(0,0,0,0.5);--bs-scrim-color-d:transparent;--bs-scrim-blur:0px;--bs-z-scrim:calc(var(--bs-z-sheet) - 1);--bs-size:0px;--bs-progress:0}.bs-backdrop{position:fixed;inset:0;background:var(--bs-backdrop-color,var(--bs-backdrop-color-d));opacity:0;pointer-events:none;z-index:var(--bs-z-backdrop);transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-backdrop,.bs-root[data-animating="true"] .bs-backdrop{transition:none}.bs-sheet{position:fixed;background:var(--bs-surface,var(--bs-surface-d));box-shadow:var(--bs-shadow,var(--bs-shadow-auto,none));--bs-shadow-fade:clamp(0,calc(var(--bs-progress,0) * 8),1);z-index:var(--bs-z-sheet);pointer-events:auto;overflow:hidden;display:flex;flex-direction:column;-webkit-tap-highlight-color:transparent;user-select:none;overscroll-behavior:contain}.bs-sheet[data-mode="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));padding-bottom:env(safe-area-inset-bottom);--bs-shadow-auto:0 calc(var(--bs-progress,0) * -2px - 3px) calc(var(--bs-progress,0) * 18px + 12px) rgba( 0,0,0,calc(var(--bs-shadow-fade) * (var(--bs-progress,0) * 0.15 + 0.12)) )}.bs-sheet[data-mode="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom:1px solid var(--bs-surface-border,var(--bs-surface-border-d));flex-direction:column-reverse;--bs-shadow-auto:0 3px 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12));padding-top:env(safe-area-inset-top)}.bs-sheet[data-mode="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:3px 0 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12))}.bs-sheet[data-mode="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:-3px 0 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12))}.bs-sheet[data-bs-rest="closed"]{box-shadow:none;visibility:hidden}.bs-sheet[data-bs-webgl="on"],.bs-sheet[data-bs-webgl="on"] .bs-handle,.bs-sheet[data-bs-webgl="on"] .bs-header,.bs-sheet[data-bs-webgl="on"] .bs-footer{background:transparent;box-shadow:none}.bs-sheet[data-mode="left"] .bs-content{padding-right:36px}.bs-sheet[data-mode="right"] .bs-content{padding-left:36px}.bs-handle{flex-shrink:0;min-height:44px;display:flex;flex-direction:column;justify-content:center;padding:var(--bs-handle-padding,8px 16px 4px);cursor:grab;touch-action:none;user-select:none;background:var(--bs-surface,var(--bs-surface-d));-webkit-tap-highlight-color:transparent;outline:none;position:relative}.bs-handle:active{cursor:grabbing}.bs-handle:focus-visible{outline:2px solid currentColor;outline-offset:-2px;border-radius:var(--bs-radius,var(--bs-radius-d))}.bs-handle::before{content:"";display:block;width:var(--bs-handle-width);height:var(--bs-handle-height);background:var(--bs-handle-color,var(--bs-handle-color-d));border-radius:calc(var(--bs-handle-height) / 2);margin:0 auto 8px;transition:width 0.15s ease,background 0.15s ease,transform 0.15s ease;pointer-events:none}.bs-sheet[data-mode="left"] .bs-handle,.bs-sheet[data-mode="right"] .bs-handle{position:absolute;top:0;bottom:0;width:28px;min-width:0;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0;background:var(--bs-surface,var(--bs-surface-d));z-index:1;overflow:hidden}.bs-sheet[data-mode="left"] .bs-handle>*,.bs-sheet[data-mode="right"] .bs-handle>*{display:none}.bs-sheet[data-mode="left"] .bs-handle{right:0;border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="right"] .bs-handle{left:0;border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="left"] .bs-handle::before,.bs-sheet[data-mode="right"] .bs-handle::before{width:var(--bs-handle-height);height:var(--bs-handle-width);margin:0}.bs-sheet:hover .bs-handle::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 15%)}.bs-handle:active::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 35%);transform:scaleX(1.15)}.bs-handle.bs-handle--ticks::after{content:"";display:block;position:absolute;left:50%;bottom:6px;transform:translateX(-50%);width:calc(var(--bs-handle-width) * 2);height:3px;background-image:radial-gradient( circle,var(--bs-handle-color,var(--bs-handle-color-d)) 0 1.5px,transparent 1.6px );background-size:8px 3px;background-repeat:repeat-x;background-position:center;opacity:0;transition:opacity 0.18s ease-out;pointer-events:none}.bs-root[data-dragging="true"] .bs-handle.bs-handle--ticks::after{opacity:0.4}.bs-sheet[data-mode="top"] .bs-handle.bs-handle--ticks::after{bottom:auto;top:6px}.bs-sheet[data-mode="left"] .bs-handle.bs-handle--ticks::after,.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{left:50%;top:50%;bottom:auto;transform:translate(-50%,-50%);width:3px;height:calc(var(--bs-handle-width) * 2);background-size:3px 8px;background-repeat:repeat-y;margin-left:calc(var(--bs-handle-height) + 6px)}.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{margin-left:calc(-1 * (var(--bs-handle-height) + 6px))}.bs-header{flex:0 0 auto;min-height:var(--bs-header-min-height,0px);padding:var(--bs-header-padding,0 16px 8px);background:var(--bs-surface,var(--bs-surface-d))}.bs-content{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;user-select:text;padding:var(--bs-content-padding,0 16px 16px)}.bs-sheet[data-bs-fit-content="moving"] .bs-content,.bs-sheet[data-bs-fit-content][data-bs-webgl="on"] .bs-content{scroll-padding-bottom:var(--bs-content-inset,0px)}.bs-sheet[data-bs-fit-content="moving"] .bs-content::after,.bs-sheet[data-bs-fit-content][data-bs-webgl="on"] .bs-content::after{content:"";display:block;flex:none;height:var(--bs-content-inset,0px)}.bs-sheet[data-bs-fit-content="rest"][data-mode="bottom"]:not([data-bs-webgl="on"])::after{content:"";flex:0 1 max(0px,var(--bs-max-size,0px) - var(--bs-size,0px))}.bs-footer{flex:0 0 auto;padding:var(--bs-footer-padding,12px 16px calc(12px + env(safe-area-inset-bottom)));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));background:var(--bs-surface,var(--bs-surface-d))}.bs-sheet[data-bs-fit-content="moving"][data-mode="bottom"]:not([data-bs-webgl="on"]) .bs-footer{transform:translateY( clamp( calc(-1 * var(--bs-footer-lift-max,0px)),calc(var(--bs-size,0px) - var(--bs-max-size,0px)),0px ) )}.bs-sheet[data-mode="bottom"]:has(.bs-footer:not([hidden]):has(*)){padding-bottom:0}.bs-header:not(:has(*)),.bs-footer:not(:has(*)),.bs-header[hidden],.bs-footer[hidden]{display:none}.bs-screen{position:absolute;inset:0;pointer-events:none;z-index:var(--bs-z-scrim);background:var(--bs-scrim-color,var(--bs-scrim-color-d));backdrop-filter:blur(var(--bs-scrim-blur,0px));-webkit-backdrop-filter:blur(var(--bs-scrim-blur,0px));transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-screen,.bs-root[data-animating="true"] .bs-screen{transition:none}.bs-scrim-overlay{z-index:calc(var(--bs-z-sheet) + 1);pointer-events:none}.bs-button-slot{position:fixed;z-index:calc(var(--bs-z-sheet) + 1);pointer-events:auto}.bs-button-slot[data-side="left"]{left:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-side="right"]{right:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="top"]{bottom:auto;top:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="left"]{left:calc(var(--bs-size,0px) + 12px);right:auto;bottom:auto;top:16px}.bs-button-slot[data-mode="right"]{right:calc(var(--bs-size,0px) + 12px);left:auto;bottom:auto;top:16px}@media (prefers-reduced-motion:reduce){.bs-backdrop,.bs-handle::before,.bs-button-slot[data-side="left"],.bs-button-slot[data-side="right"]{transition:none !important}}@media (prefers-color-scheme:dark){:where(.bs-root){--bs-surface-d:#1a1a1d;--bs-surface-border-d:rgba(255,255,255,0.08);--bs-handle-color-d:rgba(255,255,255,0.45);--bs-shadow-auto:0 -3px 16px rgba(0,0,0,0.5)}}@media (forced-colors:active){.bs-sheet{border:1px solid CanvasText}.bs-handle::before{background:CanvasText;forced-color-adjust:none}.bs-backdrop,.bs-screen{forced-color-adjust:none}}.bs-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:where(.ovl-root){--ovl-surface:var(--bs-surface,var(--bs-surface-d,#ffffff));--ovl-surface-border:var(--bs-surface-border,var(--bs-surface-border-d,rgba(0,0,0,0.08)));--ovl-shadow:0 -8px 40px rgba(0,0,0,0.35);--ovl-radius:var(--bs-radius,var(--bs-radius-d,20px));--ovl-backdrop-color:rgba(0,0,0,0.5);--ovl-z-backdrop:200;--ovl-z-panel:201}.ovl-backdrop{position:fixed;inset:0;background:var(--ovl-backdrop-color);opacity:0;pointer-events:none;z-index:var(--ovl-z-backdrop)}.ovl-panel{position:fixed;background:var(--ovl-surface);box-shadow:var(--ovl-shadow);z-index:var(--ovl-z-panel);-webkit-tap-highlight-color:transparent;outline:none;transition:transform 0.32s cubic-bezier(0.29,1.24,0.84,0.99),opacity 0.32s ease-out}.ovl-panel[data-state="open"]{transform:translate3d(0,0,0);opacity:1}@starting-style{.ovl-panel[data-edge="bottom"][data-state="open"]{transform:translate3d(0,100%,0);opacity:0}.ovl-panel[data-edge="top"][data-state="open"]{transform:translate3d(0,-100%,0);opacity:0}.ovl-panel[data-edge="left"][data-state="open"]{transform:translate3d(-100%,0,0);opacity:0}.ovl-panel[data-edge="right"][data-state="open"]{transform:translate3d(100%,0,0);opacity:0}}.ovl-panel[data-edge="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--ovl-radius);border-top-right-radius:var(--ovl-radius);border-top:1px solid var(--ovl-surface-border);padding-bottom:env(safe-area-inset-bottom)}.ovl-panel[data-edge="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-bottom:1px solid var(--ovl-surface-border);padding-top:env(safe-area-inset-top)}.ovl-panel[data-edge="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-right:1px solid var(--ovl-surface-border)}.ovl-panel[data-edge="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--ovl-radius);border-bottom-left-radius:var(--ovl-radius);border-left:1px solid var(--ovl-surface-border)}@media (prefers-reduced-motion:reduce){.ovl-panel,.ovl-backdrop{transition:none !important}}`;
4661
4691
  }
4662
4692
  });
4663
4693
 
package/dist/features.cjs CHANGED
@@ -470,6 +470,9 @@ function visualViewportFeature() {
470
470
 
471
471
  // src/core/features/content-fit.ts
472
472
  var INSET_VAR = "--bs-content-inset";
473
+ var SIZE_VAR = "--bs-size";
474
+ var CAP_VAR = "--bs-max-size";
475
+ var LIFT_VAR = "--bs-footer-lift-max";
473
476
  var FIT_ATTR = "data-bs-fit-content";
474
477
  function contentFitFeature() {
475
478
  return {
@@ -483,6 +486,8 @@ function contentFitFeature() {
483
486
  let inset = 0;
484
487
  let unpaddedMax = -1;
485
488
  let top = 0;
489
+ let resting = false;
490
+ const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
486
491
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
487
492
  const follow = (size) => {
488
493
  if (unpaddedMax < 0) {
@@ -498,21 +503,36 @@ function contentFitFeature() {
498
503
  const settle = () => {
499
504
  if (ctx.isDestroyed()) return;
500
505
  const size = ctx.getSize();
501
- unpaddedMax = -1;
502
- follow(size);
506
+ if (!resting) {
507
+ unpaddedMax = -1;
508
+ follow(size);
509
+ }
503
510
  inset = hiddenAt(size);
504
- sheet.style.setProperty(INSET_VAR, `${inset}px`);
511
+ put(INSET_VAR, inset);
512
+ put(SIZE_VAR, size);
513
+ put(CAP_VAR, ctx.getMaxAxisSize());
514
+ if (!resting) {
515
+ resting = true;
516
+ sheet.setAttribute(FIT_ATTR, "rest");
517
+ }
505
518
  unpaddedMax = -1;
506
519
  };
520
+ const move = (size) => {
521
+ if (resting) {
522
+ resting = false;
523
+ sheet.setAttribute(FIT_ATTR, "moving");
524
+ put(LIFT_VAR, scroller.offsetHeight);
525
+ }
526
+ follow(size);
527
+ };
507
528
  const moving = () => ctx.isAnimating() || ctx.isDragging();
508
529
  const whenIdle = () => {
509
530
  if (!moving()) settle();
510
531
  };
511
- sheet.setAttribute(FIT_ATTR, "");
512
532
  settle();
513
533
  const offProgress = ctx.on(
514
534
  "progress",
515
- (p) => moving() ? follow(p.size) : settle()
535
+ (p) => moving() ? move(p.size) : settle()
516
536
  );
517
537
  const offSnap = ctx.on("snap", settle);
518
538
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
@@ -524,7 +544,9 @@ function contentFitFeature() {
524
544
  observer?.disconnect();
525
545
  window.removeEventListener("orientationchange", whenIdle);
526
546
  sheet.removeAttribute(FIT_ATTR);
527
- sheet.style.removeProperty(INSET_VAR);
547
+ for (const name of [INSET_VAR, CAP_VAR, LIFT_VAR]) {
548
+ sheet.style.removeProperty(name);
549
+ }
528
550
  };
529
551
  }
530
552
  };
package/dist/features.js CHANGED
@@ -468,6 +468,9 @@ function visualViewportFeature() {
468
468
 
469
469
  // src/core/features/content-fit.ts
470
470
  var INSET_VAR = "--bs-content-inset";
471
+ var SIZE_VAR = "--bs-size";
472
+ var CAP_VAR = "--bs-max-size";
473
+ var LIFT_VAR = "--bs-footer-lift-max";
471
474
  var FIT_ATTR = "data-bs-fit-content";
472
475
  function contentFitFeature() {
473
476
  return {
@@ -481,6 +484,8 @@ function contentFitFeature() {
481
484
  let inset = 0;
482
485
  let unpaddedMax = -1;
483
486
  let top = 0;
487
+ let resting = false;
488
+ const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
484
489
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
485
490
  const follow = (size) => {
486
491
  if (unpaddedMax < 0) {
@@ -496,21 +501,36 @@ function contentFitFeature() {
496
501
  const settle = () => {
497
502
  if (ctx.isDestroyed()) return;
498
503
  const size = ctx.getSize();
499
- unpaddedMax = -1;
500
- follow(size);
504
+ if (!resting) {
505
+ unpaddedMax = -1;
506
+ follow(size);
507
+ }
501
508
  inset = hiddenAt(size);
502
- sheet.style.setProperty(INSET_VAR, `${inset}px`);
509
+ put(INSET_VAR, inset);
510
+ put(SIZE_VAR, size);
511
+ put(CAP_VAR, ctx.getMaxAxisSize());
512
+ if (!resting) {
513
+ resting = true;
514
+ sheet.setAttribute(FIT_ATTR, "rest");
515
+ }
503
516
  unpaddedMax = -1;
504
517
  };
518
+ const move = (size) => {
519
+ if (resting) {
520
+ resting = false;
521
+ sheet.setAttribute(FIT_ATTR, "moving");
522
+ put(LIFT_VAR, scroller.offsetHeight);
523
+ }
524
+ follow(size);
525
+ };
505
526
  const moving = () => ctx.isAnimating() || ctx.isDragging();
506
527
  const whenIdle = () => {
507
528
  if (!moving()) settle();
508
529
  };
509
- sheet.setAttribute(FIT_ATTR, "");
510
530
  settle();
511
531
  const offProgress = ctx.on(
512
532
  "progress",
513
- (p) => moving() ? follow(p.size) : settle()
533
+ (p) => moving() ? move(p.size) : settle()
514
534
  );
515
535
  const offSnap = ctx.on("snap", settle);
516
536
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
@@ -522,7 +542,9 @@ function contentFitFeature() {
522
542
  observer?.disconnect();
523
543
  window.removeEventListener("orientationchange", whenIdle);
524
544
  sheet.removeAttribute(FIT_ATTR);
525
- sheet.style.removeProperty(INSET_VAR);
545
+ for (const name of [INSET_VAR, CAP_VAR, LIFT_VAR]) {
546
+ sheet.style.removeProperty(name);
547
+ }
526
548
  };
527
549
  }
528
550
  };
package/dist/index.cjs CHANGED
@@ -1487,13 +1487,17 @@ var AnimationRunner = class {
1487
1487
  });
1488
1488
  let stopped = false;
1489
1489
  let auxRaf = 0;
1490
- const start = performance.now();
1491
1490
  const lastIdx = samples.values.length - 1;
1492
1491
  const auxTick = () => {
1493
1492
  if (stopped) return;
1494
- const elapsed = performance.now() - start;
1495
- const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
1496
- applyAux(samples.values[idx]);
1493
+ const at = Math.min(
1494
+ (Number(anim.currentTime) || 0) / samples.stepMs,
1495
+ lastIdx
1496
+ );
1497
+ const idx = Math.floor(at);
1498
+ const from = samples.values[idx];
1499
+ const to = samples.values[Math.min(idx + 1, lastIdx)];
1500
+ applyAux(from + (to - from) * (at - idx));
1497
1501
  auxRaf = requestAnimationFrame(auxTick);
1498
1502
  };
1499
1503
  auxRaf = requestAnimationFrame(auxTick);
@@ -2705,7 +2709,11 @@ var BottomSheetCore = class {
2705
2709
  getSize: () => this.size,
2706
2710
  isDragging: () => this.isDraggingAny(),
2707
2711
  applyAux: (size) => this.applySize(size, true),
2708
- getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2712
+ getTransformFor: (size) => {
2713
+ const cap = this.snaps.getMaxAxisSize();
2714
+ const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2715
+ return this.transformTemplate(cap - shown);
2716
+ }
2709
2717
  },
2710
2718
  resolved.animation
2711
2719
  );
@@ -4237,6 +4245,9 @@ function visualViewportFeature() {
4237
4245
 
4238
4246
  // src/core/features/content-fit.ts
4239
4247
  var INSET_VAR = "--bs-content-inset";
4248
+ var SIZE_VAR = "--bs-size";
4249
+ var CAP_VAR = "--bs-max-size";
4250
+ var LIFT_VAR = "--bs-footer-lift-max";
4240
4251
  var FIT_ATTR = "data-bs-fit-content";
4241
4252
  function contentFitFeature() {
4242
4253
  return {
@@ -4250,6 +4261,8 @@ function contentFitFeature() {
4250
4261
  let inset = 0;
4251
4262
  let unpaddedMax = -1;
4252
4263
  let top = 0;
4264
+ let resting = false;
4265
+ const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4253
4266
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4254
4267
  const follow = (size) => {
4255
4268
  if (unpaddedMax < 0) {
@@ -4265,21 +4278,36 @@ function contentFitFeature() {
4265
4278
  const settle = () => {
4266
4279
  if (ctx.isDestroyed()) return;
4267
4280
  const size = ctx.getSize();
4268
- unpaddedMax = -1;
4269
- follow(size);
4281
+ if (!resting) {
4282
+ unpaddedMax = -1;
4283
+ follow(size);
4284
+ }
4270
4285
  inset = hiddenAt(size);
4271
- sheet.style.setProperty(INSET_VAR, `${inset}px`);
4286
+ put(INSET_VAR, inset);
4287
+ put(SIZE_VAR, size);
4288
+ put(CAP_VAR, ctx.getMaxAxisSize());
4289
+ if (!resting) {
4290
+ resting = true;
4291
+ sheet.setAttribute(FIT_ATTR, "rest");
4292
+ }
4272
4293
  unpaddedMax = -1;
4273
4294
  };
4295
+ const move = (size) => {
4296
+ if (resting) {
4297
+ resting = false;
4298
+ sheet.setAttribute(FIT_ATTR, "moving");
4299
+ put(LIFT_VAR, scroller.offsetHeight);
4300
+ }
4301
+ follow(size);
4302
+ };
4274
4303
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4275
4304
  const whenIdle = () => {
4276
4305
  if (!moving()) settle();
4277
4306
  };
4278
- sheet.setAttribute(FIT_ATTR, "");
4279
4307
  settle();
4280
4308
  const offProgress = ctx.on(
4281
4309
  "progress",
4282
- (p) => moving() ? follow(p.size) : settle()
4310
+ (p) => moving() ? move(p.size) : settle()
4283
4311
  );
4284
4312
  const offSnap = ctx.on("snap", settle);
4285
4313
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
@@ -4291,7 +4319,9 @@ function contentFitFeature() {
4291
4319
  observer?.disconnect();
4292
4320
  window.removeEventListener("orientationchange", whenIdle);
4293
4321
  sheet.removeAttribute(FIT_ATTR);
4294
- sheet.style.removeProperty(INSET_VAR);
4322
+ for (const name of [INSET_VAR, CAP_VAR, LIFT_VAR]) {
4323
+ sheet.style.removeProperty(name);
4324
+ }
4295
4325
  };
4296
4326
  }
4297
4327
  };
package/dist/index.js CHANGED
@@ -1485,13 +1485,17 @@ var AnimationRunner = class {
1485
1485
  });
1486
1486
  let stopped = false;
1487
1487
  let auxRaf = 0;
1488
- const start = performance.now();
1489
1488
  const lastIdx = samples.values.length - 1;
1490
1489
  const auxTick = () => {
1491
1490
  if (stopped) return;
1492
- const elapsed = performance.now() - start;
1493
- const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
1494
- applyAux(samples.values[idx]);
1491
+ const at = Math.min(
1492
+ (Number(anim.currentTime) || 0) / samples.stepMs,
1493
+ lastIdx
1494
+ );
1495
+ const idx = Math.floor(at);
1496
+ const from = samples.values[idx];
1497
+ const to = samples.values[Math.min(idx + 1, lastIdx)];
1498
+ applyAux(from + (to - from) * (at - idx));
1495
1499
  auxRaf = requestAnimationFrame(auxTick);
1496
1500
  };
1497
1501
  auxRaf = requestAnimationFrame(auxTick);
@@ -2703,7 +2707,11 @@ var BottomSheetCore = class {
2703
2707
  getSize: () => this.size,
2704
2708
  isDragging: () => this.isDraggingAny(),
2705
2709
  applyAux: (size) => this.applySize(size, true),
2706
- getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2710
+ getTransformFor: (size) => {
2711
+ const cap = this.snaps.getMaxAxisSize();
2712
+ const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2713
+ return this.transformTemplate(cap - shown);
2714
+ }
2707
2715
  },
2708
2716
  resolved.animation
2709
2717
  );
@@ -4235,6 +4243,9 @@ function visualViewportFeature() {
4235
4243
 
4236
4244
  // src/core/features/content-fit.ts
4237
4245
  var INSET_VAR = "--bs-content-inset";
4246
+ var SIZE_VAR = "--bs-size";
4247
+ var CAP_VAR = "--bs-max-size";
4248
+ var LIFT_VAR = "--bs-footer-lift-max";
4238
4249
  var FIT_ATTR = "data-bs-fit-content";
4239
4250
  function contentFitFeature() {
4240
4251
  return {
@@ -4248,6 +4259,8 @@ function contentFitFeature() {
4248
4259
  let inset = 0;
4249
4260
  let unpaddedMax = -1;
4250
4261
  let top = 0;
4262
+ let resting = false;
4263
+ const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4251
4264
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4252
4265
  const follow = (size) => {
4253
4266
  if (unpaddedMax < 0) {
@@ -4263,21 +4276,36 @@ function contentFitFeature() {
4263
4276
  const settle = () => {
4264
4277
  if (ctx.isDestroyed()) return;
4265
4278
  const size = ctx.getSize();
4266
- unpaddedMax = -1;
4267
- follow(size);
4279
+ if (!resting) {
4280
+ unpaddedMax = -1;
4281
+ follow(size);
4282
+ }
4268
4283
  inset = hiddenAt(size);
4269
- sheet.style.setProperty(INSET_VAR, `${inset}px`);
4284
+ put(INSET_VAR, inset);
4285
+ put(SIZE_VAR, size);
4286
+ put(CAP_VAR, ctx.getMaxAxisSize());
4287
+ if (!resting) {
4288
+ resting = true;
4289
+ sheet.setAttribute(FIT_ATTR, "rest");
4290
+ }
4270
4291
  unpaddedMax = -1;
4271
4292
  };
4293
+ const move = (size) => {
4294
+ if (resting) {
4295
+ resting = false;
4296
+ sheet.setAttribute(FIT_ATTR, "moving");
4297
+ put(LIFT_VAR, scroller.offsetHeight);
4298
+ }
4299
+ follow(size);
4300
+ };
4272
4301
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4273
4302
  const whenIdle = () => {
4274
4303
  if (!moving()) settle();
4275
4304
  };
4276
- sheet.setAttribute(FIT_ATTR, "");
4277
4305
  settle();
4278
4306
  const offProgress = ctx.on(
4279
4307
  "progress",
4280
- (p) => moving() ? follow(p.size) : settle()
4308
+ (p) => moving() ? move(p.size) : settle()
4281
4309
  );
4282
4310
  const offSnap = ctx.on("snap", settle);
4283
4311
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
@@ -4289,7 +4317,9 @@ function contentFitFeature() {
4289
4317
  observer?.disconnect();
4290
4318
  window.removeEventListener("orientationchange", whenIdle);
4291
4319
  sheet.removeAttribute(FIT_ATTR);
4292
- sheet.style.removeProperty(INSET_VAR);
4320
+ for (const name of [INSET_VAR, CAP_VAR, LIFT_VAR]) {
4321
+ sheet.style.removeProperty(name);
4322
+ }
4293
4323
  };
4294
4324
  }
4295
4325
  };
@@ -1504,13 +1504,14 @@ class AnimationRunner {
1504
1504
  });
1505
1505
  let stopped = false;
1506
1506
  let auxRaf = 0;
1507
- const start = performance.now();
1508
1507
  const lastIdx = samples.values.length - 1;
1509
1508
  const auxTick = () => {
1510
1509
  if (stopped) return;
1511
- const elapsed = performance.now() - start;
1512
- const idx = Math.min(Math.floor(elapsed / samples.stepMs), lastIdx);
1513
- applyAux(samples.values[idx]);
1510
+ const at = Math.min((Number(anim.currentTime) || 0) / samples.stepMs, lastIdx);
1511
+ const idx = Math.floor(at);
1512
+ const from = samples.values[idx];
1513
+ const to = samples.values[Math.min(idx + 1, lastIdx)];
1514
+ applyAux(from + (to - from) * (at - idx));
1514
1515
  auxRaf = requestAnimationFrame(auxTick);
1515
1516
  };
1516
1517
  auxRaf = requestAnimationFrame(auxTick);
@@ -2749,7 +2750,11 @@ class BottomSheetCore {
2749
2750
  getSize: () => this.size,
2750
2751
  isDragging: () => this.isDraggingAny(),
2751
2752
  applyAux: (size) => this.applySize(size, true),
2752
- getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2753
+ getTransformFor: (size) => {
2754
+ const cap = this.snaps.getMaxAxisSize();
2755
+ const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2756
+ return this.transformTemplate(cap - shown);
2757
+ }
2753
2758
  }, resolved.animation);
2754
2759
  this.lifecycle = new LifecycleController({
2755
2760
  element: this.element,
@@ -4228,6 +4233,9 @@ function visualViewportFeature() {
4228
4233
  };
4229
4234
  }
4230
4235
  const INSET_VAR = "--bs-content-inset";
4236
+ const SIZE_VAR = "--bs-size";
4237
+ const CAP_VAR = "--bs-max-size";
4238
+ const LIFT_VAR = "--bs-footer-lift-max";
4231
4239
  const FIT_ATTR = "data-bs-fit-content";
4232
4240
  function contentFitFeature() {
4233
4241
  return {
@@ -4241,6 +4249,8 @@ function contentFitFeature() {
4241
4249
  let inset = 0;
4242
4250
  let unpaddedMax = -1;
4243
4251
  let top = 0;
4252
+ let resting = false;
4253
+ const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4244
4254
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4245
4255
  const follow = (size) => {
4246
4256
  if (unpaddedMax < 0) {
@@ -4256,19 +4266,34 @@ function contentFitFeature() {
4256
4266
  const settle = () => {
4257
4267
  if (ctx.isDestroyed()) return;
4258
4268
  const size = ctx.getSize();
4259
- unpaddedMax = -1;
4260
- follow(size);
4269
+ if (!resting) {
4270
+ unpaddedMax = -1;
4271
+ follow(size);
4272
+ }
4261
4273
  inset = hiddenAt(size);
4262
- sheet.style.setProperty(INSET_VAR, `${inset}px`);
4274
+ put(INSET_VAR, inset);
4275
+ put(SIZE_VAR, size);
4276
+ put(CAP_VAR, ctx.getMaxAxisSize());
4277
+ if (!resting) {
4278
+ resting = true;
4279
+ sheet.setAttribute(FIT_ATTR, "rest");
4280
+ }
4263
4281
  unpaddedMax = -1;
4264
4282
  };
4283
+ const move = (size) => {
4284
+ if (resting) {
4285
+ resting = false;
4286
+ sheet.setAttribute(FIT_ATTR, "moving");
4287
+ put(LIFT_VAR, scroller.offsetHeight);
4288
+ }
4289
+ follow(size);
4290
+ };
4265
4291
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4266
4292
  const whenIdle = () => {
4267
4293
  if (!moving()) settle();
4268
4294
  };
4269
- sheet.setAttribute(FIT_ATTR, "");
4270
4295
  settle();
4271
- const offProgress = ctx.on("progress", (p) => moving() ? follow(p.size) : settle());
4296
+ const offProgress = ctx.on("progress", (p) => moving() ? move(p.size) : settle());
4272
4297
  const offSnap = ctx.on("snap", settle);
4273
4298
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4274
4299
  observer?.observe(document.documentElement);
@@ -4279,7 +4304,13 @@ function contentFitFeature() {
4279
4304
  observer?.disconnect();
4280
4305
  window.removeEventListener("orientationchange", whenIdle);
4281
4306
  sheet.removeAttribute(FIT_ATTR);
4282
- sheet.style.removeProperty(INSET_VAR);
4307
+ for (const name of [
4308
+ INSET_VAR,
4309
+ CAP_VAR,
4310
+ LIFT_VAR
4311
+ ]) {
4312
+ sheet.style.removeProperty(name);
4313
+ }
4283
4314
  };
4284
4315
  }
4285
4316
  };