@surdeddd/bottom-sheet 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +126 -83
  2. package/dist/{BottomSheetEngine-CBRcBwV-.d.ts → BottomSheetEngine-DRjCU73e.d.ts} +6 -5
  3. package/dist/{BottomSheetEngine-BcyruNP1.d.cts → BottomSheetEngine-DzsIwD28.d.cts} +6 -5
  4. package/dist/element.cjs +388 -222
  5. package/dist/element.d.cts +1 -1
  6. package/dist/element.d.ts +1 -1
  7. package/dist/element.iife.global.js +2 -2
  8. package/dist/element.js +388 -222
  9. package/dist/index.cjs +389 -266
  10. package/dist/index.d.cts +2 -2
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +389 -266
  13. package/dist/integrations/formik.d.cts +1 -1
  14. package/dist/integrations/formik.d.ts +1 -1
  15. package/dist/integrations/react-hook-form.d.cts +1 -1
  16. package/dist/integrations/react-hook-form.d.ts +1 -1
  17. package/dist/overlay.cjs +191 -58
  18. package/dist/overlay.d.cts +4 -3
  19. package/dist/overlay.d.ts +4 -3
  20. package/dist/overlay.js +191 -58
  21. package/dist/preact.d.cts +2 -1
  22. package/dist/preact.d.ts +2 -1
  23. package/dist/qwik.cjs +396 -211
  24. package/dist/qwik.d.cts +11 -2
  25. package/dist/qwik.d.ts +11 -2
  26. package/dist/qwik.js +396 -211
  27. package/dist/react.cjs +500 -332
  28. package/dist/react.d.cts +26 -4
  29. package/dist/react.d.ts +26 -4
  30. package/dist/react.js +500 -332
  31. package/dist/solid.cjs +362 -210
  32. package/dist/solid.d.cts +14 -4
  33. package/dist/solid.d.ts +14 -4
  34. package/dist/solid.js +362 -210
  35. package/dist/solid.source.jsx +362 -210
  36. package/dist/styles.css +17 -1
  37. package/dist/svelte-core.cjs +345 -208
  38. package/dist/svelte-core.js +345 -208
  39. package/dist/svelte-src/BottomSheet.svelte +6 -0
  40. package/dist/svelte.cjs +359 -220
  41. package/dist/svelte.d.cts +2 -0
  42. package/dist/svelte.d.ts +2 -0
  43. package/dist/svelte.js +359 -220
  44. package/dist/teleport-7uYNiEAT.d.cts +3 -0
  45. package/dist/teleport-7uYNiEAT.d.ts +3 -0
  46. package/dist/vue.cjs +353 -209
  47. package/dist/vue.d.cts +3 -1
  48. package/dist/vue.d.ts +3 -1
  49. package/dist/vue.js +353 -209
  50. package/package.json +11 -9
package/dist/svelte.js CHANGED
@@ -185,11 +185,18 @@ var resolveSnap = (point, mode, measureFit) => {
185
185
  return Math.max(0, el.getBoundingClientRect().width);
186
186
  };
187
187
 
188
+ // src/core/primitives/devWarn.ts
189
+ function devWarn(...args) {
190
+ if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
191
+ console.warn(...args);
192
+ }
193
+ }
194
+
188
195
  // src/core/primitives/snap-points.ts
189
196
  var resolveSnapList = (points, mode, measureFit) => points.map((p) => {
190
197
  const raw = resolveSnap(p.size, mode, measureFit);
191
198
  if (!Number.isFinite(raw) || raw < 0) {
192
- console.warn(
199
+ devWarn(
193
200
  `[BottomSheet] snap "${p.id}" resolved to invalid size (${String(p.size)} \u2192 ${raw}); clamped to 0.`
194
201
  );
195
202
  return { id: p.id, size: 0 };
@@ -201,7 +208,7 @@ var auditVhUsage = (points) => {
201
208
  for (const p of points) {
202
209
  if (typeof p.size !== "string") continue;
203
210
  if (!VH_NOT_DVH.test(p.size)) continue;
204
- console.warn(
211
+ devWarn(
205
212
  `[BottomSheet] snap "${p.id}" uses "vh" \u2014 prefer "dvh" on mobile (iOS Safari URL bar makes vh unstable). See https://web.dev/blog/viewport-units`
206
213
  );
207
214
  }
@@ -255,6 +262,26 @@ var findDragSettleTarget = (input) => {
255
262
  );
256
263
  };
257
264
 
265
+ // src/core/primitives/cancelable-emit.ts
266
+ function emitCancelable(emit, base, warnLabel) {
267
+ let cancelled = false;
268
+ let frozen = false;
269
+ emit({
270
+ ...base,
271
+ cancel: () => {
272
+ if (frozen) {
273
+ devWarn(
274
+ `[BottomSheet] ${warnLabel}.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener.`
275
+ );
276
+ return;
277
+ }
278
+ cancelled = true;
279
+ }
280
+ });
281
+ frozen = true;
282
+ return cancelled;
283
+ }
284
+
258
285
  // src/core/primitives/snap-resolver.ts
259
286
  var SnapResolver = class {
260
287
  constructor(raw, allowed, mode, measureFit, onMaxAxisSizeChange) {
@@ -399,7 +426,9 @@ function notifyLinkedSheets(sheets, self) {
399
426
  try {
400
427
  if (linked.state.size === 0) continue;
401
428
  const ids = linked.getAllowedIds();
402
- const target = ids.find((id) => id !== "closed");
429
+ const resolved = linked.getResolvedSnaps();
430
+ const sizeOf = (id) => resolved.find((s) => s.id === id)?.size ?? 0;
431
+ const target = ids.find((id) => sizeOf(id) > 0);
403
432
  if (target && target !== linked.state.activeId) {
404
433
  void linked.snapTo(target);
405
434
  }
@@ -411,46 +440,198 @@ function notifyLinkedSheets(sheets, self) {
411
440
  }
412
441
  }
413
442
 
414
- // src/core/features/route.ts
415
- var closers = [];
416
- var handlerInstalled = false;
443
+ // src/core/features/history-coordinator.ts
444
+ var entries = [];
445
+ var subscribers = /* @__PURE__ */ new Set();
417
446
  var suppress = 0;
418
- var ensureHandler = () => {
419
- if (handlerInstalled || typeof window === "undefined") return;
420
- handlerInstalled = true;
421
- window.addEventListener("popstate", () => {
422
- if (suppress > 0) {
423
- suppress -= 1;
424
- return;
447
+ var internalDepth = 0;
448
+ var pendingRebrand = null;
449
+ var listenerInstalled = false;
450
+ var patchInstalled = false;
451
+ var origPushState = null;
452
+ var origReplaceState = null;
453
+ var patchedPushState = null;
454
+ var patchedReplaceState = null;
455
+ var hasWindow = () => typeof window !== "undefined";
456
+ var hasHistory = () => typeof history !== "undefined";
457
+ var runInternal = (fn) => {
458
+ internalDepth += 1;
459
+ try {
460
+ fn();
461
+ } finally {
462
+ internalDepth -= 1;
463
+ }
464
+ };
465
+ var notifyRouteChange = () => {
466
+ const snapshot = Array.from(subscribers);
467
+ for (const fn of snapshot) fn();
468
+ };
469
+ var ensureListener = () => {
470
+ if (listenerInstalled || !hasWindow()) return;
471
+ window.addEventListener("popstate", onPopState);
472
+ listenerInstalled = true;
473
+ };
474
+ var maybeTeardownListener = () => {
475
+ if (!listenerInstalled) return;
476
+ if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
477
+ if (hasWindow()) window.removeEventListener("popstate", onPopState);
478
+ listenerInstalled = false;
479
+ };
480
+ var installPatch = () => {
481
+ if (patchInstalled || !hasHistory()) return;
482
+ origPushState = history.pushState;
483
+ origReplaceState = history.replaceState;
484
+ patchedPushState = function(...args) {
485
+ origPushState.apply(this, args);
486
+ if (internalDepth === 0) notifyRouteChange();
487
+ };
488
+ patchedReplaceState = function(...args) {
489
+ origReplaceState.apply(this, args);
490
+ if (internalDepth === 0) notifyRouteChange();
491
+ };
492
+ history.pushState = patchedPushState;
493
+ history.replaceState = patchedReplaceState;
494
+ patchInstalled = true;
495
+ };
496
+ var removePatch = () => {
497
+ if (!patchInstalled) return;
498
+ if (history.pushState === patchedPushState && origPushState) {
499
+ history.pushState = origPushState;
500
+ }
501
+ if (history.replaceState === patchedReplaceState && origReplaceState) {
502
+ history.replaceState = origReplaceState;
503
+ }
504
+ origPushState = null;
505
+ origReplaceState = null;
506
+ patchedPushState = null;
507
+ patchedReplaceState = null;
508
+ patchInstalled = false;
509
+ };
510
+ function onPopState() {
511
+ if (suppress > 0) {
512
+ suppress -= 1;
513
+ const rebrand = pendingRebrand;
514
+ pendingRebrand = null;
515
+ if (rebrand) rebrand();
516
+ maybeTeardownListener();
517
+ return;
518
+ }
519
+ if (entries.length === 0) {
520
+ notifyRouteChange();
521
+ maybeTeardownListener();
522
+ return;
523
+ }
524
+ let target = null;
525
+ let targetIdx = -1;
526
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
527
+ const entry = entries[i];
528
+ if (!entry.surface.isOpen()) continue;
529
+ if (!target) {
530
+ target = entry;
531
+ targetIdx = i;
425
532
  }
426
- let target = null;
427
- for (let i = closers.length - 1; i >= 0; i -= 1) {
428
- const c = closers[i];
429
- if (!c.isOpen()) continue;
430
- if (!target) target = c;
431
- if (c.isTop()) {
432
- target = c;
433
- break;
434
- }
533
+ if (entry.surface.isTop()) {
534
+ target = entry;
535
+ targetIdx = i;
536
+ break;
435
537
  }
436
- if (!target) return;
437
- target.consumed = true;
438
- const idx = closers.indexOf(target);
439
- if (idx !== -1) closers.splice(idx, 1);
440
- const settled = target;
441
- void Promise.resolve(settled.close()).then(() => {
442
- if (settled.isOpen()) settled.restore();
443
- });
538
+ }
539
+ if (!target) {
540
+ const removed = entries.pop();
541
+ if (removed) removed.live = false;
542
+ maybeTeardownListener();
543
+ return;
544
+ }
545
+ target.live = false;
546
+ entries.splice(targetIdx, 1);
547
+ const settled = target;
548
+ void Promise.resolve(settled.surface.close()).then(() => {
549
+ if (settled.surface.isOpen()) restore(settled);
444
550
  });
445
- };
446
- var programmaticBack = () => {
447
- suppress += 1;
448
- try {
449
- history.back();
450
- } catch {
451
- suppress = Math.max(0, suppress - 1);
551
+ maybeTeardownListener();
552
+ }
553
+ function restore(entry) {
554
+ if (!hasWindow() || !hasHistory()) return;
555
+ entry.live = true;
556
+ runInternal(() => {
557
+ try {
558
+ history.pushState(entry.surface.markerState(), "", entry.surface.url);
559
+ } catch {
560
+ entry.live = false;
561
+ }
562
+ });
563
+ if (entry.live) {
564
+ entries.push(entry);
565
+ ensureListener();
452
566
  }
453
- };
567
+ }
568
+ function pushBackMarker(surface) {
569
+ const entry = { surface, priorUrl: void 0, live: false };
570
+ if (!hasWindow() || !hasHistory()) {
571
+ return entry;
572
+ }
573
+ entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
574
+ runInternal(() => {
575
+ try {
576
+ history.pushState(surface.markerState(), "", surface.url);
577
+ entry.live = true;
578
+ } catch {
579
+ entry.live = false;
580
+ }
581
+ });
582
+ if (entry.live) {
583
+ entries.push(entry);
584
+ ensureListener();
585
+ }
586
+ return entry;
587
+ }
588
+ function popBackMarker(handle) {
589
+ if (!hasWindow() || !hasHistory()) return;
590
+ const entry = handle;
591
+ const idx = entries.indexOf(entry);
592
+ if (idx === -1 || !entry.live) return;
593
+ const last = entries.length - 1;
594
+ entry.live = false;
595
+ entries.splice(idx, 1);
596
+ if (idx !== last) {
597
+ const rebrandSurface = entries[entries.length - 1].surface;
598
+ const rebrandUrl = entry.priorUrl;
599
+ pendingRebrand = () => {
600
+ runInternal(() => {
601
+ history.replaceState(
602
+ rebrandSurface.markerState(),
603
+ "",
604
+ rebrandUrl !== void 0 ? rebrandUrl : location.href
605
+ );
606
+ });
607
+ };
608
+ }
609
+ suppress += 1;
610
+ runInternal(() => {
611
+ try {
612
+ history.back();
613
+ } catch {
614
+ suppress = Math.max(0, suppress - 1);
615
+ pendingRebrand = null;
616
+ }
617
+ });
618
+ maybeTeardownListener();
619
+ }
620
+ function subscribeRouteChange(fn) {
621
+ if (!hasWindow() || !hasHistory()) return () => {
622
+ };
623
+ subscribers.add(fn);
624
+ if (subscribers.size === 1) installPatch();
625
+ ensureListener();
626
+ return () => {
627
+ if (!subscribers.has(fn)) return;
628
+ subscribers.delete(fn);
629
+ if (subscribers.size === 0) removePatch();
630
+ maybeTeardownListener();
631
+ };
632
+ }
633
+
634
+ // src/core/features/route.ts
454
635
  function installRoute(deps) {
455
636
  if (typeof window === "undefined") {
456
637
  return () => {
@@ -460,92 +641,39 @@ function installRoute(deps) {
460
641
  return () => {
461
642
  };
462
643
  }
463
- let pushed = false;
464
- let closer = null;
465
- const teardownEntry = () => {
466
- if (closer) {
467
- const idx = closers.indexOf(closer);
468
- if (idx !== -1) closers.splice(idx, 1);
469
- }
470
- const wasConsumed = closer?.consumed ?? false;
471
- closer = null;
472
- if (pushed && !wasConsumed) {
473
- pushed = false;
474
- programmaticBack();
475
- } else {
476
- pushed = false;
477
- }
478
- };
479
- const pushEntry = () => {
480
- try {
481
- if (deps.routedTo !== void 0) {
482
- history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
483
- } else {
484
- history.pushState({ __bsSheet: deps.sheetId }, "");
485
- }
486
- pushed = true;
487
- } catch {
488
- pushed = false;
489
- }
490
- };
644
+ let handle = null;
491
645
  const onOpen = () => {
492
- if (closer) return;
493
- const self = {
646
+ if (handle) return;
647
+ handle = pushBackMarker({
494
648
  isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
495
- isTop: () => deps.isTopSheet(),
496
- close: () => deps.close(),
497
- restore: () => {
498
- if (deps.isDestroyed() || closer !== self) return;
499
- self.consumed = false;
500
- if (!closers.includes(self)) closers.push(self);
501
- pushEntry();
502
- },
503
- consumed: false
504
- };
505
- closer = self;
506
- ensureHandler();
507
- closers.push(self);
508
- pushEntry();
649
+ isTop: deps.isTopSheet,
650
+ close: deps.close,
651
+ markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
652
+ url: deps.routedTo
653
+ });
654
+ };
655
+ const onClose = () => {
656
+ if (!handle) return;
657
+ popBackMarker(handle);
658
+ handle = null;
509
659
  };
510
660
  const unsubscribeOpen = deps.on("open", onOpen);
511
- const unsubscribeClose = deps.on("close", teardownEntry);
661
+ const unsubscribeClose = deps.on("close", onClose);
512
662
  if (deps.getSize() > 0) onOpen();
513
663
  return () => {
514
664
  unsubscribeOpen();
515
665
  unsubscribeClose();
516
- teardownEntry();
666
+ if (handle) {
667
+ popBackMarker(handle);
668
+ handle = null;
669
+ }
517
670
  };
518
671
  }
519
672
  function installRouteChange(deps) {
520
- if (typeof window === "undefined" || typeof history === "undefined") {
521
- return () => {
522
- };
523
- }
524
- const onChange = () => {
673
+ return subscribeRouteChange(() => {
525
674
  if (deps.isDestroyed() || deps.getSize() <= 0) return;
526
675
  void deps.close();
527
- };
528
- const wrap = (key) => {
529
- const original = history[key];
530
- const patched = function(...args) {
531
- original.apply(this, args);
532
- onChange();
533
- };
534
- history[key] = patched;
535
- return () => {
536
- if (history[key] === patched) {
537
- history[key] = original;
538
- }
539
- };
540
- };
541
- window.addEventListener("popstate", onChange);
542
- const restorePush = wrap("pushState");
543
- const restoreReplace = wrap("replaceState");
544
- return () => {
545
- window.removeEventListener("popstate", onChange);
546
- restorePush();
547
- restoreReplace();
548
- };
676
+ });
549
677
  }
550
678
 
551
679
  // src/core/features/content-swipe.ts
@@ -616,11 +744,15 @@ function installVisualViewport(deps) {
616
744
  if (clamp < deps.getMaxAxisSize()) {
617
745
  deps.setMaxAxisSize(clamp);
618
746
  }
747
+ const wasAnimating = deps.isAnimating?.() ?? false;
748
+ deps.cancelInFlight();
749
+ deps.newCycle();
619
750
  const max = deps.getMaxAxisSize();
620
751
  deps.setSize(Math.min(deps.getSize(), max));
621
752
  const current = deps.resolveActiveSnap();
622
753
  if (current && !deps.isDragging()) {
623
754
  deps.applySize(Math.min(current.size, max));
755
+ if (wasAnimating) deps.resyncAfterCancel?.();
624
756
  } else {
625
757
  deps.applySize(deps.getSize());
626
758
  }
@@ -761,6 +893,54 @@ function installFitObserver(deps) {
761
893
  };
762
894
  }
763
895
 
896
+ // src/core/features/max-height-controller.ts
897
+ function createMaxHeightController(deps) {
898
+ let maxHeightCap;
899
+ let maxHeightRaw;
900
+ const resolveCap = () => {
901
+ const raw = maxHeightRaw;
902
+ if (raw === void 0) {
903
+ maxHeightCap = void 0;
904
+ return;
905
+ }
906
+ if (typeof raw === "number") {
907
+ maxHeightCap = raw;
908
+ return;
909
+ }
910
+ if (typeof window === "undefined") return;
911
+ const measured = resolveSnap(raw, deps.mode);
912
+ maxHeightCap = measured > 0 ? measured : void 0;
913
+ };
914
+ const clampTo = () => {
915
+ if (maxHeightCap === void 0) return;
916
+ if (deps.getMaxAxisSize() > maxHeightCap) {
917
+ deps.setMaxAxisSize(maxHeightCap);
918
+ }
919
+ };
920
+ return {
921
+ setRadius(r) {
922
+ deps.element.style.setProperty(
923
+ "--bs-radius",
924
+ typeof r === "number" ? `${r}px` : r
925
+ );
926
+ },
927
+ setMaxHeight(h) {
928
+ const value = typeof h === "number" ? `${h}px` : h;
929
+ const axis = layoutAxis(deps.mode);
930
+ deps.element.style.setProperty(
931
+ axis === "height" ? "max-height" : "max-width",
932
+ value
933
+ );
934
+ maxHeightRaw = h;
935
+ resolveCap();
936
+ deps.recompute();
937
+ },
938
+ resolveCap,
939
+ clampTo,
940
+ getCap: () => maxHeightCap
941
+ };
942
+ }
943
+
764
944
  // src/core/features/fit-measurement.ts
765
945
  var measureSheetNatural = (element, content, vertical) => {
766
946
  if (!content) {
@@ -892,13 +1072,6 @@ var WriteSentinel = class {
892
1072
  }
893
1073
  };
894
1074
 
895
- // src/core/primitives/devWarn.ts
896
- function devWarn(...args) {
897
- if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
898
- console.warn(...args);
899
- }
900
- }
901
-
902
1075
  // src/core/primitives/overlay-position.ts
903
1076
  function resolveSheetAnchoredStyle(mode, position, inset) {
904
1077
  const sizeOffset = `calc(var(--bs-size, 0px) + ${inset})`;
@@ -2353,7 +2526,7 @@ var matchesRange = (def, progress) => {
2353
2526
  };
2354
2527
  function installScrimStages(deps, opts) {
2355
2528
  const doc = deps.host.ownerDocument;
2356
- const entries = opts.stages.map((def) => {
2529
+ const entries2 = opts.stages.map((def) => {
2357
2530
  const wrapper = doc.createElement("div");
2358
2531
  wrapper.className = "bs-scrim-stage";
2359
2532
  const ws = wrapper.style;
@@ -2374,9 +2547,9 @@ function installScrimStages(deps, opts) {
2374
2547
  const resolveActive = () => {
2375
2548
  const state2 = deps.getState();
2376
2549
  if (state2.size === 0) {
2377
- return entries.find((e) => matchesId(e.def, state2.activeId)) ?? null;
2550
+ return entries2.find((e) => matchesId(e.def, state2.activeId)) ?? null;
2378
2551
  }
2379
- return entries.find((e) => matchesId(e.def, state2.activeId)) ?? entries.find((e) => matchesRange(e.def, state2.progress)) ?? null;
2552
+ return entries2.find((e) => matchesId(e.def, state2.activeId)) ?? entries2.find((e) => matchesRange(e.def, state2.progress)) ?? null;
2380
2553
  };
2381
2554
  const hide = (entry, animate) => {
2382
2555
  entry.inFlight?.cancel();
@@ -2425,13 +2598,13 @@ function installScrimStages(deps, opts) {
2425
2598
  deps.on("open", () => update(true)),
2426
2599
  deps.on("close", () => update(true))
2427
2600
  ];
2428
- if (entries.some((e) => e.def.forRange)) {
2601
+ if (entries2.some((e) => e.def.forRange)) {
2429
2602
  offs.push(deps.on("progress", () => update(true)));
2430
2603
  }
2431
2604
  update(false);
2432
2605
  return () => {
2433
2606
  offs.forEach((off) => off());
2434
- for (const entry of entries) {
2607
+ for (const entry of entries2) {
2435
2608
  entry.inFlight?.cancel();
2436
2609
  entry.inFlight = null;
2437
2610
  if (entry.wrapper.parentNode) {
@@ -2544,8 +2717,7 @@ var BottomSheetEngine = class {
2544
2717
  __publicField(this, "disableCloseFlag");
2545
2718
  __publicField(this, "disableDragFlag");
2546
2719
  __publicField(this, "closeOnRouteChange");
2547
- __publicField(this, "maxHeightCap");
2548
- __publicField(this, "maxHeightRaw");
2720
+ __publicField(this, "maxHeight");
2549
2721
  __publicField(this, "snapPointsRaw");
2550
2722
  __publicField(this, "snaps");
2551
2723
  __publicField(this, "activeId");
@@ -2656,11 +2828,20 @@ var BottomSheetEngine = class {
2656
2828
  auditVhUsage(this.snapPointsRaw);
2657
2829
  this.auditDuplicateSnapIds(this.snapPointsRaw);
2658
2830
  this.rootEl = this.element.closest(".bs-root");
2831
+ this.maxHeight = createMaxHeightController({
2832
+ element: this.element,
2833
+ mode: this.mode,
2834
+ getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
2835
+ setMaxAxisSize: (size) => {
2836
+ this.snaps.setMaxAxisSize(size);
2837
+ },
2838
+ recompute: () => this.recompute()
2839
+ });
2659
2840
  this.fitDeps = {
2660
2841
  element: this.element,
2661
2842
  scrollContainer: this.scrollContainer,
2662
2843
  mode: this.mode,
2663
- getMaxHeightCap: () => this.maxHeightCap
2844
+ getMaxHeightCap: () => this.maxHeight.getCap()
2664
2845
  };
2665
2846
  this.snaps = new SnapResolver(
2666
2847
  this.snapPointsRaw,
@@ -2682,8 +2863,8 @@ var BottomSheetEngine = class {
2682
2863
  this.attach();
2683
2864
  this.registerInStack();
2684
2865
  if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
2685
- const io = new IntersectionObserver((entries) => {
2686
- for (const entry of entries) {
2866
+ const io = new IntersectionObserver((entries2) => {
2867
+ for (const entry of entries2) {
2687
2868
  if (!entry.isIntersecting) continue;
2688
2869
  if (this.destroyed) return;
2689
2870
  this.snaps.recompute();
@@ -2771,7 +2952,7 @@ var BottomSheetEngine = class {
2771
2952
  }
2772
2953
  use(plugin) {
2773
2954
  if (this.destroyed) {
2774
- console.warn(
2955
+ devWarn(
2775
2956
  `[BottomSheet] use("${plugin.name}") called on destroyed engine \u2014 ignored.`
2776
2957
  );
2777
2958
  return this;
@@ -2813,6 +2994,9 @@ var BottomSheetEngine = class {
2813
2994
  getAllowedIds() {
2814
2995
  return this.snaps.getAllowedIds().slice();
2815
2996
  }
2997
+ getResolvedSnaps() {
2998
+ return this.snaps.getResolvedSnaps();
2999
+ }
2816
3000
  async snapTo(id, velocityOrOpts = 0, _skipBeforeSnap = false) {
2817
3001
  if (this.destroyed) return;
2818
3002
  const opts = typeof velocityOrOpts === "object" ? velocityOrOpts : { velocity: velocityOrOpts };
@@ -2821,11 +3005,11 @@ var BottomSheetEngine = class {
2821
3005
  if (externalSignal?.aborted) return;
2822
3006
  const target = this.snaps.findById(id);
2823
3007
  if (!target) {
2824
- console.warn(`[BottomSheet] unknown snap id: ${id}`);
3008
+ devWarn(`[BottomSheet] unknown snap id: ${id}`);
2825
3009
  return;
2826
3010
  }
2827
3011
  if (!this.snaps.getAllowedIds().includes(id)) {
2828
- console.warn(`[BottomSheet] snap "${id}" is not in allowed list`);
3012
+ devWarn(`[BottomSheet] snap "${id}" is not in allowed list`);
2829
3013
  return;
2830
3014
  }
2831
3015
  if (!_skipBeforeSnap && this.emitBeforeSnap(target, this.activeId)) {
@@ -2957,42 +3141,11 @@ var BottomSheetEngine = class {
2957
3141
  }
2958
3142
  setRadius(r) {
2959
3143
  if (this.destroyed) return;
2960
- this.element.style.setProperty(
2961
- "--bs-radius",
2962
- typeof r === "number" ? `${r}px` : r
2963
- );
3144
+ this.maxHeight.setRadius(r);
2964
3145
  }
2965
3146
  setMaxHeight(h) {
2966
3147
  if (this.destroyed) return;
2967
- const value = typeof h === "number" ? `${h}px` : h;
2968
- const axis = layoutAxis(this.mode);
2969
- this.element.style.setProperty(
2970
- axis === "height" ? "max-height" : "max-width",
2971
- value
2972
- );
2973
- this.maxHeightRaw = h;
2974
- this.resolveMaxHeightCap();
2975
- this.recompute();
2976
- }
2977
- resolveMaxHeightCap() {
2978
- const raw = this.maxHeightRaw;
2979
- if (raw === void 0) {
2980
- this.maxHeightCap = void 0;
2981
- return;
2982
- }
2983
- if (typeof raw === "number") {
2984
- this.maxHeightCap = raw;
2985
- return;
2986
- }
2987
- if (typeof window === "undefined") return;
2988
- const measured = resolveSnap(raw, this.mode);
2989
- this.maxHeightCap = measured > 0 ? measured : void 0;
2990
- }
2991
- clampToMaxHeight() {
2992
- if (this.maxHeightCap === void 0) return;
2993
- if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
2994
- this.snaps.setMaxAxisSize(this.maxHeightCap);
2995
- }
3148
+ this.maxHeight.setMaxHeight(h);
2996
3149
  }
2997
3150
  setAllowed(ids, snap) {
2998
3151
  if (this.destroyed) return;
@@ -3080,7 +3233,7 @@ var BottomSheetEngine = class {
3080
3233
  };
3081
3234
  const host = this.screenComponent?.parentElement;
3082
3235
  if (!host) {
3083
- console.warn(
3236
+ devWarn(
3084
3237
  "[BottomSheet] setScrimStages: no scrim element mounted \u2014 pass `scrim` to the engine first."
3085
3238
  );
3086
3239
  return () => {
@@ -3130,9 +3283,9 @@ var BottomSheetEngine = class {
3130
3283
  }
3131
3284
  recompute() {
3132
3285
  if (this.destroyed) return;
3133
- this.resolveMaxHeightCap();
3286
+ this.maxHeight.resolveCap();
3134
3287
  this.snaps.recompute();
3135
- this.clampToMaxHeight();
3288
+ this.maxHeight.clampTo();
3136
3289
  this.scrim.invalidateOpacityCache();
3137
3290
  if (this.gesture?.isDragging) return;
3138
3291
  const current = this.snaps.findById(this.activeId);
@@ -3182,42 +3335,18 @@ var BottomSheetEngine = class {
3182
3335
  return this.currentAbort.signal;
3183
3336
  }
3184
3337
  emitBeforeSnap(target, previousId) {
3185
- let cancelled = false;
3186
- let frozen = false;
3187
- this.emit("before-snap", {
3188
- id: target.id,
3189
- size: target.size,
3190
- previousId,
3191
- cancel: () => {
3192
- if (frozen) {
3193
- console.warn(
3194
- "[BottomSheet] before-snap.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
3195
- );
3196
- return;
3197
- }
3198
- cancelled = true;
3199
- }
3200
- });
3201
- frozen = true;
3202
- return cancelled;
3338
+ return emitCancelable(
3339
+ (payload) => this.emit("before-snap", payload),
3340
+ { id: target.id, size: target.size, previousId },
3341
+ "before-snap"
3342
+ );
3203
3343
  }
3204
3344
  emitBeforeClose(reason) {
3205
- let cancelled = false;
3206
- let frozen = false;
3207
- this.emit("before-close", {
3208
- reason,
3209
- cancel: () => {
3210
- if (frozen) {
3211
- console.warn(
3212
- "[BottomSheet] before-close.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
3213
- );
3214
- return;
3215
- }
3216
- cancelled = true;
3217
- }
3218
- });
3219
- frozen = true;
3220
- return cancelled;
3345
+ return emitCancelable(
3346
+ (payload) => this.emit("before-close", payload),
3347
+ { reason },
3348
+ "before-close"
3349
+ );
3221
3350
  }
3222
3351
  applyAutoAriaLabelledBy() {
3223
3352
  if (typeof document === "undefined") return;
@@ -3232,16 +3361,16 @@ var BottomSheetEngine = class {
3232
3361
  this.element.setAttribute("aria-labelledby", titled.id);
3233
3362
  }
3234
3363
  recomputeSnaps() {
3235
- this.resolveMaxHeightCap();
3364
+ this.maxHeight.resolveCap();
3236
3365
  this.snaps.setRaw(this.snapPointsRaw);
3237
- this.clampToMaxHeight();
3366
+ this.maxHeight.clampTo();
3238
3367
  this.scrim.invalidateOpacityCache();
3239
3368
  }
3240
3369
  auditDuplicateSnapIds(points) {
3241
3370
  const seen = /* @__PURE__ */ new Set();
3242
3371
  for (const p of points) {
3243
3372
  if (seen.has(p.id)) {
3244
- console.warn(
3373
+ devWarn(
3245
3374
  `[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
3246
3375
  );
3247
3376
  }
@@ -3408,7 +3537,15 @@ var BottomSheetEngine = class {
3408
3537
  setSize: (size) => {
3409
3538
  this.size = size;
3410
3539
  },
3411
- applySize: (size) => this.applySize(size)
3540
+ applySize: (size) => this.applySize(size),
3541
+ cancelInFlight: () => {
3542
+ this.animation.cancel();
3543
+ },
3544
+ newCycle: () => {
3545
+ this.newCycle();
3546
+ },
3547
+ isAnimating: () => this.animation.isAnimating,
3548
+ resyncAfterCancel: () => this.resyncAfterResize()
3412
3549
  }));
3413
3550
  }
3414
3551
  this.teardowns.add(installSliderKeyboard({
@@ -3444,9 +3581,9 @@ var BottomSheetEngine = class {
3444
3581
  return;
3445
3582
  }
3446
3583
  if (this.emitBeforeSnap(target, previousId)) {
3447
- const restore = this.snaps.findById(previousId);
3448
- if (restore) {
3449
- void this.animation.animateTo(restore.size, 0);
3584
+ const restore2 = this.snaps.findById(previousId);
3585
+ if (restore2) {
3586
+ void this.animation.animateTo(restore2.size, 0);
3450
3587
  }
3451
3588
  return;
3452
3589
  }
@@ -3684,12 +3821,12 @@ function createBottomSheet(opts) {
3684
3821
  getEngine: () => engine
3685
3822
  };
3686
3823
  }
3687
- var root_1 = $2.from_html(`<div class="bs-backdrop" aria-hidden="true"></div>`);
3688
- var root_3 = $2.from_html(`<div class="bs-header"><!></div>`);
3689
- var root_5 = $2.from_html(`<div class="bs-footer"><!></div>`);
3690
- var root_6 = $2.from_html(`<div class="bs-button-slot" data-side="left"><!></div>`);
3691
- var root_7 = $2.from_html(`<div class="bs-button-slot" data-side="right"><!></div>`);
3692
- var root = $2.from_html(`<div class="bs-root"><!> <div class="bs-screen"><!></div> <section class="bs-sheet" role="dialog"><div class="bs-handle" role="slider" tabindex="0" aria-label="Resize sheet" aria-valuemin="0" aria-valuemax="0" aria-valuenow="0"></div> <!> <div class="bs-content" tabindex="0" role="region" aria-label="Sheet content"><!></div> <!> <span class="bs-sr-only" role="status" aria-live="polite"> </span></section> <!> <!></div>`);
3824
+ var root = $2.from_html(`<div class="bs-backdrop" aria-hidden="true"></div>`);
3825
+ var root_1 = $2.from_html(`<div class="bs-header"><!></div>`);
3826
+ var root_2 = $2.from_html(`<div class="bs-footer"><!></div>`);
3827
+ var root_3 = $2.from_html(`<div class="bs-button-slot" data-side="left"><!></div>`);
3828
+ var root_4 = $2.from_html(`<div class="bs-button-slot" data-side="right"><!></div>`);
3829
+ var root_5 = $2.from_html(`<div class="bs-root"><!> <div class="bs-screen"><!></div> <section class="bs-sheet" role="dialog"><div class="bs-handle" role="slider" tabindex="0" aria-label="Resize sheet" aria-valuemin="0" aria-valuemax="0" aria-valuenow="0"></div> <!> <div class="bs-content" tabindex="0" role="region" aria-label="Sheet content"><!></div> <!> <span class="bs-sr-only" role="status" aria-live="polite"> </span></section> <!> <!></div>`);
3693
3830
  function BottomSheet($$anchor, $$props) {
3694
3831
  $2.push($$props, true);
3695
3832
  let mode = $2.prop($$props, "mode", 3, "bottom"), animation = $2.prop($$props, "animation", 3, "spring"), focusTrap = $2.prop($$props, "focusTrap", 3, false), closeOnEscape = $2.prop($$props, "closeOnEscape", 3, true), closeOnBack = $2.prop($$props, "closeOnBack", 3, false), lockBodyScroll2 = $2.prop($$props, "lockBodyScroll", 3, true), rubberBand2 = $2.prop($$props, "rubberBand", 3, true), backdrop = $2.prop($$props, "backdrop", 3, true), closeOnBackdrop = $2.prop($$props, "closeOnBackdrop", 3, true), persistent = $2.prop($$props, "persistent", 3, false), disableClose = $2.prop($$props, "disableClose", 3, false), disableDrag = $2.prop($$props, "disableDrag", 3, false), closeOnRouteChange = $2.prop($$props, "closeOnRouteChange", 3, false), stackEffect = $2.prop($$props, "stackEffect", 3, false), teleport = $2.prop($$props, "teleport", 3, false), openProp = $2.prop($$props, "open", 15), snap = $2.prop($$props, "snap", 15), ariaLabel = $2.prop($$props, "ariaLabel", 3, "Bottom sheet");
@@ -3773,6 +3910,8 @@ function BottomSheet($$anchor, $$props) {
3773
3910
  sync();
3774
3911
  $$props.ondragend?.();
3775
3912
  });
3913
+ if ($$props.ondrag) engine.on("drag", (payload) => $$props.ondrag(payload));
3914
+ if ($$props.onprogress) engine.on("progress", (payload) => $$props.onprogress(payload));
3776
3915
  });
3777
3916
  onDestroy(() => {
3778
3917
  restoreTeleport?.();
@@ -3869,11 +4008,11 @@ function BottomSheet($$anchor, $$props) {
3869
4008
  getState,
3870
4009
  getEngine
3871
4010
  };
3872
- var div = root();
4011
+ var div = root_5();
3873
4012
  var node = $2.child(div);
3874
4013
  {
3875
4014
  var consequent = ($$anchor2) => {
3876
- var div_1 = root_1();
4015
+ var div_1 = root();
3877
4016
  $2.bind_this(div_1, ($$value) => $2.set(backdropEl, $$value), () => $2.get(backdropEl));
3878
4017
  $2.delegated("click", div_1, function(...$$args) {
3879
4018
  (closeOnBackdrop() ? () => {
@@ -3907,7 +4046,7 @@ function BottomSheet($$anchor, $$props) {
3907
4046
  var node_3 = $2.sibling(div_3, 2);
3908
4047
  {
3909
4048
  var consequent_2 = ($$anchor2) => {
3910
- var div_4 = root_3();
4049
+ var div_4 = root_1();
3911
4050
  var node_4 = $2.child(div_4);
3912
4051
  $2.snippet(node_4, () => $$props.header, () => $2.get(viewState));
3913
4052
  $2.reset(div_4);
@@ -3935,7 +4074,7 @@ function BottomSheet($$anchor, $$props) {
3935
4074
  var node_7 = $2.sibling(div_5, 2);
3936
4075
  {
3937
4076
  var consequent_4 = ($$anchor2) => {
3938
- var div_6 = root_5();
4077
+ var div_6 = root_2();
3939
4078
  var node_8 = $2.child(div_6);
3940
4079
  $2.snippet(node_8, () => $$props.footer, () => $2.get(viewState));
3941
4080
  $2.reset(div_6);
@@ -3953,7 +4092,7 @@ function BottomSheet($$anchor, $$props) {
3953
4092
  var node_9 = $2.sibling(section, 2);
3954
4093
  {
3955
4094
  var consequent_5 = ($$anchor2) => {
3956
- var div_7 = root_6();
4095
+ var div_7 = root_3();
3957
4096
  var node_10 = $2.child(div_7);
3958
4097
  $2.snippet(node_10, () => $$props.leftButton);
3959
4098
  $2.reset(div_7);
@@ -3967,7 +4106,7 @@ function BottomSheet($$anchor, $$props) {
3967
4106
  var node_11 = $2.sibling(node_9, 2);
3968
4107
  {
3969
4108
  var consequent_6 = ($$anchor2) => {
3970
- var div_8 = root_7();
4109
+ var div_8 = root_4();
3971
4110
  var node_12 = $2.child(div_8);
3972
4111
  $2.snippet(node_12, () => $$props.rightButton);
3973
4112
  $2.reset(div_8);