@surdeddd/bottom-sheet 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/{BottomSheetEngine-CAymrH-P.d.cts → BottomSheetEngine-BJrH7qY3.d.cts} +39 -3
  2. package/dist/{BottomSheetEngine-DcqcuudN.d.ts → BottomSheetEngine-L05jGZvU.d.ts} +39 -3
  3. package/dist/element.cjs +490 -91
  4. package/dist/element.d.cts +23 -4
  5. package/dist/element.d.ts +23 -4
  6. package/dist/element.iife.global.js +2 -2
  7. package/dist/element.js +490 -91
  8. package/dist/index.cjs +347 -80
  9. package/dist/index.d.cts +3 -2
  10. package/dist/index.d.ts +3 -2
  11. package/dist/index.js +347 -80
  12. package/dist/integrations/formik.d.cts +1 -1
  13. package/dist/integrations/formik.d.ts +1 -1
  14. package/dist/integrations/react-hook-form.d.cts +1 -1
  15. package/dist/integrations/react-hook-form.d.ts +1 -1
  16. package/dist/overlay.cjs +13 -2
  17. package/dist/overlay.js +13 -2
  18. package/dist/preact.d.cts +1 -1
  19. package/dist/preact.d.ts +1 -1
  20. package/dist/qwik.cjs +358 -81
  21. package/dist/qwik.d.cts +4 -2
  22. package/dist/qwik.d.ts +4 -2
  23. package/dist/qwik.js +358 -81
  24. package/dist/react.cjs +451 -89
  25. package/dist/react.d.cts +29 -4
  26. package/dist/react.d.ts +29 -4
  27. package/dist/react.js +451 -89
  28. package/dist/solid.cjs +347 -80
  29. package/dist/solid.d.cts +38 -2
  30. package/dist/solid.d.ts +38 -2
  31. package/dist/solid.js +347 -80
  32. package/dist/solid.source.jsx +347 -80
  33. package/dist/styles.css +68 -55
  34. package/dist/svelte-core.cjs +352 -80
  35. package/dist/svelte-core.js +352 -80
  36. package/dist/svelte-src/BottomSheet.svelte +113 -15
  37. package/dist/svelte.cjs +474 -133
  38. package/dist/svelte.d.cts +21 -0
  39. package/dist/svelte.d.ts +21 -0
  40. package/dist/svelte.js +474 -133
  41. package/dist/vue.cjs +610 -109
  42. package/dist/vue.d.cts +51 -2
  43. package/dist/vue.d.ts +51 -2
  44. package/dist/vue.js +611 -110
  45. package/package.json +8 -8
package/dist/vue.cjs CHANGED
@@ -39,6 +39,15 @@ var SheetStack = class {
39
39
  size() {
40
40
  return this.entries.length;
41
41
  }
42
+ depthOf(id) {
43
+ const open = [];
44
+ for (const entry of this.entries) {
45
+ if (!entry.isOpen || entry.isOpen()) open.push(entry);
46
+ }
47
+ const idx = open.findIndex((e) => e.id === id);
48
+ if (idx === -1) return 0;
49
+ return open.length - 1 - idx;
50
+ }
42
51
  clear() {
43
52
  this.entries = [];
44
53
  }
@@ -157,7 +166,9 @@ var PERCENT = /^(-?\d+(?:\.\d+)?)%$/;
157
166
  var resolveSnap = (point, mode, measureFit) => {
158
167
  if (typeof point === "number") return Math.max(0, point);
159
168
  if (point === "full") return viewportSize(mode);
160
- if (point === "fit") return Math.max(0, measureFit?.() ?? 0);
169
+ if (point === "fit" || point === "content") {
170
+ return Math.max(0, measureFit?.() ?? 0);
171
+ }
161
172
  const pctMatch = point.match(PERCENT);
162
173
  if (pctMatch) {
163
174
  const pct = parseFloat(pctMatch[1]) / 100;
@@ -394,6 +405,42 @@ function notifyLinkedSheets(sheets, self) {
394
405
  }
395
406
 
396
407
  // src/core/features/route.ts
408
+ var closers = [];
409
+ var handlerInstalled = false;
410
+ var suppress = 0;
411
+ var ensureHandler = () => {
412
+ if (handlerInstalled || typeof window === "undefined") return;
413
+ handlerInstalled = true;
414
+ window.addEventListener("popstate", () => {
415
+ if (suppress > 0) {
416
+ suppress -= 1;
417
+ return;
418
+ }
419
+ let target = null;
420
+ for (let i = closers.length - 1; i >= 0; i -= 1) {
421
+ const c = closers[i];
422
+ if (!c.isOpen()) continue;
423
+ if (!target) target = c;
424
+ if (c.isTop()) {
425
+ target = c;
426
+ break;
427
+ }
428
+ }
429
+ if (!target) return;
430
+ target.consumed = true;
431
+ const idx = closers.indexOf(target);
432
+ if (idx !== -1) closers.splice(idx, 1);
433
+ target.close();
434
+ });
435
+ };
436
+ var programmaticBack = () => {
437
+ suppress += 1;
438
+ try {
439
+ history.back();
440
+ } catch {
441
+ suppress = Math.max(0, suppress - 1);
442
+ }
443
+ };
397
444
  function installRoute(deps) {
398
445
  if (typeof window === "undefined") {
399
446
  return () => {
@@ -403,82 +450,81 @@ function installRoute(deps) {
403
450
  return () => {
404
451
  };
405
452
  }
406
- let routePushed = false;
407
- let closeOnBackPushed = false;
408
- let detachPopstate = null;
409
- const popOurMarker = (key, expected) => {
410
- const state = history.state;
411
- if (state && state[key] === expected) {
412
- try {
413
- history.back();
414
- } catch {
415
- }
453
+ let pushed = false;
454
+ let closer = null;
455
+ const teardownEntry = () => {
456
+ if (closer) {
457
+ const idx = closers.indexOf(closer);
458
+ if (idx !== -1) closers.splice(idx, 1);
459
+ }
460
+ const wasConsumed = closer?.consumed ?? false;
461
+ closer = null;
462
+ if (pushed && !wasConsumed) {
463
+ pushed = false;
464
+ programmaticBack();
465
+ } else {
466
+ pushed = false;
416
467
  }
417
468
  };
418
469
  const onOpen = () => {
419
- if (deps.routedTo && !detachPopstate) {
420
- const target = deps.routedTo;
421
- try {
422
- history.pushState({ __bsRouted: target }, "", target);
423
- routePushed = true;
424
- } catch {
425
- }
426
- const onPop = (event) => {
427
- if (deps.isDestroyed()) return;
428
- const state = event.state;
429
- if ((!state || state.__bsRouted !== target) && deps.getSize() > 0) {
430
- routePushed = false;
431
- void deps.close();
432
- }
433
- };
434
- window.addEventListener("popstate", onPop);
435
- detachPopstate = () => window.removeEventListener("popstate", onPop);
436
- } else if (deps.closeOnBack && !detachPopstate) {
437
- try {
470
+ if (closer) return;
471
+ closer = {
472
+ isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
473
+ isTop: () => deps.isTopSheet(),
474
+ close: () => void deps.close(),
475
+ consumed: false
476
+ };
477
+ ensureHandler();
478
+ closers.push(closer);
479
+ try {
480
+ if (deps.routedTo !== void 0) {
481
+ history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
482
+ } else {
438
483
  history.pushState({ __bsSheet: deps.sheetId }, "");
439
- closeOnBackPushed = true;
440
- } catch {
441
484
  }
442
- const onPop = () => {
443
- if (deps.isDestroyed()) return;
444
- if (deps.getSize() > 0 && deps.isTopSheet()) {
445
- const state = history.state;
446
- if (state?.__bsSheet !== deps.sheetId) closeOnBackPushed = false;
447
- void deps.close();
448
- }
449
- };
450
- window.addEventListener("popstate", onPop);
451
- detachPopstate = () => window.removeEventListener("popstate", onPop);
452
- }
453
- };
454
- const onClose = () => {
455
- detachPopstate?.();
456
- detachPopstate = null;
457
- if (routePushed) {
458
- routePushed = false;
459
- if (deps.routedTo !== void 0) popOurMarker("__bsRouted", deps.routedTo);
460
- }
461
- if (closeOnBackPushed) {
462
- closeOnBackPushed = false;
463
- popOurMarker("__bsSheet", deps.sheetId);
485
+ pushed = true;
486
+ } catch {
487
+ pushed = false;
464
488
  }
465
489
  };
466
490
  const unsubscribeOpen = deps.on("open", onOpen);
467
- const unsubscribeClose = deps.on("close", onClose);
491
+ const unsubscribeClose = deps.on("close", teardownEntry);
468
492
  if (deps.getSize() > 0) onOpen();
469
493
  return () => {
470
494
  unsubscribeOpen();
471
495
  unsubscribeClose();
472
- detachPopstate?.();
473
- detachPopstate = null;
474
- if (routePushed) {
475
- routePushed = false;
476
- if (deps.routedTo !== void 0) popOurMarker("__bsRouted", deps.routedTo);
477
- }
478
- if (closeOnBackPushed) {
479
- closeOnBackPushed = false;
480
- popOurMarker("__bsSheet", deps.sheetId);
481
- }
496
+ teardownEntry();
497
+ };
498
+ }
499
+ function installRouteChange(deps) {
500
+ if (typeof window === "undefined" || typeof history === "undefined") {
501
+ return () => {
502
+ };
503
+ }
504
+ const onChange = () => {
505
+ if (deps.isDestroyed() || deps.getSize() <= 0) return;
506
+ void deps.close();
507
+ };
508
+ const wrap = (key) => {
509
+ const original = history[key];
510
+ const patched = function(...args) {
511
+ original.apply(this, args);
512
+ onChange();
513
+ };
514
+ history[key] = patched;
515
+ return () => {
516
+ if (history[key] === patched) {
517
+ history[key] = original;
518
+ }
519
+ };
520
+ };
521
+ window.addEventListener("popstate", onChange);
522
+ const restorePush = wrap("pushState");
523
+ const restoreReplace = wrap("replaceState");
524
+ return () => {
525
+ window.removeEventListener("popstate", onChange);
526
+ restorePush();
527
+ restoreReplace();
482
528
  };
483
529
  }
484
530
 
@@ -786,6 +832,7 @@ function applyOverlayPosition(ws, mode, position, inset) {
786
832
 
787
833
  // src/core/controllers/scrim-controller.ts
788
834
  var VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
835
+ var DEFAULT_SCRIM_DIM = "rgba(0, 0, 0, 0.4)";
789
836
  var ScrimController = class {
790
837
  constructor(deps, opts) {
791
838
  __publicField(this, "screenComponent");
@@ -824,9 +871,11 @@ var ScrimController = class {
824
871
  this.backdropRange = opts.backdropRange ?? preset?.range ?? [0, 1];
825
872
  this.screenRange = opts.screenRange ?? preset?.range ?? [0, 1];
826
873
  this.scrimTapToCloseEnabled = opts.scrimTapToClose ?? false;
874
+ const explicitColor = opts.scrimColor ?? preset?.color;
875
+ const effectiveColor = explicitColor ?? (this.scrimMode !== "off" && !this.backdrop ? DEFAULT_SCRIM_DIM : void 0);
827
876
  if (this.screenComponent) {
828
877
  this.applyScrimStyles({
829
- color: opts.scrimColor ?? preset?.color,
878
+ color: effectiveColor,
830
879
  blur: opts.scrimBlur ?? preset?.blur,
831
880
  interactive: opts.scrimInteractive ?? preset?.interactive ?? false
832
881
  });
@@ -1600,7 +1649,7 @@ var LifecycleController = class {
1600
1649
  this.releaseScrollLock = null;
1601
1650
  this.inertSiblings.remove();
1602
1651
  if (this.returnFocus) {
1603
- const target = typeof this.returnFocus === "function" ? this.returnFocus() : this.returnFocus;
1652
+ const target = typeof this.returnFocus === "function" ? this.returnFocus() : typeof this.returnFocus === "string" ? typeof document !== "undefined" ? document.querySelector(this.returnFocus) : null : this.returnFocus;
1604
1653
  target?.focus?.();
1605
1654
  }
1606
1655
  }
@@ -1767,6 +1816,7 @@ var GestureController = class {
1767
1816
  __publicField(this, "dragStartSize", 0);
1768
1817
  __publicField(this, "currentPointerKind", "touch");
1769
1818
  __publicField(this, "keyboardDismissed", false);
1819
+ __publicField(this, "dragSuppressed", false);
1770
1820
  __publicField(this, "dragPayload", { size: 0, delta: 0 });
1771
1821
  this.deps = deps;
1772
1822
  }
@@ -1777,6 +1827,11 @@ var GestureController = class {
1777
1827
  if (this.detach) return this.detach;
1778
1828
  this.detach = installGestures(this.deps.handle, this.deps.mode, {
1779
1829
  onStart: (_coord, kind) => {
1830
+ if (this.deps.getDisableDrag?.()) {
1831
+ this.dragSuppressed = true;
1832
+ return;
1833
+ }
1834
+ this.dragSuppressed = false;
1780
1835
  this.deps.cancelAnimation();
1781
1836
  this.isDragging_ = true;
1782
1837
  this.dragStartSize = this.deps.getDragContext().size;
@@ -1787,6 +1842,7 @@ var GestureController = class {
1787
1842
  this.deps.emit("dragstart", { size: this.dragStartSize });
1788
1843
  },
1789
1844
  onMove: (delta) => {
1845
+ if (this.dragSuppressed) return;
1790
1846
  const ctx = this.deps.getDragContext();
1791
1847
  const { min, max } = ctx.range;
1792
1848
  const maxAxis = ctx.maxAxisSize;
@@ -1810,6 +1866,10 @@ var GestureController = class {
1810
1866
  }
1811
1867
  },
1812
1868
  onEnd: (delta, velocity, kind) => {
1869
+ if (this.dragSuppressed) {
1870
+ this.dragSuppressed = false;
1871
+ return;
1872
+ }
1813
1873
  this.isDragging_ = false;
1814
1874
  this.keyboardDismissed = false;
1815
1875
  this.deps.getRoot()?.removeAttribute("data-dragging");
@@ -1820,6 +1880,10 @@ var GestureController = class {
1820
1880
  this.deps.settleAfterDrag(delta, velocity, kind);
1821
1881
  },
1822
1882
  onCancel: () => {
1883
+ if (this.dragSuppressed) {
1884
+ this.dragSuppressed = false;
1885
+ return;
1886
+ }
1823
1887
  this.isDragging_ = false;
1824
1888
  this.keyboardDismissed = false;
1825
1889
  this.deps.getRoot()?.removeAttribute("data-dragging");
@@ -2199,6 +2263,12 @@ function resolveEngineOptions(opts, extras) {
2199
2263
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2200
2264
  rubberBandEnabled: opts.rubberBand ?? true,
2201
2265
  closeOnBack: opts.closeOnBack ?? false,
2266
+ persistent: opts.persistent ?? false,
2267
+ disableClose: opts.disableClose ?? false,
2268
+ disableDrag: opts.disableDrag ?? false,
2269
+ closeOnRouteChange: opts.closeOnRouteChange ?? false,
2270
+ radius: opts.radius,
2271
+ maxHeight: opts.maxHeight,
2202
2272
  initialAllowed,
2203
2273
  initialId,
2204
2274
  scrim: {
@@ -2225,7 +2295,8 @@ function resolveEngineOptions(opts, extras) {
2225
2295
  closeOnEscape: opts.closeOnEscape,
2226
2296
  lockBodyScroll: opts.lockBodyScroll,
2227
2297
  inertSiblings: opts.inertSiblings,
2228
- shouldApplyInertSiblings: extras?.shouldApplyInertSiblings
2298
+ shouldApplyInertSiblings: extras?.shouldApplyInertSiblings,
2299
+ returnFocus: opts.returnFocusTo
2229
2300
  }
2230
2301
  };
2231
2302
  }
@@ -2270,6 +2341,11 @@ var BottomSheetEngine = class {
2270
2341
  __publicField(this, "lifecycle");
2271
2342
  __publicField(this, "closeOnBack");
2272
2343
  __publicField(this, "routedTo");
2344
+ __publicField(this, "persistent");
2345
+ __publicField(this, "disableCloseFlag");
2346
+ __publicField(this, "disableDragFlag");
2347
+ __publicField(this, "closeOnRouteChange");
2348
+ __publicField(this, "maxHeightCap");
2273
2349
  __publicField(this, "snapPointsRaw");
2274
2350
  __publicField(this, "snaps");
2275
2351
  __publicField(this, "activeId");
@@ -2282,6 +2358,7 @@ var BottomSheetEngine = class {
2282
2358
  __publicField(this, "sizeWriteSentinel", new WriteSentinel());
2283
2359
  __publicField(this, "progressWriteSentinel", new WriteSentinel());
2284
2360
  __publicField(this, "isTopSheet", true);
2361
+ __publicField(this, "opening", false);
2285
2362
  __publicField(this, "progressPayload", {
2286
2363
  value: 0,
2287
2364
  size: 0
@@ -2338,7 +2415,8 @@ var BottomSheetEngine = class {
2338
2415
  void this.snapTo(id);
2339
2416
  },
2340
2417
  close: () => {
2341
- void this.close();
2418
+ if (!this.canDismiss()) return;
2419
+ void this.close("backdrop");
2342
2420
  }
2343
2421
  },
2344
2422
  resolved.scrim
@@ -2362,6 +2440,10 @@ var BottomSheetEngine = class {
2362
2440
  );
2363
2441
  this.closeOnBack = resolved.closeOnBack;
2364
2442
  this.routedTo = opts.routedTo;
2443
+ this.persistent = resolved.persistent;
2444
+ this.disableCloseFlag = resolved.disableClose;
2445
+ this.disableDragFlag = resolved.disableDrag;
2446
+ this.closeOnRouteChange = resolved.closeOnRouteChange;
2365
2447
  this.stackEffectEnabled = opts.stackEffect ?? false;
2366
2448
  this.snapPointsRaw = opts.snapPoints;
2367
2449
  this.persistKey = opts.persistKey;
@@ -2375,7 +2457,7 @@ var BottomSheetEngine = class {
2375
2457
  this.snapPointsRaw,
2376
2458
  resolved.initialAllowed,
2377
2459
  this.mode,
2378
- () => layoutAxis(this.mode) === "width" ? this.handle.offsetWidth : this.handle.offsetHeight,
2460
+ () => this.measureFitSize(),
2379
2461
  (maxAxisSize) => {
2380
2462
  this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
2381
2463
  }
@@ -2409,6 +2491,19 @@ var BottomSheetEngine = class {
2409
2491
  io.observe(this.element);
2410
2492
  this.teardowns.add(() => io.disconnect());
2411
2493
  }
2494
+ this.installFitObserver();
2495
+ if (resolved.radius !== void 0) this.setRadius(resolved.radius);
2496
+ if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
2497
+ this.applyAutoAriaLabelledBy();
2498
+ if (this.closeOnRouteChange) {
2499
+ this.teardowns.add(
2500
+ installRouteChange({
2501
+ isDestroyed: () => this.destroyed,
2502
+ getSize: () => this.size,
2503
+ close: () => this.close()
2504
+ })
2505
+ );
2506
+ }
2412
2507
  if (this.persistKey) {
2413
2508
  this.teardowns.add(installPersist(this, this.persistKey));
2414
2509
  }
@@ -2433,7 +2528,7 @@ var BottomSheetEngine = class {
2433
2528
  isTopSheet: () => this.isTopSheet,
2434
2529
  getSize: () => this.size,
2435
2530
  isDestroyed: () => this.destroyed,
2436
- close: () => this.close(),
2531
+ close: () => this.close("back"),
2437
2532
  on: (event, fn) => this.on(event, fn),
2438
2533
  sheetId: this.id
2439
2534
  })
@@ -2527,6 +2622,10 @@ var BottomSheetEngine = class {
2527
2622
  const previousSize = this.size;
2528
2623
  this.scrollCache.cache(previousId, previousSize, target.size);
2529
2624
  this.activeId = id;
2625
+ if (wasClosed && target.size > 0) {
2626
+ this.opening = true;
2627
+ sheetStack.promote(this.id);
2628
+ }
2530
2629
  if (this.animation.viewTransitionsAvailable) {
2531
2630
  this.currentViewTransition?.skipTransition?.();
2532
2631
  const vt = document.startViewTransition(() => {
@@ -2541,19 +2640,26 @@ var BottomSheetEngine = class {
2541
2640
  } else {
2542
2641
  await this.animation.animateTo(target.size, velocityPxPerMs);
2543
2642
  }
2643
+ this.opening = false;
2544
2644
  externalSignal?.removeEventListener("abort", onExternalAbort);
2545
2645
  if (signal.aborted) return;
2546
2646
  this.scrollCache.restore(id, previousSize, target.size);
2547
2647
  this.updateAriaSlider();
2548
- this.emit("snap", { id, size: target.size });
2648
+ this.emit("snap", {
2649
+ id,
2650
+ size: target.size,
2651
+ progress: this.computeProgress(target.size)
2652
+ });
2549
2653
  if (wasClosed && target.size > 0) {
2550
2654
  this.emit("open", { id });
2551
2655
  this.handleOpen();
2552
2656
  notifyLinkedSheets(this.linkedSheets, this);
2657
+ this.emit("opened", { id });
2553
2658
  }
2554
2659
  if (target.size === 0) {
2555
2660
  this.emit("close", void 0);
2556
2661
  this.handleClose();
2662
+ this.emit("closed", void 0);
2557
2663
  }
2558
2664
  }
2559
2665
  async dragTo(targetSize, velocityOrOpts = 0) {
@@ -2578,11 +2684,74 @@ var BottomSheetEngine = class {
2578
2684
  const target = id ?? this.snaps.getAllowedIds().find((a) => a !== "closed") ?? this.activeId;
2579
2685
  return this.snapTo(target);
2580
2686
  }
2581
- close() {
2687
+ close(reason = "programmatic") {
2582
2688
  if (this.destroyed) return Promise.resolve();
2689
+ if (this.disableCloseFlag) return Promise.resolve();
2690
+ if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
2583
2691
  const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
2584
2692
  return this.snapTo(closedId ?? this.activeId);
2585
2693
  }
2694
+ canDismiss() {
2695
+ return !this.persistent && !this.disableCloseFlag && !this.destroyed;
2696
+ }
2697
+ isTop() {
2698
+ return this.isTopSheet;
2699
+ }
2700
+ depth() {
2701
+ return sheetStack.depthOf(this.id);
2702
+ }
2703
+ expand() {
2704
+ if (this.destroyed) return Promise.resolve();
2705
+ const ids = this.allowedIdsBySize();
2706
+ const target = ids[ids.length - 1];
2707
+ if (!target) return Promise.resolve();
2708
+ return this.snapTo(target);
2709
+ }
2710
+ collapse() {
2711
+ if (this.destroyed) return Promise.resolve();
2712
+ const ids = this.allowedIdsBySize();
2713
+ const nonZero = ids.find((id) => (this.snaps.findById(id)?.size ?? 0) > 0);
2714
+ const target = nonZero ?? ids[0];
2715
+ if (!target) return Promise.resolve();
2716
+ return this.snapTo(target);
2717
+ }
2718
+ setRadius(r) {
2719
+ if (this.destroyed) return;
2720
+ this.element.style.setProperty(
2721
+ "--bs-radius",
2722
+ typeof r === "number" ? `${r}px` : r
2723
+ );
2724
+ }
2725
+ setMaxHeight(h) {
2726
+ if (this.destroyed) return;
2727
+ const value = typeof h === "number" ? `${h}px` : h;
2728
+ const axis = layoutAxis(this.mode);
2729
+ this.element.style.setProperty(
2730
+ axis === "height" ? "maxHeight" : "maxWidth",
2731
+ value
2732
+ );
2733
+ if (typeof h === "number") {
2734
+ this.maxHeightCap = h;
2735
+ this.clampToMaxHeight();
2736
+ } else if (typeof window !== "undefined") {
2737
+ const probe2 = document.createElement("div");
2738
+ probe2.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;${axis === "height" ? "height" : "width"}:${value};`;
2739
+ document.body.appendChild(probe2);
2740
+ const measured = axis === "height" ? probe2.offsetHeight : probe2.offsetWidth;
2741
+ probe2.remove();
2742
+ this.maxHeightCap = measured > 0 ? measured : void 0;
2743
+ this.clampToMaxHeight();
2744
+ }
2745
+ }
2746
+ clampToMaxHeight() {
2747
+ if (this.maxHeightCap === void 0) return;
2748
+ if (this.snaps.getMaxAxisSize() > this.maxHeightCap) {
2749
+ this.snaps.setMaxAxisSize(this.maxHeightCap);
2750
+ }
2751
+ if (this.size > this.maxHeightCap && !this.gesture?.isDragging) {
2752
+ this.applySize(this.maxHeightCap);
2753
+ }
2754
+ }
2586
2755
  setAllowed(ids, snap) {
2587
2756
  if (this.destroyed) return;
2588
2757
  this.snaps.setAllowedIds(ids);
@@ -2716,8 +2885,53 @@ var BottomSheetEngine = class {
2716
2885
  }
2717
2886
  this.updateAriaSlider();
2718
2887
  }
2888
+ recompute() {
2889
+ if (this.destroyed) return;
2890
+ this.snaps.recompute();
2891
+ this.scrim.invalidateOpacityCache();
2892
+ if (this.gesture?.isDragging) return;
2893
+ const current = this.snaps.findById(this.activeId);
2894
+ if (current) {
2895
+ this.size = current.size;
2896
+ this.applySize(this.size);
2897
+ this.updateAriaSlider();
2898
+ }
2899
+ }
2900
+ measureFitSize() {
2901
+ const vertical = layoutAxis(this.mode) === "height";
2902
+ const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
2903
+ const content = this.scrollContainer;
2904
+ const natural = content ? handleSize + (vertical ? content.scrollHeight : content.scrollWidth) : handleSize;
2905
+ if (typeof window === "undefined") return natural;
2906
+ const viewport = vertical ? window.innerHeight : window.innerWidth;
2907
+ return viewport > 0 ? Math.min(natural, viewport) : natural;
2908
+ }
2909
+ installFitObserver() {
2910
+ if (typeof ResizeObserver === "undefined") return;
2911
+ if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
2912
+ return;
2913
+ const targets = [this.handle];
2914
+ if (this.scrollContainer && this.scrollContainer !== this.handle) {
2915
+ targets.push(this.scrollContainer);
2916
+ }
2917
+ let raf = 0;
2918
+ const ro = new ResizeObserver(() => {
2919
+ if (raf) return;
2920
+ raf = requestAnimationFrame(() => {
2921
+ raf = 0;
2922
+ if (this.destroyed || this.gesture?.isDragging) return;
2923
+ this.recompute();
2924
+ });
2925
+ });
2926
+ for (const t of targets) ro.observe(t);
2927
+ this.teardowns.add(() => {
2928
+ ro.disconnect();
2929
+ if (raf) cancelAnimationFrame(raf);
2930
+ });
2931
+ }
2719
2932
  destroy() {
2720
2933
  this.destroyed = true;
2934
+ this.opening = false;
2721
2935
  this.currentAbort.abort();
2722
2936
  this.currentViewTransition?.skipTransition?.();
2723
2937
  this.currentViewTransition = null;
@@ -2767,6 +2981,36 @@ var BottomSheetEngine = class {
2767
2981
  frozen = true;
2768
2982
  return cancelled;
2769
2983
  }
2984
+ emitBeforeClose(reason) {
2985
+ let cancelled = false;
2986
+ let frozen = false;
2987
+ this.emit("before-close", {
2988
+ reason,
2989
+ cancel: () => {
2990
+ if (frozen) {
2991
+ console.warn(
2992
+ "[BottomSheet] before-close.cancel() called asynchronously \u2014 ignored. cancel() must be invoked synchronously inside the listener."
2993
+ );
2994
+ return;
2995
+ }
2996
+ cancelled = true;
2997
+ }
2998
+ });
2999
+ frozen = true;
3000
+ return cancelled;
3001
+ }
3002
+ applyAutoAriaLabelledBy() {
3003
+ if (typeof document === "undefined") return;
3004
+ if (!this.lifecycle.focusTrapEnabled) return;
3005
+ if (this.element.getAttribute("aria-labelledby")) return;
3006
+ const scope = this.handle ?? this.element;
3007
+ const titled = scope.querySelector("[data-bs-title]") ?? scope.querySelector("h1,h2,h3,h4,h5,h6");
3008
+ if (!titled) return;
3009
+ if (!titled.id) {
3010
+ titled.id = nextInstanceId("bs-title");
3011
+ }
3012
+ this.element.setAttribute("aria-labelledby", titled.id);
3013
+ }
2770
3014
  recomputeSnaps() {
2771
3015
  const seen = /* @__PURE__ */ new Set();
2772
3016
  for (const p of this.snapPointsRaw) {
@@ -2802,11 +3046,8 @@ var BottomSheetEngine = class {
2802
3046
  },
2803
3047
  setIsTop: (isTop) => {
2804
3048
  this.isTopSheet = isTop;
2805
- if (this.backdrop) {
2806
- this.backdrop.style.display = isTop ? "" : "none";
2807
- }
2808
3049
  },
2809
- isOpen: () => this.size > 0,
3050
+ isOpen: () => this.size > 0 || this.opening,
2810
3051
  setDepth: (depth) => this.applyStackDepth(depth)
2811
3052
  }));
2812
3053
  }
@@ -2838,6 +3079,7 @@ var BottomSheetEngine = class {
2838
3079
  buf.rubberBandEnabled = this.rubberBandEnabled;
2839
3080
  return buf;
2840
3081
  },
3082
+ getDisableDrag: () => this.disableDragFlag,
2841
3083
  cancelAnimation: () => this.animation.cancel(),
2842
3084
  applySize: (size) => this.applySize(size),
2843
3085
  animateTo: (size, velocity) => this.animation.animateTo(size, velocity),
@@ -2917,8 +3159,9 @@ var BottomSheetEngine = class {
2917
3159
  if (this.lifecycle.closeOnEscape) {
2918
3160
  const onKey = (e) => {
2919
3161
  if (this.destroyed || e.defaultPrevented) return;
3162
+ if (!this.canDismiss()) return;
2920
3163
  if (e.key === "Escape" && this.isTopSheet && this.size > 0) {
2921
- void this.close();
3164
+ void this.close("escape");
2922
3165
  }
2923
3166
  };
2924
3167
  document.addEventListener("keydown", onKey);
@@ -2981,20 +3224,31 @@ var BottomSheetEngine = class {
2981
3224
  const previousSnapSize = this.snaps.findById(previousId)?.size;
2982
3225
  this.scrollCache.cache(previousId, previousSize, target.size);
2983
3226
  this.activeId = target.id;
3227
+ if (previousSnapSize === 0 && target.size > 0) {
3228
+ this.opening = true;
3229
+ sheetStack.promote(this.id);
3230
+ }
2984
3231
  void this.animation.animateTo(target.size, velocity).then(() => {
3232
+ this.opening = false;
2985
3233
  if (signal.aborted) return;
2986
3234
  this.scrollCache.restore(target.id, previousSize, target.size);
2987
3235
  this.updateAriaSlider();
2988
- this.emit("snap", { id: target.id, size: target.size });
3236
+ this.emit("snap", {
3237
+ id: target.id,
3238
+ size: target.size,
3239
+ progress: this.computeProgress(target.size)
3240
+ });
2989
3241
  this.haptic();
2990
3242
  if (previousSnapSize === 0 && target.size > 0) {
2991
3243
  this.emit("open", { id: target.id });
2992
3244
  this.handleOpen();
2993
3245
  notifyLinkedSheets(this.linkedSheets, this);
3246
+ this.emit("opened", { id: target.id });
2994
3247
  }
2995
3248
  if (target.size === 0) {
2996
3249
  this.emit("close", void 0);
2997
3250
  this.handleClose();
3251
+ this.emit("closed", void 0);
2998
3252
  }
2999
3253
  });
3000
3254
  }
@@ -3019,6 +3273,9 @@ var BottomSheetEngine = class {
3019
3273
  if (this.anchorHost && this.anchorHost !== this.scrimParent) {
3020
3274
  this.anchorHost.style.setProperty("--bs-size", `${size}px`);
3021
3275
  }
3276
+ if (this.rootEl && this.rootEl !== this.scrimParent && this.rootEl !== this.anchorHost) {
3277
+ this.rootEl.style.setProperty("--bs-size", `${size}px`);
3278
+ }
3022
3279
  }
3023
3280
  const progress = this.computeProgress(size);
3024
3281
  const progressChanged = this.progressWriteSentinel.shouldWrite(
@@ -3030,6 +3287,9 @@ var BottomSheetEngine = class {
3030
3287
  if (this.anchorHost) {
3031
3288
  this.anchorHost.style.setProperty("--bs-progress", String(progress));
3032
3289
  }
3290
+ if (this.rootEl && this.rootEl !== this.anchorHost) {
3291
+ this.rootEl.style.setProperty("--bs-progress", String(progress));
3292
+ }
3033
3293
  }
3034
3294
  this.scrim.applyOpacity(progress, progressChanged);
3035
3295
  if (progressChanged && this.bus.listenerCount("progress") > 0) {
@@ -3063,17 +3323,24 @@ var BottomSheetEngine = class {
3063
3323
  const target = this.snaps.findById(this.activeId);
3064
3324
  if (!target) return;
3065
3325
  this.updateAriaSlider();
3066
- this.emit("snap", { id: target.id, size: target.size });
3326
+ this.emit("snap", {
3327
+ id: target.id,
3328
+ size: target.size,
3329
+ progress: this.computeProgress(target.size)
3330
+ });
3067
3331
  if (target.size > 0 && !this.lifecycle.isInstalled) {
3068
3332
  this.emit("open", { id: target.id });
3069
3333
  this.handleOpen();
3070
3334
  notifyLinkedSheets(this.linkedSheets, this);
3335
+ this.emit("opened", { id: target.id });
3071
3336
  } else if (target.size === 0 && this.lifecycle.isInstalled) {
3072
3337
  this.emit("close", void 0);
3073
3338
  this.handleClose();
3339
+ this.emit("closed", void 0);
3074
3340
  }
3075
3341
  }
3076
3342
  handleClose() {
3343
+ this.opening = false;
3077
3344
  this.lifecycle.release();
3078
3345
  sheetStack.update();
3079
3346
  }
@@ -3138,7 +3405,7 @@ function useBottomSheet(opts) {
3138
3405
  state,
3139
3406
  snapTo: (id) => engine?.snapTo(id) ?? Promise.resolve(),
3140
3407
  open: (id) => engine?.open(id) ?? Promise.resolve(),
3141
- close: () => engine?.close() ?? Promise.resolve(),
3408
+ close: (reason) => engine?.close(reason) ?? Promise.resolve(),
3142
3409
  setAllowed: (ids, snap) => engine?.setAllowed(ids, snap),
3143
3410
  setSnapPoints: (points, allowed) => engine?.setSnapPoints(points, allowed),
3144
3411
  setScrim: (opts2) => engine?.setScrim(opts2),
@@ -3148,6 +3415,16 @@ function useBottomSheet(opts) {
3148
3415
  }),
3149
3416
  setScrimStages: (opts2) => engine?.setScrimStages(opts2) ?? (() => {
3150
3417
  }),
3418
+ recompute: () => engine?.recompute(),
3419
+ setScrimColor: (color) => engine?.setScrimColor(color),
3420
+ setBackdropRange: (range) => engine?.setBackdropRange(range),
3421
+ setRadius: (r) => engine?.setRadius(r),
3422
+ setMaxHeight: (h) => engine?.setMaxHeight(h),
3423
+ expand: () => engine?.expand() ?? Promise.resolve(),
3424
+ collapse: () => engine?.collapse() ?? Promise.resolve(),
3425
+ isTop: () => engine?.isTop() ?? false,
3426
+ depth: () => engine?.depth() ?? 0,
3427
+ canDismiss: () => engine?.canDismiss() ?? false,
3151
3428
  on: (event, fn) => {
3152
3429
  if (engine) return engine.on(event, fn);
3153
3430
  const entry = {
@@ -3283,6 +3560,35 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3283
3560
  type: Boolean,
3284
3561
  required: false
3285
3562
  },
3563
+ persistent: {
3564
+ type: Boolean,
3565
+ required: false
3566
+ },
3567
+ disableClose: {
3568
+ type: Boolean,
3569
+ required: false
3570
+ },
3571
+ disableDrag: {
3572
+ type: Boolean,
3573
+ required: false
3574
+ },
3575
+ closeOnRouteChange: {
3576
+ type: Boolean,
3577
+ required: false
3578
+ },
3579
+ radius: {
3580
+ type: [String, Number],
3581
+ required: false
3582
+ },
3583
+ maxHeight: {
3584
+ type: [String, Number],
3585
+ required: false
3586
+ },
3587
+ returnFocusTo: {
3588
+ type: [String, Function],
3589
+ required: false,
3590
+ skipCheck: true
3591
+ },
3286
3592
  persistKey: {
3287
3593
  type: String,
3288
3594
  required: false
@@ -3333,22 +3639,159 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3333
3639
  type: String,
3334
3640
  required: false,
3335
3641
  default: "Bottom sheet"
3642
+ },
3643
+ open: {
3644
+ type: Boolean,
3645
+ required: false
3646
+ },
3647
+ snap: {
3648
+ type: null,
3649
+ required: false
3650
+ },
3651
+ teleport: {
3652
+ type: Boolean,
3653
+ required: false,
3654
+ default: true
3655
+ },
3656
+ teleportTo: {
3657
+ type: null,
3658
+ required: false,
3659
+ default: "body"
3660
+ },
3661
+ anchors: {
3662
+ type: Array,
3663
+ required: false
3664
+ },
3665
+ scrimStages: {
3666
+ type: [Object, null],
3667
+ required: false
3668
+ },
3669
+ backdropColor: {
3670
+ type: String,
3671
+ required: false
3672
+ },
3673
+ backdropOpacity: {
3674
+ type: Number,
3675
+ required: false
3336
3676
  }
3337
3677
  },
3338
3678
  emits: [
3339
3679
  "change",
3340
3680
  "snap",
3341
3681
  "open",
3342
- "close"
3682
+ "close",
3683
+ "opened",
3684
+ "closed",
3685
+ "before-close",
3686
+ "drag-start",
3687
+ "drag-end",
3688
+ "update:open",
3689
+ "update:snap"
3343
3690
  ],
3344
3691
  setup(__props, { expose: __expose, emit: __emit }) {
3345
3692
  const props = __props;
3346
3693
  const emit = __emit;
3347
- const { sheetRef, handleRef, contentRef, backdropRef, screenRef, state, snapTo, open, close, setAllowed, setSnapPoints, setScrim, setScrimOverlay, on, getEngine } = useBottomSheet(props);
3694
+ const { sheetRef, handleRef, contentRef, backdropRef, screenRef, state, snapTo, open, close, setAllowed, setSnapPoints, setScrim, setScrimOverlay, addAnchor, setScrimStages, recompute, setScrimColor, setBackdropRange, setRadius, setMaxHeight, expand, collapse, isTop, depth, canDismiss, on, getEngine } = useBottomSheet(props);
3348
3695
  vue.watch(() => ({ ...state }), (next) => emit("change", next), { deep: false });
3349
- on("snap", (payload) => emit("snap", payload.id));
3350
- on("open", (payload) => emit("open", payload.id));
3351
- on("close", () => emit("close"));
3696
+ on("snap", (payload) => {
3697
+ emit("snap", payload.id);
3698
+ emit("update:snap", payload.id);
3699
+ });
3700
+ on("open", (payload) => {
3701
+ emit("open", payload.id);
3702
+ emit("update:open", true);
3703
+ });
3704
+ on("close", () => {
3705
+ emit("close");
3706
+ emit("update:open", false);
3707
+ });
3708
+ on("opened", (payload) => emit("opened", payload.id));
3709
+ on("closed", () => emit("closed"));
3710
+ on("before-close", (payload) => emit("before-close", payload));
3711
+ on("dragstart", (payload) => emit("drag-start", payload));
3712
+ on("dragend", (payload) => emit("drag-end", payload));
3713
+ vue.watch(() => props.open, (next) => {
3714
+ if (next === void 0) return;
3715
+ const isOpen = state.size > 0;
3716
+ if (next && !isOpen) void open();
3717
+ else if (!next && isOpen) void close();
3718
+ });
3719
+ vue.watch(() => props.snap, (next) => {
3720
+ if (next === void 0 || next === state.activeId) return;
3721
+ void snapTo(next);
3722
+ });
3723
+ vue.watch(() => props.backdropColor, (next) => {
3724
+ if (next === void 0) return;
3725
+ setScrimColor(next);
3726
+ });
3727
+ vue.watch(() => props.backdropOpacity, (next) => {
3728
+ if (next === void 0) return;
3729
+ setBackdropRange([0, next]);
3730
+ });
3731
+ vue.watch(() => props.radius, (next) => {
3732
+ if (next === void 0) return;
3733
+ setRadius(next);
3734
+ });
3735
+ vue.watch(() => props.maxHeight, (next) => {
3736
+ if (next === void 0) return;
3737
+ setMaxHeight(next);
3738
+ });
3739
+ const mounted = vue.ref(false);
3740
+ const anchorHosts = vue.shallowRef({});
3741
+ const anchorDetachers = vue.ref([]);
3742
+ let stagesDetach = null;
3743
+ const teardownAnchors = () => {
3744
+ anchorDetachers.value.forEach((d) => d());
3745
+ anchorDetachers.value = [];
3746
+ anchorHosts.value = {};
3747
+ };
3748
+ const buildAnchors = () => {
3749
+ teardownAnchors();
3750
+ const engine = getEngine();
3751
+ if (!engine || !props.anchors?.length) return;
3752
+ const hosts = {};
3753
+ const detachers = [];
3754
+ for (const a of props.anchors) {
3755
+ const host = document.createElement("div");
3756
+ hosts[a.id] = host;
3757
+ const { id: _id, ...rest } = a;
3758
+ detachers.push(engine.addAnchor({
3759
+ ...rest,
3760
+ element: host
3761
+ }));
3762
+ }
3763
+ anchorHosts.value = hosts;
3764
+ anchorDetachers.value = detachers;
3765
+ };
3766
+ const anchorsKey = vue.computed(() => JSON.stringify((props.anchors ?? []).map((a) => [
3767
+ a.id,
3768
+ a.position,
3769
+ a.inset,
3770
+ Array.isArray(a.showOn) ? a.showOn : a.showOn ? "fn" : null,
3771
+ a.fadeRange,
3772
+ a.interactive,
3773
+ typeof a.animation === "string" ? a.animation : a.animation ? "x" : null
3774
+ ])));
3775
+ const applyStages = () => {
3776
+ stagesDetach?.();
3777
+ stagesDetach = null;
3778
+ const engine = getEngine();
3779
+ if (!engine || !props.scrimStages) return;
3780
+ stagesDetach = engine.setScrimStages(props.scrimStages);
3781
+ };
3782
+ vue.onMounted(() => {
3783
+ mounted.value = true;
3784
+ buildAnchors();
3785
+ applyStages();
3786
+ vue.watch(anchorsKey, buildAnchors);
3787
+ vue.watch(() => props.scrimStages, applyStages, { deep: true });
3788
+ if (props.open && state.size === 0) void open();
3789
+ });
3790
+ vue.onBeforeUnmount(() => {
3791
+ teardownAnchors();
3792
+ stagesDetach?.();
3793
+ stagesDetach = null;
3794
+ });
3352
3795
  const isVerticalAxis = vue.computed(() => {
3353
3796
  const mode = props.mode ?? "bottom";
3354
3797
  return mode === "bottom" || mode === "top";
@@ -3367,6 +3810,18 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3367
3810
  setSnapPoints,
3368
3811
  setScrim,
3369
3812
  setScrimOverlay,
3813
+ addAnchor,
3814
+ setScrimStages,
3815
+ recompute,
3816
+ setScrimColor,
3817
+ setBackdropRange,
3818
+ setRadius,
3819
+ setMaxHeight,
3820
+ expand,
3821
+ collapse,
3822
+ isTop,
3823
+ depth,
3824
+ canDismiss,
3370
3825
  on,
3371
3826
  getEngine,
3372
3827
  state: vue.readonly(state)
@@ -3387,8 +3842,33 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3387
3842
  setSnapPoints,
3388
3843
  setScrim,
3389
3844
  setScrimOverlay,
3845
+ addAnchor,
3846
+ setScrimStages,
3847
+ recompute,
3848
+ setScrimColor,
3849
+ setBackdropRange,
3850
+ setRadius,
3851
+ setMaxHeight,
3852
+ expand,
3853
+ collapse,
3854
+ isTop,
3855
+ depth,
3856
+ canDismiss,
3390
3857
  on,
3391
3858
  getEngine,
3859
+ mounted,
3860
+ anchorHosts,
3861
+ anchorDetachers,
3862
+ get stagesDetach() {
3863
+ return stagesDetach;
3864
+ },
3865
+ set stagesDetach(v) {
3866
+ stagesDetach = v;
3867
+ },
3868
+ teardownAnchors,
3869
+ buildAnchors,
3870
+ anchorsKey,
3871
+ applyStages,
3392
3872
  isVerticalAxis,
3393
3873
  allowedIds,
3394
3874
  activeIdx,
@@ -3413,36 +3893,35 @@ var _hoisted_3 = [
3413
3893
  "aria-modal",
3414
3894
  "aria-label"
3415
3895
  ];
3416
- var _hoisted_4 = {
3417
- key: 0,
3418
- class: "bs-button-slot",
3419
- "data-side": "left"
3420
- };
3421
- var _hoisted_5 = {
3422
- key: 1,
3423
- class: "bs-button-slot",
3424
- "data-side": "right"
3425
- };
3426
- var _hoisted_6 = [
3896
+ var _hoisted_4 = [
3427
3897
  "aria-orientation",
3428
3898
  "aria-valuemax",
3429
3899
  "aria-valuenow",
3430
3900
  "aria-valuetext"
3431
3901
  ];
3432
- var _hoisted_7 = {
3902
+ var _hoisted_5 = {
3433
3903
  ref: "contentRef",
3434
3904
  class: "bs-content",
3435
3905
  tabindex: "0",
3436
3906
  role: "region",
3437
3907
  "aria-label": "Sheet content"
3438
3908
  };
3439
- var _hoisted_8 = {
3909
+ var _hoisted_6 = {
3910
+ key: 0,
3911
+ class: "bs-footer"
3912
+ };
3913
+ var _hoisted_7 = {
3440
3914
  class: "bs-sr-only",
3441
3915
  role: "status",
3442
3916
  "aria-live": "polite"
3443
3917
  };
3918
+ var _hoisted_8 = ["data-mode"];
3919
+ var _hoisted_9 = ["data-mode"];
3444
3920
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
3445
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
3921
+ return vue.openBlock(), vue.createBlock(vue.Teleport, {
3922
+ to: $props.teleportTo,
3923
+ disabled: !$props.teleport || !$setup.mounted
3924
+ }, [vue.createElementVNode("div", _hoisted_1, [
3446
3925
  $props.backdrop ? (vue.openBlock(), vue.createElementBlock(
3447
3926
  "div",
3448
3927
  {
@@ -3450,13 +3929,12 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
3450
3929
  ref: "backdropRef",
3451
3930
  class: "bs-backdrop",
3452
3931
  "aria-hidden": "true",
3453
- onClick: _cache[0] || (_cache[0] = ($event) => $props.closeOnBackdrop ? $setup.close() : void 0)
3932
+ onClick: _cache[0] || (_cache[0] = ($event) => $props.closeOnBackdrop && $setup.canDismiss() ? $setup.close("backdrop") : void 0)
3454
3933
  },
3455
3934
  null,
3456
3935
  512
3457
3936
  /* NEED_PATCH */
3458
3937
  )) : vue.createCommentVNode("v-if", true),
3459
- vue.createCommentVNode("\n Scrim surface always renders so the engine can host scrim presets\n (color/blur via setScrim), overlay injections (setScrimOverlay),\n and progress-driven opacity. The `screen` slot, when used, renders\n inside as user content. Without a slot it stays an empty positioning\n context.\n "),
3460
3938
  vue.createElementVNode(
3461
3939
  "div",
3462
3940
  _hoisted_2,
@@ -3473,8 +3951,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
3473
3951
  "aria-modal": $setup.ariaModal ? "true" : void 0,
3474
3952
  "aria-label": $props.ariaLabel
3475
3953
  }, [
3476
- _ctx.$slots["button-left"] ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4, [vue.renderSlot(_ctx.$slots, "button-left")])) : vue.createCommentVNode("v-if", true),
3477
- _ctx.$slots["button-right"] ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, [vue.renderSlot(_ctx.$slots, "button-right")])) : vue.createCommentVNode("v-if", true),
3478
3954
  vue.createElementVNode("div", {
3479
3955
  ref: "handleRef",
3480
3956
  class: "bs-handle",
@@ -3486,23 +3962,48 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
3486
3962
  "aria-valuenow": $setup.activeIdx,
3487
3963
  "aria-valuetext": $setup.state.activeId,
3488
3964
  "aria-label": "Resize sheet"
3489
- }, [vue.renderSlot(_ctx.$slots, "header", { state: $setup.state })], 8, _hoisted_6),
3965
+ }, [vue.renderSlot(_ctx.$slots, "header", { state: $setup.state })], 8, _hoisted_4),
3490
3966
  vue.createElementVNode(
3491
3967
  "div",
3492
- _hoisted_7,
3968
+ _hoisted_5,
3493
3969
  [vue.renderSlot(_ctx.$slots, "default")],
3494
3970
  512
3495
3971
  /* NEED_PATCH */
3496
3972
  ),
3973
+ _ctx.$slots.footer ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_6, [vue.renderSlot(_ctx.$slots, "footer", { state: $setup.state })])) : vue.createCommentVNode("v-if", true),
3497
3974
  vue.createElementVNode(
3498
3975
  "span",
3499
- _hoisted_8,
3976
+ _hoisted_7,
3500
3977
  vue.toDisplayString($setup.state.activeId),
3501
3978
  1
3502
3979
  /* TEXT */
3503
3980
  )
3504
- ], 8, _hoisted_3)
3505
- ]);
3981
+ ], 8, _hoisted_3),
3982
+ _ctx.$slots["button-left"] ? (vue.openBlock(), vue.createElementBlock("div", {
3983
+ key: 1,
3984
+ class: "bs-button-slot",
3985
+ "data-side": "left",
3986
+ "data-mode": $setup.props.mode ?? "bottom"
3987
+ }, [vue.renderSlot(_ctx.$slots, "button-left")], 8, _hoisted_8)) : vue.createCommentVNode("v-if", true),
3988
+ _ctx.$slots["button-right"] ? (vue.openBlock(), vue.createElementBlock("div", {
3989
+ key: 2,
3990
+ class: "bs-button-slot",
3991
+ "data-side": "right",
3992
+ "data-mode": $setup.props.mode ?? "bottom"
3993
+ }, [vue.renderSlot(_ctx.$slots, "button-right")], 8, _hoisted_9)) : vue.createCommentVNode("v-if", true)
3994
+ ]), (vue.openBlock(true), vue.createElementBlock(
3995
+ vue.Fragment,
3996
+ null,
3997
+ vue.renderList($setup.props.anchors ?? [], (a) => {
3998
+ return vue.openBlock(), vue.createBlock(vue.Teleport, {
3999
+ key: a.id,
4000
+ to: $setup.anchorHosts[a.id],
4001
+ disabled: !$setup.anchorHosts[a.id]
4002
+ }, [vue.renderSlot(_ctx.$slots, `anchor-${a.id}`, { state: $setup.state })], 8, ["to", "disabled"]);
4003
+ }),
4004
+ 128
4005
+ /* KEYED_FRAGMENT */
4006
+ ))], 8, ["to", "disabled"]);
3506
4007
  }
3507
4008
  var BottomSheet_default = /* @__PURE__ */ export_helper_default(_sfc_main, [["render", _sfc_render], ["__file", "/home/runner/work/BottomSheet/BottomSheet/src/vue/BottomSheet.vue"]]);
3508
4009