@surdeddd/bottom-sheet 0.23.2 → 0.23.3

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 (57) hide show
  1. package/dist/{BottomSheetCore-9i-Uh6T3.d.ts → BottomSheetCore-COvILxmR.d.ts} +2 -0
  2. package/dist/{BottomSheetCore-CQStdVy2.d.cts → BottomSheetCore-CaJwHnxY.d.cts} +2 -0
  3. package/dist/{BottomSheetEngine-CsQWHLNb.d.cts → BottomSheetEngine-C_1aPJsU.d.cts} +1 -1
  4. package/dist/{BottomSheetEngine-Dn6h-7gF.d.ts → BottomSheetEngine-CsgCcCSO.d.ts} +1 -1
  5. package/dist/core.cjs +43 -13
  6. package/dist/core.d.cts +2 -2
  7. package/dist/core.d.ts +2 -2
  8. package/dist/core.js +43 -13
  9. package/dist/debug.d.cts +1 -1
  10. package/dist/debug.d.ts +1 -1
  11. package/dist/{default-features-C3cilcW9.d.ts → default-features-BJx7J0NH.d.ts} +1 -1
  12. package/dist/{default-features-DkG9aho0.d.cts → default-features-CTJb8Wdk.d.cts} +1 -1
  13. package/dist/element.cjs +100 -19
  14. package/dist/element.d.cts +2 -2
  15. package/dist/element.d.ts +2 -2
  16. package/dist/element.iife.global.js +2 -2
  17. package/dist/element.js +100 -19
  18. package/dist/features.cjs +56 -3
  19. package/dist/features.d.cts +3 -3
  20. package/dist/features.d.ts +3 -3
  21. package/dist/features.js +56 -3
  22. package/dist/{index-CVGC5B5D.d.cts → index-BBrJJjy5.d.cts} +1 -1
  23. package/dist/{index-CnsJQZp2.d.ts → index-CXN7t3rr.d.ts} +1 -1
  24. package/dist/index.cjs +96 -16
  25. package/dist/index.d.cts +5 -5
  26. package/dist/index.d.ts +5 -5
  27. package/dist/index.js +96 -16
  28. package/dist/integrations/formik.d.cts +1 -1
  29. package/dist/integrations/formik.d.ts +1 -1
  30. package/dist/integrations/react-hook-form.d.cts +1 -1
  31. package/dist/integrations/react-hook-form.d.ts +1 -1
  32. package/dist/preact.d.cts +2 -2
  33. package/dist/preact.d.ts +2 -2
  34. package/dist/qwik-lib/index.qwik.cjs +87 -16
  35. package/dist/qwik-lib/index.qwik.mjs +87 -16
  36. package/dist/qwik.cjs +96 -16
  37. package/dist/qwik.d.cts +2 -2
  38. package/dist/qwik.d.ts +2 -2
  39. package/dist/qwik.js +96 -16
  40. package/dist/react.cjs +96 -16
  41. package/dist/react.d.cts +3 -3
  42. package/dist/react.d.ts +3 -3
  43. package/dist/react.js +96 -16
  44. package/dist/solid.cjs +96 -16
  45. package/dist/solid.d.cts +2 -0
  46. package/dist/solid.d.ts +2 -0
  47. package/dist/solid.js +96 -16
  48. package/dist/solid.source.jsx +96 -16
  49. package/dist/svelte-core.cjs +96 -16
  50. package/dist/svelte-core.js +96 -16
  51. package/dist/svelte.cjs +96 -16
  52. package/dist/svelte.js +96 -16
  53. package/dist/vue.cjs +96 -16
  54. package/dist/vue.js +96 -16
  55. package/dist/webgl.d.cts +1 -1
  56. package/dist/webgl.d.ts +1 -1
  57. package/package.json +11 -11
package/dist/preact.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { BottomSheet, BottomSheetFromConfig, BottomSheetFromConfigProps, BottomSheetHandle, BottomSheetProps, HeaderProp, Overlay, OverlayHandle, OverlayProps, SheetConfig, UseBottomSheetRefs, UseBottomSheetReturn, UseOverlayReturn, useBottomSheet, useOverlay } from './react.cjs';
2
- export { d as EngineState, f as SheetMode, h as SnapPoint, e as SnapPointDef } from './BottomSheetCore-CQStdVy2.cjs';
2
+ export { d as EngineState, f as SheetMode, h as SnapPoint, e as SnapPointDef } from './BottomSheetCore-CaJwHnxY.cjs';
3
3
  export { OverlayEdge, OverlayOptions, OverlayState } from './overlay.cjs';
4
4
  import 'react';
5
- import './BottomSheetEngine-CsQWHLNb.cjs';
5
+ import './BottomSheetEngine-C_1aPJsU.cjs';
6
6
  import './teleport-7uYNiEAT.cjs';
7
7
  import './transform-jVfAikE9.cjs';
package/dist/preact.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { BottomSheet, BottomSheetFromConfig, BottomSheetFromConfigProps, BottomSheetHandle, BottomSheetProps, HeaderProp, Overlay, OverlayHandle, OverlayProps, SheetConfig, UseBottomSheetRefs, UseBottomSheetReturn, UseOverlayReturn, useBottomSheet, useOverlay } from './react.js';
2
- export { d as EngineState, f as SheetMode, h as SnapPoint, e as SnapPointDef } from './BottomSheetCore-9i-Uh6T3.js';
2
+ export { d as EngineState, f as SheetMode, h as SnapPoint, e as SnapPointDef } from './BottomSheetCore-COvILxmR.js';
3
3
  export { OverlayEdge, OverlayOptions, OverlayState } from './overlay.js';
4
4
  import 'react';
5
- import './BottomSheetEngine-Dn6h-7gF.js';
5
+ import './BottomSheetEngine-CsgCcCSO.js';
6
6
  import './teleport-7uYNiEAT.js';
7
7
  import './transform-jVfAikE9.js';
@@ -84,6 +84,7 @@ function buildTransformTemplate(axis) {
84
84
  return (offset) => `translate3d(${offset}px, 0, 0)`;
85
85
  }
86
86
  }
87
+ const offsetFromMatrix = (axis, m) => axis === "bottom" ? m.m42 : axis === "top" ? -m.m42 : axis === "left" ? -m.m41 : m.m41;
87
88
  const layoutAxis = (axis) => axis === "left" || axis === "right" ? "width" : "height";
88
89
  const counters = {};
89
90
  function nextInstanceId(prefix) {
@@ -1181,7 +1182,7 @@ const tween = ({ from, to, duration, easing = easeOutCubic, onUpdate }) => {
1181
1182
  }
1182
1183
  const step = (now) => {
1183
1184
  if (cancelled) return;
1184
- const elapsed = now - start;
1185
+ const elapsed = Math.max(0, now - start);
1185
1186
  const t = Math.min(elapsed / duration, 1);
1186
1187
  const value = from + (to - from) * easing(t);
1187
1188
  onUpdate(value);
@@ -1229,8 +1230,8 @@ const runSpring = ({ from, to, velocity = 0, config, onUpdate }) => {
1229
1230
  resolveFn = resolve;
1230
1231
  const step = (now) => {
1231
1232
  if (cancelled) return;
1232
- const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
1233
- lastTime = now;
1233
+ const dt = Math.min(Math.max(0, now - lastTime) / 1e3, MAX_DT);
1234
+ lastTime = Math.max(lastTime, now);
1234
1235
  const steps = Math.max(1, Math.ceil(dt * 240));
1235
1236
  const subDt = dt / steps;
1236
1237
  let stepsLeft = steps;
@@ -1310,6 +1311,7 @@ function resolveAnimationPreset(animation) {
1310
1311
  };
1311
1312
  }
1312
1313
  }
1314
+ const SETTLE_ANIMATION_ID = "bs-settle";
1313
1315
  const SIM_HZ = 240;
1314
1316
  const SAMPLE_STRIDE = 4;
1315
1317
  const MAX_SIM_MS = 3e3;
@@ -1370,6 +1372,7 @@ class AnimationRunner {
1370
1372
  __publicField(this, "isDragging");
1371
1373
  __publicField(this, "applyAux");
1372
1374
  __publicField(this, "getTransformFor");
1375
+ __publicField(this, "readShownSize");
1373
1376
  __publicField(this, "settleWaapi");
1374
1377
  __publicField(this, "currentWaapi", null);
1375
1378
  __publicField(this, "animationKind");
@@ -1389,6 +1392,7 @@ class AnimationRunner {
1389
1392
  this.isDragging = deps.isDragging;
1390
1393
  this.applyAux = deps.applyAux;
1391
1394
  this.getTransformFor = deps.getTransformFor;
1395
+ this.readShownSize = deps.readShownSize;
1392
1396
  this.settleWaapi = opts.settleAnimation === "waapi";
1393
1397
  const preset = resolveAnimationPreset(opts.animation);
1394
1398
  this.animationKind = preset.kind;
@@ -1424,10 +1428,12 @@ class AnimationRunner {
1424
1428
  const entry = this.currentWaapi;
1425
1429
  this.currentWaapi = null;
1426
1430
  entry.stop();
1431
+ const size = this.readShownSize?.() ?? entry.sizeNow();
1427
1432
  try {
1428
1433
  entry.anim.cancel();
1429
1434
  } catch {
1430
1435
  }
1436
+ this.applySizeFn(size);
1431
1437
  }
1432
1438
  cancel() {
1433
1439
  this.currentTween?.cancel();
@@ -1437,6 +1443,7 @@ class AnimationRunner {
1437
1443
  async animateTo(target, velocityPxPerMs) {
1438
1444
  if (target === this.getSize()) {
1439
1445
  if (!this.isAnimating && !this.isDragging()) {
1446
+ this.applySizeFn(target);
1440
1447
  this.element.style.willChange = "";
1441
1448
  }
1442
1449
  return;
@@ -1463,6 +1470,7 @@ class AnimationRunner {
1463
1470
  return;
1464
1471
  }
1465
1472
  }
1473
+ let current = false;
1466
1474
  if (this.animationKind === "spring") {
1467
1475
  const spring = runSpring({
1468
1476
  from: this.getSize(),
@@ -1473,7 +1481,8 @@ class AnimationRunner {
1473
1481
  });
1474
1482
  this.currentSpring = spring;
1475
1483
  await spring.promise;
1476
- if (this.currentSpring === spring) this.currentSpring = null;
1484
+ current = this.currentSpring === spring;
1485
+ if (current) this.currentSpring = null;
1477
1486
  } else {
1478
1487
  const tw = tween({
1479
1488
  from: this.getSize(),
@@ -1484,11 +1493,15 @@ class AnimationRunner {
1484
1493
  });
1485
1494
  this.currentTween = tw;
1486
1495
  await tw.promise;
1487
- if (this.currentTween === tw) this.currentTween = null;
1496
+ current = this.currentTween === tw;
1497
+ if (current) this.currentTween = null;
1488
1498
  }
1489
1499
  if (!this.isAnimating) {
1490
1500
  this.getRootEl()?.removeAttribute("data-animating");
1491
- if (!this.isDragging()) this.element.style.willChange = "";
1501
+ if (!this.isDragging()) {
1502
+ if (current) this.applySizeFn(this.getSize());
1503
+ this.element.style.willChange = "";
1504
+ }
1492
1505
  }
1493
1506
  }
1494
1507
  async runWaapiSettle(samples, target) {
@@ -1502,16 +1515,20 @@ class AnimationRunner {
1502
1515
  easing: "linear",
1503
1516
  fill: "forwards"
1504
1517
  });
1518
+ anim.id = SETTLE_ANIMATION_ID;
1505
1519
  let stopped = false;
1506
1520
  let auxRaf = 0;
1507
1521
  const lastIdx = samples.values.length - 1;
1508
- const auxTick = () => {
1509
- if (stopped) return;
1522
+ const sizeNow = () => {
1510
1523
  const at = Math.min((Number(anim.currentTime) || 0) / samples.stepMs, lastIdx);
1511
1524
  const idx = Math.floor(at);
1512
1525
  const from = samples.values[idx];
1513
1526
  const to = samples.values[Math.min(idx + 1, lastIdx)];
1514
- applyAux(from + (to - from) * (at - idx));
1527
+ return from + (to - from) * (at - idx);
1528
+ };
1529
+ const auxTick = () => {
1530
+ if (stopped) return;
1531
+ applyAux(sizeNow());
1515
1532
  auxRaf = requestAnimationFrame(auxTick);
1516
1533
  };
1517
1534
  auxRaf = requestAnimationFrame(auxTick);
@@ -1520,7 +1537,8 @@ class AnimationRunner {
1520
1537
  stop: () => {
1521
1538
  stopped = true;
1522
1539
  cancelAnimationFrame(auxRaf);
1523
- }
1540
+ },
1541
+ sizeNow
1524
1542
  };
1525
1543
  this.currentWaapi = entry;
1526
1544
  try {
@@ -2653,6 +2671,7 @@ class BottomSheetCore {
2653
2671
  __publicField(this, "closeOnBack");
2654
2672
  __publicField(this, "routedTo");
2655
2673
  __publicField(this, "fitContentToSnap");
2674
+ __publicField(this, "settleAnimation");
2656
2675
  __publicField(this, "persistent");
2657
2676
  __publicField(this, "disableCloseFlag");
2658
2677
  __publicField(this, "disableDragFlag");
@@ -2754,6 +2773,11 @@ class BottomSheetCore {
2754
2773
  const cap = this.snaps.getMaxAxisSize();
2755
2774
  const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2756
2775
  return this.transformTemplate(cap - shown);
2776
+ },
2777
+ readShownSize: () => {
2778
+ const shown = getComputedStyle(this.element).transform;
2779
+ if (!shown || shown === "none") return void 0;
2780
+ return this.snaps.getMaxAxisSize() - offsetFromMatrix(this.mode, new DOMMatrix(shown));
2757
2781
  }
2758
2782
  }, resolved.animation);
2759
2783
  this.lifecycle = new LifecycleController({
@@ -2763,6 +2787,7 @@ class BottomSheetCore {
2763
2787
  this.closeOnBack = resolved.closeOnBack;
2764
2788
  this.routedTo = opts.routedTo;
2765
2789
  this.fitContentToSnap = opts.fitContentToSnap === true;
2790
+ this.settleAnimation = opts.settleAnimation;
2766
2791
  this.persistent = resolved.persistent;
2767
2792
  this.disableCloseFlag = resolved.disableClose;
2768
2793
  this.disableDragFlag = resolved.disableDrag;
@@ -2855,7 +2880,8 @@ class BottomSheetCore {
2855
2880
  closeOnRouteChange: this.closeOnRouteChange,
2856
2881
  persistKey: this.persistKey,
2857
2882
  autoCollapseAfter,
2858
- fitContentToSnap: this.fitContentToSnap
2883
+ fitContentToSnap: this.fitContentToSnap,
2884
+ settleAnimation: this.settleAnimation
2859
2885
  },
2860
2886
  isDestroyed: () => this.destroyed,
2861
2887
  isDragging: () => this.isDraggingAny(),
@@ -3726,7 +3752,8 @@ class BottomSheetCore {
3726
3752
  const offset = cap - clamped;
3727
3753
  const style = this.element.style;
3728
3754
  if (!skipTransform) style.transform = this.transformTemplate(offset);
3729
- if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
3755
+ const sizeChanged = this.sizeWriteSentinel.shouldWrite(clamped, this.animation.isAnimating || this.isDraggingAny() ? SIZE_WRITE_EPSILON : 0);
3756
+ if (sizeChanged) {
3730
3757
  style.setProperty("--bs-size", `${clamped}px`);
3731
3758
  if (this.scrimParent) {
3732
3759
  this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
@@ -3750,7 +3777,7 @@ class BottomSheetCore {
3750
3777
  }
3751
3778
  }
3752
3779
  this.scrim.applyOpacity(progress, progressChanged);
3753
- if (progressChanged && this.bus.listenerCount("progress") > 0) {
3780
+ if ((progressChanged || sizeChanged) && this.bus.listenerCount("progress") > 0) {
3754
3781
  this.progressPayload.value = progress;
3755
3782
  this.progressPayload.size = clamped;
3756
3783
  this.emit("progress", this.progressPayload);
@@ -4233,7 +4260,6 @@ function visualViewportFeature() {
4233
4260
  };
4234
4261
  }
4235
4262
  const INSET_VAR = "--bs-content-inset";
4236
- const SIZE_VAR = "--bs-size";
4237
4263
  const CAP_VAR = "--bs-max-size";
4238
4264
  const LIFT_VAR = "--bs-footer-lift-max";
4239
4265
  const FIT_ATTR = "data-bs-fit-content";
@@ -4246,10 +4272,14 @@ function contentFitFeature() {
4246
4272
  return;
4247
4273
  }
4248
4274
  const sheet = ctx.element;
4275
+ const waapi = ctx.options.settleAnimation === "waapi";
4249
4276
  let inset = 0;
4250
4277
  let unpaddedMax = -1;
4251
4278
  let top = 0;
4252
4279
  let resting = false;
4280
+ let liftMax = 0;
4281
+ let followed = null;
4282
+ let follower = null;
4253
4283
  const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4254
4284
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4255
4285
  const follow = (size) => {
@@ -4263,8 +4293,39 @@ function contentFitFeature() {
4263
4293
  top = limit;
4264
4294
  }
4265
4295
  };
4296
+ const unfollow = () => {
4297
+ follower?.cancel();
4298
+ follower = null;
4299
+ followed = null;
4300
+ };
4301
+ const followSettle = () => {
4302
+ if (followed?.playState === "running") return;
4303
+ const settleAnim = sheet.getAnimations?.().find((a) => a.id === SETTLE_ANIMATION_ID);
4304
+ const footer = sheet.querySelector(".bs-footer");
4305
+ if (!settleAnim || !footer) return;
4306
+ const effect = settleAnim.effect;
4307
+ unfollow();
4308
+ const own = footer.animate(effect.getKeyframes().map((k) => ({
4309
+ offset: k.computedOffset,
4310
+ transform: `translateY(${-Math.min(Math.max(0, parseFloat(String(k.transform).split(",")[1]) || 0), liftMax)}px)`
4311
+ })), {
4312
+ duration: effect.getTiming().duration,
4313
+ easing: "linear",
4314
+ fill: "forwards"
4315
+ });
4316
+ follower = own;
4317
+ followed = settleAnim;
4318
+ const done = () => {
4319
+ if (followed === settleAnim) unfollow();
4320
+ };
4321
+ settleAnim.ready.then(() => {
4322
+ if (follower === own) own.startTime = settleAnim.startTime;
4323
+ }, done);
4324
+ settleAnim.finished.then(done, done);
4325
+ };
4266
4326
  const settle = () => {
4267
4327
  if (ctx.isDestroyed()) return;
4328
+ unfollow();
4268
4329
  const size = ctx.getSize();
4269
4330
  if (!resting) {
4270
4331
  unpaddedMax = -1;
@@ -4272,7 +4333,6 @@ function contentFitFeature() {
4272
4333
  }
4273
4334
  inset = hiddenAt(size);
4274
4335
  put(INSET_VAR, inset);
4275
- put(SIZE_VAR, size);
4276
4336
  put(CAP_VAR, ctx.getMaxAxisSize());
4277
4337
  if (!resting) {
4278
4338
  resting = true;
@@ -4284,9 +4344,13 @@ function contentFitFeature() {
4284
4344
  if (resting) {
4285
4345
  resting = false;
4286
4346
  sheet.setAttribute(FIT_ATTR, "moving");
4287
- put(LIFT_VAR, scroller.offsetHeight);
4347
+ liftMax = scroller.offsetHeight;
4348
+ put(LIFT_VAR, liftMax);
4288
4349
  }
4289
4350
  follow(size);
4351
+ if (waapi && ctx.isAnimating() && sheet.dataset.mode === "bottom") {
4352
+ followSettle();
4353
+ }
4290
4354
  };
4291
4355
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4292
4356
  const whenIdle = () => {
@@ -4296,13 +4360,20 @@ function contentFitFeature() {
4296
4360
  const offProgress = ctx.on("progress", (p) => moving() ? move(p.size) : settle());
4297
4361
  const offSnap = ctx.on("snap", settle);
4298
4362
  const offDragStart = ctx.on("dragstart", () => move(ctx.getSize()));
4363
+ const offBeforeSnap = ctx.on("before-snap", () => {
4364
+ queueMicrotask(() => {
4365
+ if (!ctx.isDestroyed() && ctx.isAnimating()) move(ctx.getSize());
4366
+ });
4367
+ });
4299
4368
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4300
4369
  observer?.observe(document.documentElement);
4301
4370
  window.addEventListener("orientationchange", whenIdle);
4302
4371
  return () => {
4372
+ unfollow();
4303
4373
  offProgress();
4304
4374
  offSnap();
4305
4375
  offDragStart();
4376
+ offBeforeSnap();
4306
4377
  observer?.disconnect();
4307
4378
  window.removeEventListener("orientationchange", whenIdle);
4308
4379
  sheet.removeAttribute(FIT_ATTR);
@@ -82,6 +82,7 @@ function buildTransformTemplate(axis) {
82
82
  return (offset) => `translate3d(${offset}px, 0, 0)`;
83
83
  }
84
84
  }
85
+ const offsetFromMatrix = (axis, m) => axis === "bottom" ? m.m42 : axis === "top" ? -m.m42 : axis === "left" ? -m.m41 : m.m41;
85
86
  const layoutAxis = (axis) => axis === "left" || axis === "right" ? "width" : "height";
86
87
  const counters = {};
87
88
  function nextInstanceId(prefix) {
@@ -1179,7 +1180,7 @@ const tween = ({ from, to, duration, easing = easeOutCubic, onUpdate }) => {
1179
1180
  }
1180
1181
  const step = (now) => {
1181
1182
  if (cancelled) return;
1182
- const elapsed = now - start;
1183
+ const elapsed = Math.max(0, now - start);
1183
1184
  const t = Math.min(elapsed / duration, 1);
1184
1185
  const value = from + (to - from) * easing(t);
1185
1186
  onUpdate(value);
@@ -1227,8 +1228,8 @@ const runSpring = ({ from, to, velocity = 0, config, onUpdate }) => {
1227
1228
  resolveFn = resolve;
1228
1229
  const step = (now) => {
1229
1230
  if (cancelled) return;
1230
- const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
1231
- lastTime = now;
1231
+ const dt = Math.min(Math.max(0, now - lastTime) / 1e3, MAX_DT);
1232
+ lastTime = Math.max(lastTime, now);
1232
1233
  const steps = Math.max(1, Math.ceil(dt * 240));
1233
1234
  const subDt = dt / steps;
1234
1235
  let stepsLeft = steps;
@@ -1308,6 +1309,7 @@ function resolveAnimationPreset(animation) {
1308
1309
  };
1309
1310
  }
1310
1311
  }
1312
+ const SETTLE_ANIMATION_ID = "bs-settle";
1311
1313
  const SIM_HZ = 240;
1312
1314
  const SAMPLE_STRIDE = 4;
1313
1315
  const MAX_SIM_MS = 3e3;
@@ -1368,6 +1370,7 @@ class AnimationRunner {
1368
1370
  __publicField(this, "isDragging");
1369
1371
  __publicField(this, "applyAux");
1370
1372
  __publicField(this, "getTransformFor");
1373
+ __publicField(this, "readShownSize");
1371
1374
  __publicField(this, "settleWaapi");
1372
1375
  __publicField(this, "currentWaapi", null);
1373
1376
  __publicField(this, "animationKind");
@@ -1387,6 +1390,7 @@ class AnimationRunner {
1387
1390
  this.isDragging = deps.isDragging;
1388
1391
  this.applyAux = deps.applyAux;
1389
1392
  this.getTransformFor = deps.getTransformFor;
1393
+ this.readShownSize = deps.readShownSize;
1390
1394
  this.settleWaapi = opts.settleAnimation === "waapi";
1391
1395
  const preset = resolveAnimationPreset(opts.animation);
1392
1396
  this.animationKind = preset.kind;
@@ -1422,10 +1426,12 @@ class AnimationRunner {
1422
1426
  const entry = this.currentWaapi;
1423
1427
  this.currentWaapi = null;
1424
1428
  entry.stop();
1429
+ const size = this.readShownSize?.() ?? entry.sizeNow();
1425
1430
  try {
1426
1431
  entry.anim.cancel();
1427
1432
  } catch {
1428
1433
  }
1434
+ this.applySizeFn(size);
1429
1435
  }
1430
1436
  cancel() {
1431
1437
  this.currentTween?.cancel();
@@ -1435,6 +1441,7 @@ class AnimationRunner {
1435
1441
  async animateTo(target, velocityPxPerMs) {
1436
1442
  if (target === this.getSize()) {
1437
1443
  if (!this.isAnimating && !this.isDragging()) {
1444
+ this.applySizeFn(target);
1438
1445
  this.element.style.willChange = "";
1439
1446
  }
1440
1447
  return;
@@ -1461,6 +1468,7 @@ class AnimationRunner {
1461
1468
  return;
1462
1469
  }
1463
1470
  }
1471
+ let current = false;
1464
1472
  if (this.animationKind === "spring") {
1465
1473
  const spring = runSpring({
1466
1474
  from: this.getSize(),
@@ -1471,7 +1479,8 @@ class AnimationRunner {
1471
1479
  });
1472
1480
  this.currentSpring = spring;
1473
1481
  await spring.promise;
1474
- if (this.currentSpring === spring) this.currentSpring = null;
1482
+ current = this.currentSpring === spring;
1483
+ if (current) this.currentSpring = null;
1475
1484
  } else {
1476
1485
  const tw = tween({
1477
1486
  from: this.getSize(),
@@ -1482,11 +1491,15 @@ class AnimationRunner {
1482
1491
  });
1483
1492
  this.currentTween = tw;
1484
1493
  await tw.promise;
1485
- if (this.currentTween === tw) this.currentTween = null;
1494
+ current = this.currentTween === tw;
1495
+ if (current) this.currentTween = null;
1486
1496
  }
1487
1497
  if (!this.isAnimating) {
1488
1498
  this.getRootEl()?.removeAttribute("data-animating");
1489
- if (!this.isDragging()) this.element.style.willChange = "";
1499
+ if (!this.isDragging()) {
1500
+ if (current) this.applySizeFn(this.getSize());
1501
+ this.element.style.willChange = "";
1502
+ }
1490
1503
  }
1491
1504
  }
1492
1505
  async runWaapiSettle(samples, target) {
@@ -1500,16 +1513,20 @@ class AnimationRunner {
1500
1513
  easing: "linear",
1501
1514
  fill: "forwards"
1502
1515
  });
1516
+ anim.id = SETTLE_ANIMATION_ID;
1503
1517
  let stopped = false;
1504
1518
  let auxRaf = 0;
1505
1519
  const lastIdx = samples.values.length - 1;
1506
- const auxTick = () => {
1507
- if (stopped) return;
1520
+ const sizeNow = () => {
1508
1521
  const at = Math.min((Number(anim.currentTime) || 0) / samples.stepMs, lastIdx);
1509
1522
  const idx = Math.floor(at);
1510
1523
  const from = samples.values[idx];
1511
1524
  const to = samples.values[Math.min(idx + 1, lastIdx)];
1512
- applyAux(from + (to - from) * (at - idx));
1525
+ return from + (to - from) * (at - idx);
1526
+ };
1527
+ const auxTick = () => {
1528
+ if (stopped) return;
1529
+ applyAux(sizeNow());
1513
1530
  auxRaf = requestAnimationFrame(auxTick);
1514
1531
  };
1515
1532
  auxRaf = requestAnimationFrame(auxTick);
@@ -1518,7 +1535,8 @@ class AnimationRunner {
1518
1535
  stop: () => {
1519
1536
  stopped = true;
1520
1537
  cancelAnimationFrame(auxRaf);
1521
- }
1538
+ },
1539
+ sizeNow
1522
1540
  };
1523
1541
  this.currentWaapi = entry;
1524
1542
  try {
@@ -2651,6 +2669,7 @@ class BottomSheetCore {
2651
2669
  __publicField(this, "closeOnBack");
2652
2670
  __publicField(this, "routedTo");
2653
2671
  __publicField(this, "fitContentToSnap");
2672
+ __publicField(this, "settleAnimation");
2654
2673
  __publicField(this, "persistent");
2655
2674
  __publicField(this, "disableCloseFlag");
2656
2675
  __publicField(this, "disableDragFlag");
@@ -2752,6 +2771,11 @@ class BottomSheetCore {
2752
2771
  const cap = this.snaps.getMaxAxisSize();
2753
2772
  const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2754
2773
  return this.transformTemplate(cap - shown);
2774
+ },
2775
+ readShownSize: () => {
2776
+ const shown = getComputedStyle(this.element).transform;
2777
+ if (!shown || shown === "none") return void 0;
2778
+ return this.snaps.getMaxAxisSize() - offsetFromMatrix(this.mode, new DOMMatrix(shown));
2755
2779
  }
2756
2780
  }, resolved.animation);
2757
2781
  this.lifecycle = new LifecycleController({
@@ -2761,6 +2785,7 @@ class BottomSheetCore {
2761
2785
  this.closeOnBack = resolved.closeOnBack;
2762
2786
  this.routedTo = opts.routedTo;
2763
2787
  this.fitContentToSnap = opts.fitContentToSnap === true;
2788
+ this.settleAnimation = opts.settleAnimation;
2764
2789
  this.persistent = resolved.persistent;
2765
2790
  this.disableCloseFlag = resolved.disableClose;
2766
2791
  this.disableDragFlag = resolved.disableDrag;
@@ -2853,7 +2878,8 @@ class BottomSheetCore {
2853
2878
  closeOnRouteChange: this.closeOnRouteChange,
2854
2879
  persistKey: this.persistKey,
2855
2880
  autoCollapseAfter,
2856
- fitContentToSnap: this.fitContentToSnap
2881
+ fitContentToSnap: this.fitContentToSnap,
2882
+ settleAnimation: this.settleAnimation
2857
2883
  },
2858
2884
  isDestroyed: () => this.destroyed,
2859
2885
  isDragging: () => this.isDraggingAny(),
@@ -3724,7 +3750,8 @@ class BottomSheetCore {
3724
3750
  const offset = cap - clamped;
3725
3751
  const style = this.element.style;
3726
3752
  if (!skipTransform) style.transform = this.transformTemplate(offset);
3727
- if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
3753
+ const sizeChanged = this.sizeWriteSentinel.shouldWrite(clamped, this.animation.isAnimating || this.isDraggingAny() ? SIZE_WRITE_EPSILON : 0);
3754
+ if (sizeChanged) {
3728
3755
  style.setProperty("--bs-size", `${clamped}px`);
3729
3756
  if (this.scrimParent) {
3730
3757
  this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
@@ -3748,7 +3775,7 @@ class BottomSheetCore {
3748
3775
  }
3749
3776
  }
3750
3777
  this.scrim.applyOpacity(progress, progressChanged);
3751
- if (progressChanged && this.bus.listenerCount("progress") > 0) {
3778
+ if ((progressChanged || sizeChanged) && this.bus.listenerCount("progress") > 0) {
3752
3779
  this.progressPayload.value = progress;
3753
3780
  this.progressPayload.size = clamped;
3754
3781
  this.emit("progress", this.progressPayload);
@@ -4231,7 +4258,6 @@ function visualViewportFeature() {
4231
4258
  };
4232
4259
  }
4233
4260
  const INSET_VAR = "--bs-content-inset";
4234
- const SIZE_VAR = "--bs-size";
4235
4261
  const CAP_VAR = "--bs-max-size";
4236
4262
  const LIFT_VAR = "--bs-footer-lift-max";
4237
4263
  const FIT_ATTR = "data-bs-fit-content";
@@ -4244,10 +4270,14 @@ function contentFitFeature() {
4244
4270
  return;
4245
4271
  }
4246
4272
  const sheet = ctx.element;
4273
+ const waapi = ctx.options.settleAnimation === "waapi";
4247
4274
  let inset = 0;
4248
4275
  let unpaddedMax = -1;
4249
4276
  let top = 0;
4250
4277
  let resting = false;
4278
+ let liftMax = 0;
4279
+ let followed = null;
4280
+ let follower = null;
4251
4281
  const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4252
4282
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4253
4283
  const follow = (size) => {
@@ -4261,8 +4291,39 @@ function contentFitFeature() {
4261
4291
  top = limit;
4262
4292
  }
4263
4293
  };
4294
+ const unfollow = () => {
4295
+ follower?.cancel();
4296
+ follower = null;
4297
+ followed = null;
4298
+ };
4299
+ const followSettle = () => {
4300
+ if (followed?.playState === "running") return;
4301
+ const settleAnim = sheet.getAnimations?.().find((a) => a.id === SETTLE_ANIMATION_ID);
4302
+ const footer = sheet.querySelector(".bs-footer");
4303
+ if (!settleAnim || !footer) return;
4304
+ const effect = settleAnim.effect;
4305
+ unfollow();
4306
+ const own = footer.animate(effect.getKeyframes().map((k) => ({
4307
+ offset: k.computedOffset,
4308
+ transform: `translateY(${-Math.min(Math.max(0, parseFloat(String(k.transform).split(",")[1]) || 0), liftMax)}px)`
4309
+ })), {
4310
+ duration: effect.getTiming().duration,
4311
+ easing: "linear",
4312
+ fill: "forwards"
4313
+ });
4314
+ follower = own;
4315
+ followed = settleAnim;
4316
+ const done = () => {
4317
+ if (followed === settleAnim) unfollow();
4318
+ };
4319
+ settleAnim.ready.then(() => {
4320
+ if (follower === own) own.startTime = settleAnim.startTime;
4321
+ }, done);
4322
+ settleAnim.finished.then(done, done);
4323
+ };
4264
4324
  const settle = () => {
4265
4325
  if (ctx.isDestroyed()) return;
4326
+ unfollow();
4266
4327
  const size = ctx.getSize();
4267
4328
  if (!resting) {
4268
4329
  unpaddedMax = -1;
@@ -4270,7 +4331,6 @@ function contentFitFeature() {
4270
4331
  }
4271
4332
  inset = hiddenAt(size);
4272
4333
  put(INSET_VAR, inset);
4273
- put(SIZE_VAR, size);
4274
4334
  put(CAP_VAR, ctx.getMaxAxisSize());
4275
4335
  if (!resting) {
4276
4336
  resting = true;
@@ -4282,9 +4342,13 @@ function contentFitFeature() {
4282
4342
  if (resting) {
4283
4343
  resting = false;
4284
4344
  sheet.setAttribute(FIT_ATTR, "moving");
4285
- put(LIFT_VAR, scroller.offsetHeight);
4345
+ liftMax = scroller.offsetHeight;
4346
+ put(LIFT_VAR, liftMax);
4286
4347
  }
4287
4348
  follow(size);
4349
+ if (waapi && ctx.isAnimating() && sheet.dataset.mode === "bottom") {
4350
+ followSettle();
4351
+ }
4288
4352
  };
4289
4353
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4290
4354
  const whenIdle = () => {
@@ -4294,13 +4358,20 @@ function contentFitFeature() {
4294
4358
  const offProgress = ctx.on("progress", (p) => moving() ? move(p.size) : settle());
4295
4359
  const offSnap = ctx.on("snap", settle);
4296
4360
  const offDragStart = ctx.on("dragstart", () => move(ctx.getSize()));
4361
+ const offBeforeSnap = ctx.on("before-snap", () => {
4362
+ queueMicrotask(() => {
4363
+ if (!ctx.isDestroyed() && ctx.isAnimating()) move(ctx.getSize());
4364
+ });
4365
+ });
4297
4366
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4298
4367
  observer?.observe(document.documentElement);
4299
4368
  window.addEventListener("orientationchange", whenIdle);
4300
4369
  return () => {
4370
+ unfollow();
4301
4371
  offProgress();
4302
4372
  offSnap();
4303
4373
  offDragStart();
4374
+ offBeforeSnap();
4304
4375
  observer?.disconnect();
4305
4376
  window.removeEventListener("orientationchange", whenIdle);
4306
4377
  sheet.removeAttribute(FIT_ATTR);