@surdeddd/bottom-sheet 0.23.1 → 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 (61) hide show
  1. package/README.md +3 -3
  2. package/dist/{BottomSheetCore-9i-Uh6T3.d.ts → BottomSheetCore-COvILxmR.d.ts} +2 -0
  3. package/dist/{BottomSheetCore-CQStdVy2.d.cts → BottomSheetCore-CaJwHnxY.d.cts} +2 -0
  4. package/dist/{BottomSheetEngine-CsQWHLNb.d.cts → BottomSheetEngine-C_1aPJsU.d.cts} +1 -1
  5. package/dist/{BottomSheetEngine-Dn6h-7gF.d.ts → BottomSheetEngine-CsgCcCSO.d.ts} +1 -1
  6. package/dist/core.cjs +43 -13
  7. package/dist/core.d.cts +2 -2
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +43 -13
  10. package/dist/debug.d.cts +1 -1
  11. package/dist/debug.d.ts +1 -1
  12. package/dist/{default-features-C3cilcW9.d.ts → default-features-BJx7J0NH.d.ts} +1 -1
  13. package/dist/{default-features-DkG9aho0.d.cts → default-features-CTJb8Wdk.d.cts} +1 -1
  14. package/dist/element.cjs +103 -20
  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 +103 -20
  19. package/dist/features.cjs +58 -3
  20. package/dist/features.d.cts +3 -3
  21. package/dist/features.d.ts +3 -3
  22. package/dist/features.js +58 -3
  23. package/dist/{index-CVGC5B5D.d.cts → index-BBrJJjy5.d.cts} +1 -1
  24. package/dist/{index-CnsJQZp2.d.ts → index-CXN7t3rr.d.ts} +1 -1
  25. package/dist/index.cjs +98 -16
  26. package/dist/index.d.cts +5 -5
  27. package/dist/index.d.ts +5 -5
  28. package/dist/index.js +98 -16
  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 +89 -16
  36. package/dist/qwik-lib/index.qwik.mjs +89 -16
  37. package/dist/qwik.cjs +98 -16
  38. package/dist/qwik.d.cts +2 -2
  39. package/dist/qwik.d.ts +2 -2
  40. package/dist/qwik.js +98 -16
  41. package/dist/react.cjs +98 -16
  42. package/dist/react.d.cts +3 -3
  43. package/dist/react.d.ts +3 -3
  44. package/dist/react.js +98 -16
  45. package/dist/solid.cjs +98 -16
  46. package/dist/solid.d.cts +2 -0
  47. package/dist/solid.d.ts +2 -0
  48. package/dist/solid.js +98 -16
  49. package/dist/solid.source.jsx +98 -16
  50. package/dist/styles.css +8 -6
  51. package/dist/svelte-core.cjs +98 -16
  52. package/dist/svelte-core.js +98 -16
  53. package/dist/svelte.cjs +98 -16
  54. package/dist/svelte.js +98 -16
  55. package/dist/vue.cjs +98 -16
  56. package/dist/vue.js +98 -16
  57. package/dist/webgl.cjs +192 -42
  58. package/dist/webgl.d.cts +1 -1
  59. package/dist/webgl.d.ts +1 -1
  60. package/dist/webgl.js +192 -42
  61. package/package.json +12 -12
package/dist/solid.cjs CHANGED
@@ -89,6 +89,7 @@ function buildTransformTemplate(axis) {
89
89
  return (offset) => `translate3d(${offset}px, 0, 0)`;
90
90
  }
91
91
  }
92
+ var offsetFromMatrix = (axis, m) => axis === "bottom" ? m.m42 : axis === "top" ? -m.m42 : axis === "left" ? -m.m41 : m.m41;
92
93
  var layoutAxis = (axis) => axis === "left" || axis === "right" ? "width" : "height";
93
94
 
94
95
  // src/core/primitives/instance-id.ts
@@ -1174,7 +1175,7 @@ var tween = ({
1174
1175
  }
1175
1176
  const step = (now) => {
1176
1177
  if (cancelled) return;
1177
- const elapsed = now - start;
1178
+ const elapsed = Math.max(0, now - start);
1178
1179
  const t = Math.min(elapsed / duration, 1);
1179
1180
  const value = from + (to - from) * easing(t);
1180
1181
  onUpdate(value);
@@ -1227,8 +1228,8 @@ var runSpring = ({
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;
@@ -1292,6 +1293,7 @@ function resolveAnimationPreset(animation) {
1292
1293
  }
1293
1294
 
1294
1295
  // src/core/animation/waapi-settle.ts
1296
+ var SETTLE_ANIMATION_ID = "bs-settle";
1295
1297
  var SIM_HZ = 240;
1296
1298
  var SAMPLE_STRIDE = 4;
1297
1299
  var MAX_SIM_MS = 3e3;
@@ -1349,6 +1351,7 @@ var AnimationRunner = class {
1349
1351
  __publicField(this, "isDragging");
1350
1352
  __publicField(this, "applyAux");
1351
1353
  __publicField(this, "getTransformFor");
1354
+ __publicField(this, "readShownSize");
1352
1355
  __publicField(this, "settleWaapi");
1353
1356
  __publicField(this, "currentWaapi", null);
1354
1357
  __publicField(this, "animationKind");
@@ -1368,6 +1371,7 @@ var AnimationRunner = class {
1368
1371
  this.isDragging = deps.isDragging;
1369
1372
  this.applyAux = deps.applyAux;
1370
1373
  this.getTransformFor = deps.getTransformFor;
1374
+ this.readShownSize = deps.readShownSize;
1371
1375
  this.settleWaapi = opts.settleAnimation === "waapi";
1372
1376
  const preset = resolveAnimationPreset(opts.animation);
1373
1377
  this.animationKind = preset.kind;
@@ -1400,10 +1404,12 @@ var AnimationRunner = class {
1400
1404
  const entry = this.currentWaapi;
1401
1405
  this.currentWaapi = null;
1402
1406
  entry.stop();
1407
+ const size = this.readShownSize?.() ?? entry.sizeNow();
1403
1408
  try {
1404
1409
  entry.anim.cancel();
1405
1410
  } catch {
1406
1411
  }
1412
+ this.applySizeFn(size);
1407
1413
  }
1408
1414
  cancel() {
1409
1415
  this.currentTween?.cancel();
@@ -1413,6 +1419,7 @@ var AnimationRunner = class {
1413
1419
  async animateTo(target, velocityPxPerMs) {
1414
1420
  if (target === this.getSize()) {
1415
1421
  if (!this.isAnimating && !this.isDragging()) {
1422
+ this.applySizeFn(target);
1416
1423
  this.element.style.willChange = "";
1417
1424
  }
1418
1425
  return;
@@ -1449,6 +1456,7 @@ var AnimationRunner = class {
1449
1456
  return;
1450
1457
  }
1451
1458
  }
1459
+ let current = false;
1452
1460
  if (this.animationKind === "spring") {
1453
1461
  const spring = runSpring({
1454
1462
  from: this.getSize(),
@@ -1459,7 +1467,8 @@ var AnimationRunner = class {
1459
1467
  });
1460
1468
  this.currentSpring = spring;
1461
1469
  await spring.promise;
1462
- if (this.currentSpring === spring) this.currentSpring = null;
1470
+ current = this.currentSpring === spring;
1471
+ if (current) this.currentSpring = null;
1463
1472
  } else {
1464
1473
  const tw = tween({
1465
1474
  from: this.getSize(),
@@ -1470,11 +1479,15 @@ var AnimationRunner = class {
1470
1479
  });
1471
1480
  this.currentTween = tw;
1472
1481
  await tw.promise;
1473
- if (this.currentTween === tw) this.currentTween = null;
1482
+ current = this.currentTween === tw;
1483
+ if (current) this.currentTween = null;
1474
1484
  }
1475
1485
  if (!this.isAnimating) {
1476
1486
  this.getRootEl()?.removeAttribute("data-animating");
1477
- if (!this.isDragging()) this.element.style.willChange = "";
1487
+ if (!this.isDragging()) {
1488
+ if (current) this.applySizeFn(this.getSize());
1489
+ this.element.style.willChange = "";
1490
+ }
1478
1491
  }
1479
1492
  }
1480
1493
  async runWaapiSettle(samples, target) {
@@ -1488,11 +1501,11 @@ var AnimationRunner = class {
1488
1501
  easing: "linear",
1489
1502
  fill: "forwards"
1490
1503
  });
1504
+ anim.id = SETTLE_ANIMATION_ID;
1491
1505
  let stopped = false;
1492
1506
  let auxRaf = 0;
1493
1507
  const lastIdx = samples.values.length - 1;
1494
- const auxTick = () => {
1495
- if (stopped) return;
1508
+ const sizeNow = () => {
1496
1509
  const at = Math.min(
1497
1510
  (Number(anim.currentTime) || 0) / samples.stepMs,
1498
1511
  lastIdx
@@ -1500,7 +1513,11 @@ var AnimationRunner = class {
1500
1513
  const idx = Math.floor(at);
1501
1514
  const from = samples.values[idx];
1502
1515
  const to = samples.values[Math.min(idx + 1, lastIdx)];
1503
- applyAux(from + (to - from) * (at - idx));
1516
+ return from + (to - from) * (at - idx);
1517
+ };
1518
+ const auxTick = () => {
1519
+ if (stopped) return;
1520
+ applyAux(sizeNow());
1504
1521
  auxRaf = requestAnimationFrame(auxTick);
1505
1522
  };
1506
1523
  auxRaf = requestAnimationFrame(auxTick);
@@ -1509,7 +1526,8 @@ var AnimationRunner = class {
1509
1526
  stop: () => {
1510
1527
  stopped = true;
1511
1528
  cancelAnimationFrame(auxRaf);
1512
- }
1529
+ },
1530
+ sizeNow
1513
1531
  };
1514
1532
  this.currentWaapi = entry;
1515
1533
  try {
@@ -2612,6 +2630,7 @@ var BottomSheetCore = class {
2612
2630
  __publicField(this, "closeOnBack");
2613
2631
  __publicField(this, "routedTo");
2614
2632
  __publicField(this, "fitContentToSnap");
2633
+ __publicField(this, "settleAnimation");
2615
2634
  __publicField(this, "persistent");
2616
2635
  __publicField(this, "disableCloseFlag");
2617
2636
  __publicField(this, "disableDragFlag");
@@ -2716,6 +2735,11 @@ var BottomSheetCore = class {
2716
2735
  const cap = this.snaps.getMaxAxisSize();
2717
2736
  const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2718
2737
  return this.transformTemplate(cap - shown);
2738
+ },
2739
+ readShownSize: () => {
2740
+ const shown = getComputedStyle(this.element).transform;
2741
+ if (!shown || shown === "none") return void 0;
2742
+ return this.snaps.getMaxAxisSize() - offsetFromMatrix(this.mode, new DOMMatrix(shown));
2719
2743
  }
2720
2744
  },
2721
2745
  resolved.animation
@@ -2730,6 +2754,7 @@ var BottomSheetCore = class {
2730
2754
  this.closeOnBack = resolved.closeOnBack;
2731
2755
  this.routedTo = opts.routedTo;
2732
2756
  this.fitContentToSnap = opts.fitContentToSnap === true;
2757
+ this.settleAnimation = opts.settleAnimation;
2733
2758
  this.persistent = resolved.persistent;
2734
2759
  this.disableCloseFlag = resolved.disableClose;
2735
2760
  this.disableDragFlag = resolved.disableDrag;
@@ -2832,7 +2857,8 @@ var BottomSheetCore = class {
2832
2857
  closeOnRouteChange: this.closeOnRouteChange,
2833
2858
  persistKey: this.persistKey,
2834
2859
  autoCollapseAfter,
2835
- fitContentToSnap: this.fitContentToSnap
2860
+ fitContentToSnap: this.fitContentToSnap,
2861
+ settleAnimation: this.settleAnimation
2836
2862
  },
2837
2863
  isDestroyed: () => this.destroyed,
2838
2864
  isDragging: () => this.isDraggingAny(),
@@ -3724,7 +3750,11 @@ var BottomSheetCore = class {
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(
3754
+ clamped,
3755
+ this.animation.isAnimating || this.isDraggingAny() ? SIZE_WRITE_EPSILON : 0
3756
+ );
3757
+ if (sizeChanged) {
3728
3758
  style.setProperty("--bs-size", `${clamped}px`);
3729
3759
  if (this.scrimParent) {
3730
3760
  this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
@@ -3751,7 +3781,7 @@ var BottomSheetCore = class {
3751
3781
  }
3752
3782
  }
3753
3783
  this.scrim.applyOpacity(progress, progressChanged);
3754
- if (progressChanged && this.bus.listenerCount("progress") > 0) {
3784
+ if ((progressChanged || sizeChanged) && this.bus.listenerCount("progress") > 0) {
3755
3785
  this.progressPayload.value = progress;
3756
3786
  this.progressPayload.size = clamped;
3757
3787
  this.emit("progress", this.progressPayload);
@@ -4248,7 +4278,6 @@ function visualViewportFeature() {
4248
4278
 
4249
4279
  // src/core/features/content-fit.ts
4250
4280
  var INSET_VAR = "--bs-content-inset";
4251
- var SIZE_VAR = "--bs-size";
4252
4281
  var CAP_VAR = "--bs-max-size";
4253
4282
  var LIFT_VAR = "--bs-footer-lift-max";
4254
4283
  var FIT_ATTR = "data-bs-fit-content";
@@ -4261,10 +4290,14 @@ function contentFitFeature() {
4261
4290
  return;
4262
4291
  }
4263
4292
  const sheet = ctx.element;
4293
+ const waapi = ctx.options.settleAnimation === "waapi";
4264
4294
  let inset = 0;
4265
4295
  let unpaddedMax = -1;
4266
4296
  let top = 0;
4267
4297
  let resting = false;
4298
+ let liftMax = 0;
4299
+ let followed = null;
4300
+ let follower = null;
4268
4301
  const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4269
4302
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4270
4303
  const follow = (size) => {
@@ -4278,8 +4311,45 @@ function contentFitFeature() {
4278
4311
  top = limit;
4279
4312
  }
4280
4313
  };
4314
+ const unfollow = () => {
4315
+ follower?.cancel();
4316
+ follower = null;
4317
+ followed = null;
4318
+ };
4319
+ const followSettle = () => {
4320
+ if (followed?.playState === "running") return;
4321
+ const settleAnim = sheet.getAnimations?.().find((a) => a.id === SETTLE_ANIMATION_ID);
4322
+ const footer = sheet.querySelector(".bs-footer");
4323
+ if (!settleAnim || !footer) return;
4324
+ const effect = settleAnim.effect;
4325
+ unfollow();
4326
+ const own = footer.animate(
4327
+ effect.getKeyframes().map((k) => ({
4328
+ offset: k.computedOffset,
4329
+ transform: `translateY(${-Math.min(
4330
+ Math.max(0, parseFloat(String(k.transform).split(",")[1]) || 0),
4331
+ liftMax
4332
+ )}px)`
4333
+ })),
4334
+ {
4335
+ duration: effect.getTiming().duration,
4336
+ easing: "linear",
4337
+ fill: "forwards"
4338
+ }
4339
+ );
4340
+ follower = own;
4341
+ followed = settleAnim;
4342
+ const done = () => {
4343
+ if (followed === settleAnim) unfollow();
4344
+ };
4345
+ settleAnim.ready.then(() => {
4346
+ if (follower === own) own.startTime = settleAnim.startTime;
4347
+ }, done);
4348
+ settleAnim.finished.then(done, done);
4349
+ };
4281
4350
  const settle = () => {
4282
4351
  if (ctx.isDestroyed()) return;
4352
+ unfollow();
4283
4353
  const size = ctx.getSize();
4284
4354
  if (!resting) {
4285
4355
  unpaddedMax = -1;
@@ -4287,7 +4357,6 @@ function contentFitFeature() {
4287
4357
  }
4288
4358
  inset = hiddenAt(size);
4289
4359
  put(INSET_VAR, inset);
4290
- put(SIZE_VAR, size);
4291
4360
  put(CAP_VAR, ctx.getMaxAxisSize());
4292
4361
  if (!resting) {
4293
4362
  resting = true;
@@ -4299,9 +4368,13 @@ function contentFitFeature() {
4299
4368
  if (resting) {
4300
4369
  resting = false;
4301
4370
  sheet.setAttribute(FIT_ATTR, "moving");
4302
- put(LIFT_VAR, scroller.offsetHeight);
4371
+ liftMax = scroller.offsetHeight;
4372
+ put(LIFT_VAR, liftMax);
4303
4373
  }
4304
4374
  follow(size);
4375
+ if (waapi && ctx.isAnimating() && sheet.dataset.mode === "bottom") {
4376
+ followSettle();
4377
+ }
4305
4378
  };
4306
4379
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4307
4380
  const whenIdle = () => {
@@ -4313,12 +4386,21 @@ function contentFitFeature() {
4313
4386
  (p) => moving() ? move(p.size) : settle()
4314
4387
  );
4315
4388
  const offSnap = ctx.on("snap", settle);
4389
+ const offDragStart = ctx.on("dragstart", () => move(ctx.getSize()));
4390
+ const offBeforeSnap = ctx.on("before-snap", () => {
4391
+ queueMicrotask(() => {
4392
+ if (!ctx.isDestroyed() && ctx.isAnimating()) move(ctx.getSize());
4393
+ });
4394
+ });
4316
4395
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4317
4396
  observer?.observe(document.documentElement);
4318
4397
  window.addEventListener("orientationchange", whenIdle);
4319
4398
  return () => {
4399
+ unfollow();
4320
4400
  offProgress();
4321
4401
  offSnap();
4402
+ offDragStart();
4403
+ offBeforeSnap();
4322
4404
  observer?.disconnect();
4323
4405
  window.removeEventListener("orientationchange", whenIdle);
4324
4406
  sheet.removeAttribute(FIT_ATTR);
package/dist/solid.d.cts CHANGED
@@ -142,6 +142,7 @@ type EngineFeatureOptions = {
142
142
  persistKey?: string;
143
143
  autoCollapseAfter?: number;
144
144
  fitContentToSnap: boolean;
145
+ settleAnimation?: "waapi";
145
146
  };
146
147
  type EngineFeatureContext = {
147
148
  element: HTMLElement;
@@ -265,6 +266,7 @@ declare class BottomSheetCore {
265
266
  private closeOnBack;
266
267
  private routedTo;
267
268
  private fitContentToSnap;
269
+ private settleAnimation;
268
270
  private persistent;
269
271
  private disableCloseFlag;
270
272
  private disableDragFlag;
package/dist/solid.d.ts CHANGED
@@ -142,6 +142,7 @@ type EngineFeatureOptions = {
142
142
  persistKey?: string;
143
143
  autoCollapseAfter?: number;
144
144
  fitContentToSnap: boolean;
145
+ settleAnimation?: "waapi";
145
146
  };
146
147
  type EngineFeatureContext = {
147
148
  element: HTMLElement;
@@ -265,6 +266,7 @@ declare class BottomSheetCore {
265
266
  private closeOnBack;
266
267
  private routedTo;
267
268
  private fitContentToSnap;
269
+ private settleAnimation;
268
270
  private persistent;
269
271
  private disableCloseFlag;
270
272
  private disableDragFlag;
package/dist/solid.js CHANGED
@@ -87,6 +87,7 @@ function buildTransformTemplate(axis) {
87
87
  return (offset) => `translate3d(${offset}px, 0, 0)`;
88
88
  }
89
89
  }
90
+ var offsetFromMatrix = (axis, m) => axis === "bottom" ? m.m42 : axis === "top" ? -m.m42 : axis === "left" ? -m.m41 : m.m41;
90
91
  var layoutAxis = (axis) => axis === "left" || axis === "right" ? "width" : "height";
91
92
 
92
93
  // src/core/primitives/instance-id.ts
@@ -1172,7 +1173,7 @@ var tween = ({
1172
1173
  }
1173
1174
  const step = (now) => {
1174
1175
  if (cancelled) return;
1175
- const elapsed = now - start;
1176
+ const elapsed = Math.max(0, now - start);
1176
1177
  const t = Math.min(elapsed / duration, 1);
1177
1178
  const value = from + (to - from) * easing(t);
1178
1179
  onUpdate(value);
@@ -1225,8 +1226,8 @@ var runSpring = ({
1225
1226
  resolveFn = resolve;
1226
1227
  const step = (now) => {
1227
1228
  if (cancelled) return;
1228
- const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
1229
- lastTime = now;
1229
+ const dt = Math.min(Math.max(0, now - lastTime) / 1e3, MAX_DT);
1230
+ lastTime = Math.max(lastTime, now);
1230
1231
  const steps = Math.max(1, Math.ceil(dt * 240));
1231
1232
  const subDt = dt / steps;
1232
1233
  let stepsLeft = steps;
@@ -1290,6 +1291,7 @@ function resolveAnimationPreset(animation) {
1290
1291
  }
1291
1292
 
1292
1293
  // src/core/animation/waapi-settle.ts
1294
+ var SETTLE_ANIMATION_ID = "bs-settle";
1293
1295
  var SIM_HZ = 240;
1294
1296
  var SAMPLE_STRIDE = 4;
1295
1297
  var MAX_SIM_MS = 3e3;
@@ -1347,6 +1349,7 @@ var AnimationRunner = class {
1347
1349
  __publicField(this, "isDragging");
1348
1350
  __publicField(this, "applyAux");
1349
1351
  __publicField(this, "getTransformFor");
1352
+ __publicField(this, "readShownSize");
1350
1353
  __publicField(this, "settleWaapi");
1351
1354
  __publicField(this, "currentWaapi", null);
1352
1355
  __publicField(this, "animationKind");
@@ -1366,6 +1369,7 @@ var AnimationRunner = class {
1366
1369
  this.isDragging = deps.isDragging;
1367
1370
  this.applyAux = deps.applyAux;
1368
1371
  this.getTransformFor = deps.getTransformFor;
1372
+ this.readShownSize = deps.readShownSize;
1369
1373
  this.settleWaapi = opts.settleAnimation === "waapi";
1370
1374
  const preset = resolveAnimationPreset(opts.animation);
1371
1375
  this.animationKind = preset.kind;
@@ -1398,10 +1402,12 @@ var AnimationRunner = class {
1398
1402
  const entry = this.currentWaapi;
1399
1403
  this.currentWaapi = null;
1400
1404
  entry.stop();
1405
+ const size = this.readShownSize?.() ?? entry.sizeNow();
1401
1406
  try {
1402
1407
  entry.anim.cancel();
1403
1408
  } catch {
1404
1409
  }
1410
+ this.applySizeFn(size);
1405
1411
  }
1406
1412
  cancel() {
1407
1413
  this.currentTween?.cancel();
@@ -1411,6 +1417,7 @@ var AnimationRunner = class {
1411
1417
  async animateTo(target, velocityPxPerMs) {
1412
1418
  if (target === this.getSize()) {
1413
1419
  if (!this.isAnimating && !this.isDragging()) {
1420
+ this.applySizeFn(target);
1414
1421
  this.element.style.willChange = "";
1415
1422
  }
1416
1423
  return;
@@ -1447,6 +1454,7 @@ var AnimationRunner = class {
1447
1454
  return;
1448
1455
  }
1449
1456
  }
1457
+ let current = false;
1450
1458
  if (this.animationKind === "spring") {
1451
1459
  const spring = runSpring({
1452
1460
  from: this.getSize(),
@@ -1457,7 +1465,8 @@ var AnimationRunner = class {
1457
1465
  });
1458
1466
  this.currentSpring = spring;
1459
1467
  await spring.promise;
1460
- if (this.currentSpring === spring) this.currentSpring = null;
1468
+ current = this.currentSpring === spring;
1469
+ if (current) this.currentSpring = null;
1461
1470
  } else {
1462
1471
  const tw = tween({
1463
1472
  from: this.getSize(),
@@ -1468,11 +1477,15 @@ var AnimationRunner = class {
1468
1477
  });
1469
1478
  this.currentTween = tw;
1470
1479
  await tw.promise;
1471
- if (this.currentTween === tw) this.currentTween = null;
1480
+ current = this.currentTween === tw;
1481
+ if (current) this.currentTween = null;
1472
1482
  }
1473
1483
  if (!this.isAnimating) {
1474
1484
  this.getRootEl()?.removeAttribute("data-animating");
1475
- if (!this.isDragging()) this.element.style.willChange = "";
1485
+ if (!this.isDragging()) {
1486
+ if (current) this.applySizeFn(this.getSize());
1487
+ this.element.style.willChange = "";
1488
+ }
1476
1489
  }
1477
1490
  }
1478
1491
  async runWaapiSettle(samples, target) {
@@ -1486,11 +1499,11 @@ var AnimationRunner = class {
1486
1499
  easing: "linear",
1487
1500
  fill: "forwards"
1488
1501
  });
1502
+ anim.id = SETTLE_ANIMATION_ID;
1489
1503
  let stopped = false;
1490
1504
  let auxRaf = 0;
1491
1505
  const lastIdx = samples.values.length - 1;
1492
- const auxTick = () => {
1493
- if (stopped) return;
1506
+ const sizeNow = () => {
1494
1507
  const at = Math.min(
1495
1508
  (Number(anim.currentTime) || 0) / samples.stepMs,
1496
1509
  lastIdx
@@ -1498,7 +1511,11 @@ var AnimationRunner = class {
1498
1511
  const idx = Math.floor(at);
1499
1512
  const from = samples.values[idx];
1500
1513
  const to = samples.values[Math.min(idx + 1, lastIdx)];
1501
- applyAux(from + (to - from) * (at - idx));
1514
+ return from + (to - from) * (at - idx);
1515
+ };
1516
+ const auxTick = () => {
1517
+ if (stopped) return;
1518
+ applyAux(sizeNow());
1502
1519
  auxRaf = requestAnimationFrame(auxTick);
1503
1520
  };
1504
1521
  auxRaf = requestAnimationFrame(auxTick);
@@ -1507,7 +1524,8 @@ var AnimationRunner = class {
1507
1524
  stop: () => {
1508
1525
  stopped = true;
1509
1526
  cancelAnimationFrame(auxRaf);
1510
- }
1527
+ },
1528
+ sizeNow
1511
1529
  };
1512
1530
  this.currentWaapi = entry;
1513
1531
  try {
@@ -2610,6 +2628,7 @@ var BottomSheetCore = class {
2610
2628
  __publicField(this, "closeOnBack");
2611
2629
  __publicField(this, "routedTo");
2612
2630
  __publicField(this, "fitContentToSnap");
2631
+ __publicField(this, "settleAnimation");
2613
2632
  __publicField(this, "persistent");
2614
2633
  __publicField(this, "disableCloseFlag");
2615
2634
  __publicField(this, "disableDragFlag");
@@ -2714,6 +2733,11 @@ var BottomSheetCore = class {
2714
2733
  const cap = this.snaps.getMaxAxisSize();
2715
2734
  const shown = cap > 0 && !this.allowOvershoot ? Math.min(size, cap) : size;
2716
2735
  return this.transformTemplate(cap - shown);
2736
+ },
2737
+ readShownSize: () => {
2738
+ const shown = getComputedStyle(this.element).transform;
2739
+ if (!shown || shown === "none") return void 0;
2740
+ return this.snaps.getMaxAxisSize() - offsetFromMatrix(this.mode, new DOMMatrix(shown));
2717
2741
  }
2718
2742
  },
2719
2743
  resolved.animation
@@ -2728,6 +2752,7 @@ var BottomSheetCore = class {
2728
2752
  this.closeOnBack = resolved.closeOnBack;
2729
2753
  this.routedTo = opts.routedTo;
2730
2754
  this.fitContentToSnap = opts.fitContentToSnap === true;
2755
+ this.settleAnimation = opts.settleAnimation;
2731
2756
  this.persistent = resolved.persistent;
2732
2757
  this.disableCloseFlag = resolved.disableClose;
2733
2758
  this.disableDragFlag = resolved.disableDrag;
@@ -2830,7 +2855,8 @@ var BottomSheetCore = class {
2830
2855
  closeOnRouteChange: this.closeOnRouteChange,
2831
2856
  persistKey: this.persistKey,
2832
2857
  autoCollapseAfter,
2833
- fitContentToSnap: this.fitContentToSnap
2858
+ fitContentToSnap: this.fitContentToSnap,
2859
+ settleAnimation: this.settleAnimation
2834
2860
  },
2835
2861
  isDestroyed: () => this.destroyed,
2836
2862
  isDragging: () => this.isDraggingAny(),
@@ -3722,7 +3748,11 @@ var BottomSheetCore = class {
3722
3748
  const offset = cap - clamped;
3723
3749
  const style = this.element.style;
3724
3750
  if (!skipTransform) style.transform = this.transformTemplate(offset);
3725
- if (this.sizeWriteSentinel.shouldWrite(clamped, SIZE_WRITE_EPSILON)) {
3751
+ const sizeChanged = this.sizeWriteSentinel.shouldWrite(
3752
+ clamped,
3753
+ this.animation.isAnimating || this.isDraggingAny() ? SIZE_WRITE_EPSILON : 0
3754
+ );
3755
+ if (sizeChanged) {
3726
3756
  style.setProperty("--bs-size", `${clamped}px`);
3727
3757
  if (this.scrimParent) {
3728
3758
  this.scrimParent.style.setProperty("--bs-size", `${clamped}px`);
@@ -3749,7 +3779,7 @@ var BottomSheetCore = class {
3749
3779
  }
3750
3780
  }
3751
3781
  this.scrim.applyOpacity(progress, progressChanged);
3752
- if (progressChanged && this.bus.listenerCount("progress") > 0) {
3782
+ if ((progressChanged || sizeChanged) && this.bus.listenerCount("progress") > 0) {
3753
3783
  this.progressPayload.value = progress;
3754
3784
  this.progressPayload.size = clamped;
3755
3785
  this.emit("progress", this.progressPayload);
@@ -4246,7 +4276,6 @@ function visualViewportFeature() {
4246
4276
 
4247
4277
  // src/core/features/content-fit.ts
4248
4278
  var INSET_VAR = "--bs-content-inset";
4249
- var SIZE_VAR = "--bs-size";
4250
4279
  var CAP_VAR = "--bs-max-size";
4251
4280
  var LIFT_VAR = "--bs-footer-lift-max";
4252
4281
  var FIT_ATTR = "data-bs-fit-content";
@@ -4259,10 +4288,14 @@ function contentFitFeature() {
4259
4288
  return;
4260
4289
  }
4261
4290
  const sheet = ctx.element;
4291
+ const waapi = ctx.options.settleAnimation === "waapi";
4262
4292
  let inset = 0;
4263
4293
  let unpaddedMax = -1;
4264
4294
  let top = 0;
4265
4295
  let resting = false;
4296
+ let liftMax = 0;
4297
+ let followed = null;
4298
+ let follower = null;
4266
4299
  const put = (name, px) => sheet.style.setProperty(name, `${px}px`);
4267
4300
  const hiddenAt = (size) => sheet.dataset.mode === "bottom" ? Math.max(0, ctx.getMaxAxisSize() - size) : 0;
4268
4301
  const follow = (size) => {
@@ -4276,8 +4309,45 @@ function contentFitFeature() {
4276
4309
  top = limit;
4277
4310
  }
4278
4311
  };
4312
+ const unfollow = () => {
4313
+ follower?.cancel();
4314
+ follower = null;
4315
+ followed = null;
4316
+ };
4317
+ const followSettle = () => {
4318
+ if (followed?.playState === "running") return;
4319
+ const settleAnim = sheet.getAnimations?.().find((a) => a.id === SETTLE_ANIMATION_ID);
4320
+ const footer = sheet.querySelector(".bs-footer");
4321
+ if (!settleAnim || !footer) return;
4322
+ const effect = settleAnim.effect;
4323
+ unfollow();
4324
+ const own = footer.animate(
4325
+ effect.getKeyframes().map((k) => ({
4326
+ offset: k.computedOffset,
4327
+ transform: `translateY(${-Math.min(
4328
+ Math.max(0, parseFloat(String(k.transform).split(",")[1]) || 0),
4329
+ liftMax
4330
+ )}px)`
4331
+ })),
4332
+ {
4333
+ duration: effect.getTiming().duration,
4334
+ easing: "linear",
4335
+ fill: "forwards"
4336
+ }
4337
+ );
4338
+ follower = own;
4339
+ followed = settleAnim;
4340
+ const done = () => {
4341
+ if (followed === settleAnim) unfollow();
4342
+ };
4343
+ settleAnim.ready.then(() => {
4344
+ if (follower === own) own.startTime = settleAnim.startTime;
4345
+ }, done);
4346
+ settleAnim.finished.then(done, done);
4347
+ };
4279
4348
  const settle = () => {
4280
4349
  if (ctx.isDestroyed()) return;
4350
+ unfollow();
4281
4351
  const size = ctx.getSize();
4282
4352
  if (!resting) {
4283
4353
  unpaddedMax = -1;
@@ -4285,7 +4355,6 @@ function contentFitFeature() {
4285
4355
  }
4286
4356
  inset = hiddenAt(size);
4287
4357
  put(INSET_VAR, inset);
4288
- put(SIZE_VAR, size);
4289
4358
  put(CAP_VAR, ctx.getMaxAxisSize());
4290
4359
  if (!resting) {
4291
4360
  resting = true;
@@ -4297,9 +4366,13 @@ function contentFitFeature() {
4297
4366
  if (resting) {
4298
4367
  resting = false;
4299
4368
  sheet.setAttribute(FIT_ATTR, "moving");
4300
- put(LIFT_VAR, scroller.offsetHeight);
4369
+ liftMax = scroller.offsetHeight;
4370
+ put(LIFT_VAR, liftMax);
4301
4371
  }
4302
4372
  follow(size);
4373
+ if (waapi && ctx.isAnimating() && sheet.dataset.mode === "bottom") {
4374
+ followSettle();
4375
+ }
4303
4376
  };
4304
4377
  const moving = () => ctx.isAnimating() || ctx.isDragging();
4305
4378
  const whenIdle = () => {
@@ -4311,12 +4384,21 @@ function contentFitFeature() {
4311
4384
  (p) => moving() ? move(p.size) : settle()
4312
4385
  );
4313
4386
  const offSnap = ctx.on("snap", settle);
4387
+ const offDragStart = ctx.on("dragstart", () => move(ctx.getSize()));
4388
+ const offBeforeSnap = ctx.on("before-snap", () => {
4389
+ queueMicrotask(() => {
4390
+ if (!ctx.isDestroyed() && ctx.isAnimating()) move(ctx.getSize());
4391
+ });
4392
+ });
4314
4393
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(whenIdle);
4315
4394
  observer?.observe(document.documentElement);
4316
4395
  window.addEventListener("orientationchange", whenIdle);
4317
4396
  return () => {
4397
+ unfollow();
4318
4398
  offProgress();
4319
4399
  offSnap();
4400
+ offDragStart();
4401
+ offBeforeSnap();
4320
4402
  observer?.disconnect();
4321
4403
  window.removeEventListener("orientationchange", whenIdle);
4322
4404
  sheet.removeAttribute(FIT_ATTR);