@surdeddd/bottom-sheet 0.8.2 → 0.9.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 (46) hide show
  1. package/dist/{BottomSheetEngine-7BDK2OWX.d.cts → BottomSheetEngine-BcyruNP1.d.cts} +12 -6
  2. package/dist/{BottomSheetEngine-BFTb0-4Z.d.ts → BottomSheetEngine-CBRcBwV-.d.ts} +12 -6
  3. package/dist/element.cjs +530 -349
  4. package/dist/element.d.cts +2 -1
  5. package/dist/element.d.ts +2 -1
  6. package/dist/element.iife.global.js +2 -2
  7. package/dist/element.js +530 -349
  8. package/dist/index.cjs +438 -294
  9. package/dist/index.d.cts +3 -3
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.js +438 -294
  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 +160 -96
  17. package/dist/overlay.d.cts +2 -0
  18. package/dist/overlay.d.ts +2 -0
  19. package/dist/overlay.js +160 -96
  20. package/dist/preact.d.cts +1 -1
  21. package/dist/preact.d.ts +1 -1
  22. package/dist/qwik.cjs +387 -211
  23. package/dist/qwik.d.cts +4 -3
  24. package/dist/qwik.d.ts +4 -3
  25. package/dist/qwik.js +387 -211
  26. package/dist/react.cjs +472 -296
  27. package/dist/react.d.cts +3 -2
  28. package/dist/react.d.ts +3 -2
  29. package/dist/react.js +472 -296
  30. package/dist/solid.cjs +417 -215
  31. package/dist/solid.d.cts +21 -7
  32. package/dist/solid.d.ts +21 -7
  33. package/dist/solid.js +417 -215
  34. package/dist/solid.source.jsx +412 -209
  35. package/dist/svelte-core.cjs +328 -209
  36. package/dist/svelte-core.js +328 -209
  37. package/dist/svelte-src/BottomSheet.svelte +56 -0
  38. package/dist/svelte.cjs +365 -210
  39. package/dist/svelte.d.cts +4 -0
  40. package/dist/svelte.d.ts +4 -0
  41. package/dist/svelte.js +365 -210
  42. package/dist/vue.cjs +358 -211
  43. package/dist/vue.d.cts +6 -0
  44. package/dist/vue.d.ts +6 -0
  45. package/dist/vue.js +358 -211
  46. package/package.json +6 -6
package/dist/solid.js CHANGED
@@ -265,18 +265,25 @@ var SnapResolver = class {
265
265
  __publicField(this, "resolved", []);
266
266
  __publicField(this, "maxAxisSize", 0);
267
267
  __publicField(this, "rangeCache", null);
268
+ __publicField(this, "notified", false);
268
269
  this.raw = raw;
269
270
  this.allowedIds = allowed ?? raw.map((p) => p.id);
270
271
  this.recompute();
271
272
  }
272
273
  recompute() {
273
- this.resolved = resolveSnapList(this.raw, this.mode, this.measureFit);
274
- this.maxAxisSize = this.resolved.reduce(
274
+ const measure = this.measureFit;
275
+ let measured;
276
+ const measureOnce = measure ? () => measured ?? (measured = measure()) : void 0;
277
+ this.resolved = resolveSnapList(this.raw, this.mode, measureOnce);
278
+ const nextMax = this.resolved.reduce(
275
279
  (m, s) => s.size > m ? s.size : m,
276
280
  0
277
281
  );
278
282
  this.rangeCache = null;
279
- this.onMaxAxisSizeChange?.(this.maxAxisSize);
283
+ const changed = nextMax !== this.maxAxisSize || !this.notified;
284
+ this.maxAxisSize = nextMax;
285
+ this.notified = true;
286
+ if (changed) this.onMaxAxisSizeChange?.(this.maxAxisSize);
280
287
  }
281
288
  setRaw(raw) {
282
289
  this.raw = raw;
@@ -429,7 +436,10 @@ var ensureHandler = () => {
429
436
  target.consumed = true;
430
437
  const idx = closers.indexOf(target);
431
438
  if (idx !== -1) closers.splice(idx, 1);
432
- target.close();
439
+ const settled = target;
440
+ void Promise.resolve(settled.close()).then(() => {
441
+ if (settled.isOpen()) settled.restore();
442
+ });
433
443
  });
434
444
  };
435
445
  var programmaticBack = () => {
@@ -465,16 +475,7 @@ function installRoute(deps) {
465
475
  pushed = false;
466
476
  }
467
477
  };
468
- const onOpen = () => {
469
- if (closer) return;
470
- closer = {
471
- isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
472
- isTop: () => deps.isTopSheet(),
473
- close: () => void deps.close(),
474
- consumed: false
475
- };
476
- ensureHandler();
477
- closers.push(closer);
478
+ const pushEntry = () => {
478
479
  try {
479
480
  if (deps.routedTo !== void 0) {
480
481
  history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
@@ -486,6 +487,25 @@ function installRoute(deps) {
486
487
  pushed = false;
487
488
  }
488
489
  };
490
+ const onOpen = () => {
491
+ if (closer) return;
492
+ const self = {
493
+ isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
494
+ isTop: () => deps.isTopSheet(),
495
+ close: () => deps.close(),
496
+ restore: () => {
497
+ if (deps.isDestroyed() || closer !== self) return;
498
+ self.consumed = false;
499
+ if (!closers.includes(self)) closers.push(self);
500
+ pushEntry();
501
+ },
502
+ consumed: false
503
+ };
504
+ closer = self;
505
+ ensureHandler();
506
+ closers.push(self);
507
+ pushEntry();
508
+ };
489
509
  const unsubscribeOpen = deps.on("open", onOpen);
490
510
  const unsubscribeClose = deps.on("close", teardownEntry);
491
511
  if (deps.getSize() > 0) onOpen();
@@ -532,11 +552,13 @@ var CONTENT_PULL_THRESHOLD = 60;
532
552
  function installContentSwipe(deps) {
533
553
  const { container } = deps;
534
554
  let startY = 0;
555
+ let startScrollTop = 0;
535
556
  let moved = false;
536
557
  const onTouchStart = (e) => {
537
558
  const t = e.touches[0];
538
559
  if (!t) return;
539
560
  startY = t.clientY;
561
+ startScrollTop = container.scrollTop;
540
562
  moved = false;
541
563
  };
542
564
  const onTouchMove = (e) => {
@@ -547,6 +569,7 @@ function installContentSwipe(deps) {
547
569
  const onTouchEnd = (e) => {
548
570
  if (!moved) return;
549
571
  if (deps.isDragging() || deps.isAnimating()) return;
572
+ if (container.scrollTop !== startScrollTop) return;
550
573
  const t = e.changedTouches[0];
551
574
  if (!t) return;
552
575
  const deltaY = t.clientY - startY;
@@ -658,6 +681,131 @@ function installResizeObserver(deps) {
658
681
  };
659
682
  }
660
683
 
684
+ // src/core/features/fit-observer.ts
685
+ var contentTargets = (scroller) => {
686
+ if (!scroller) return [];
687
+ const hasSlot = typeof HTMLSlotElement !== "undefined";
688
+ const out = [];
689
+ for (const child of Array.from(scroller.children)) {
690
+ if (hasSlot && child instanceof HTMLSlotElement) {
691
+ for (const el of child.assignedElements()) out.push(el);
692
+ } else {
693
+ out.push(child);
694
+ }
695
+ }
696
+ return out;
697
+ };
698
+ function installFitObserver(deps) {
699
+ if (typeof ResizeObserver === "undefined") return () => {
700
+ };
701
+ if (!deps.hasFitSnap()) return () => {
702
+ };
703
+ let raf = 0;
704
+ const schedule = () => {
705
+ if (raf) return;
706
+ raf = requestAnimationFrame(() => {
707
+ raf = 0;
708
+ if (deps.isDestroyed() || deps.isDragging()) return;
709
+ deps.recompute();
710
+ });
711
+ };
712
+ const ro = new ResizeObserver(schedule);
713
+ ro.observe(deps.handle);
714
+ const scroller = deps.scrollContainer;
715
+ const observed = /* @__PURE__ */ new Set();
716
+ const slots = /* @__PURE__ */ new Set();
717
+ const hasSlot = typeof HTMLSlotElement !== "undefined";
718
+ const onSlotChange = () => resync();
719
+ const trackSlots = () => {
720
+ if (!scroller || !hasSlot) return;
721
+ for (const child of Array.from(scroller.children)) {
722
+ if (child instanceof HTMLSlotElement && !slots.has(child)) {
723
+ child.addEventListener("slotchange", onSlotChange);
724
+ slots.add(child);
725
+ }
726
+ }
727
+ };
728
+ const resync = () => {
729
+ trackSlots();
730
+ const targets = contentTargets(scroller);
731
+ for (const el of observed) {
732
+ if (!targets.includes(el)) {
733
+ ro.unobserve(el);
734
+ observed.delete(el);
735
+ }
736
+ }
737
+ for (const el of targets) {
738
+ if (!observed.has(el)) {
739
+ ro.observe(el);
740
+ observed.add(el);
741
+ }
742
+ }
743
+ schedule();
744
+ };
745
+ let mo;
746
+ if (scroller) {
747
+ resync();
748
+ if (typeof MutationObserver !== "undefined") {
749
+ mo = new MutationObserver(resync);
750
+ mo.observe(scroller, { childList: true });
751
+ }
752
+ }
753
+ return () => {
754
+ ro.disconnect();
755
+ mo?.disconnect();
756
+ for (const slot of slots) {
757
+ slot.removeEventListener("slotchange", onSlotChange);
758
+ }
759
+ if (raf) cancelAnimationFrame(raf);
760
+ };
761
+ }
762
+
763
+ // src/core/features/fit-measurement.ts
764
+ var measureSheetNatural = (element, content, vertical) => {
765
+ if (!content) {
766
+ return vertical ? element.offsetHeight : element.offsetWidth;
767
+ }
768
+ const axis = vertical ? "height" : "width";
769
+ const sheetStyle = element.style;
770
+ const cs = content.style;
771
+ const prevSheet = sheetStyle[axis];
772
+ const prevFlex = cs.flex;
773
+ const prevContent = vertical ? cs.height : cs.width;
774
+ sheetStyle[axis] = "auto";
775
+ cs.flex = "none";
776
+ if (vertical) cs.height = "auto";
777
+ else cs.width = "auto";
778
+ const poked = vertical ? element.offsetHeight : element.offsetWidth;
779
+ const contentBox = vertical ? content.clientHeight : content.clientWidth;
780
+ const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
781
+ const natural = Math.max(poked, poked - contentBox + contentScroll);
782
+ sheetStyle[axis] = prevSheet;
783
+ cs.flex = prevFlex;
784
+ if (vertical) cs.height = prevContent;
785
+ else cs.width = prevContent;
786
+ return natural;
787
+ };
788
+ var containingExtent = (element, vertical) => {
789
+ const op = element.offsetParent;
790
+ if (op && op !== document.body && op !== document.documentElement) {
791
+ return vertical ? op.clientHeight : op.clientWidth;
792
+ }
793
+ return vertical ? window.innerHeight : window.innerWidth;
794
+ };
795
+ var measureFitSize = (deps) => {
796
+ const vertical = layoutAxis(deps.mode) === "height";
797
+ const natural = measureSheetNatural(
798
+ deps.element,
799
+ deps.scrollContainer,
800
+ vertical
801
+ );
802
+ const cap = deps.getMaxHeightCap();
803
+ const capped = cap !== void 0 ? Math.min(natural, cap) : natural;
804
+ if (typeof window === "undefined") return capped;
805
+ const viewport = containingExtent(deps.element, vertical);
806
+ return viewport > 0 ? Math.min(capped, viewport) : capped;
807
+ };
808
+
661
809
  // src/core/features/slider-keyboard.ts
662
810
  function installSliderKeyboard(deps) {
663
811
  const isVerticalAxis = deps.mode === "bottom" || deps.mode === "top";
@@ -1144,6 +1292,9 @@ var ScrimController = class {
1144
1292
  const s = this.screenComponent.style;
1145
1293
  s.opacity = "";
1146
1294
  s.display = "";
1295
+ s.position = "";
1296
+ s.inset = "";
1297
+ s.pointerEvents = "";
1147
1298
  }
1148
1299
  if (this.backdrop) {
1149
1300
  this.backdrop.style.opacity = "";
@@ -1392,7 +1543,12 @@ var AnimationRunner = class {
1392
1543
  this.currentSpring?.cancel();
1393
1544
  }
1394
1545
  async animateTo(target, velocityPxPerMs) {
1395
- if (target === this.getSize()) return;
1546
+ if (target === this.getSize()) {
1547
+ if (!this.isAnimating && !this.isDragging()) {
1548
+ this.element.style.willChange = "";
1549
+ }
1550
+ return;
1551
+ }
1396
1552
  this.currentTween?.cancel();
1397
1553
  this.currentSpring?.cancel();
1398
1554
  this.getRootEl()?.setAttribute("data-animating", "true");
@@ -1400,7 +1556,7 @@ var AnimationRunner = class {
1400
1556
  if (this.reducedMotion) {
1401
1557
  this.applySizeFn(target);
1402
1558
  this.getRootEl()?.removeAttribute("data-animating");
1403
- if (!this.isDragging()) this.element.style.willChange = "auto";
1559
+ if (!this.isDragging()) this.element.style.willChange = "";
1404
1560
  return;
1405
1561
  }
1406
1562
  if (this.animationKind === "spring") {
@@ -1428,7 +1584,7 @@ var AnimationRunner = class {
1428
1584
  }
1429
1585
  if (!this.isAnimating) {
1430
1586
  this.getRootEl()?.removeAttribute("data-animating");
1431
- if (!this.isDragging()) this.element.style.willChange = "auto";
1587
+ if (!this.isDragging()) this.element.style.willChange = "";
1432
1588
  }
1433
1589
  }
1434
1590
  destroy() {
@@ -1459,9 +1615,35 @@ var isVisible = (el) => {
1459
1615
  }
1460
1616
  return el.offsetParent !== null;
1461
1617
  };
1462
- var focusables = (root) => Array.from(root.querySelectorAll(FOCUSABLE)).filter(
1618
+ var collectFocusables = (root) => {
1619
+ const out = Array.from(root.querySelectorAll(FOCUSABLE));
1620
+ if (typeof HTMLSlotElement !== "undefined") {
1621
+ for (const slot of Array.from(root.querySelectorAll("slot"))) {
1622
+ for (const assigned of slot.assignedElements()) {
1623
+ if (assigned.matches(FOCUSABLE)) out.push(assigned);
1624
+ out.push(...collectFocusables(assigned));
1625
+ }
1626
+ }
1627
+ }
1628
+ return out;
1629
+ };
1630
+ var focusables = (root) => collectFocusables(root).filter(
1463
1631
  (el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
1464
1632
  );
1633
+ var containsComposed = (container, node) => {
1634
+ let n = node;
1635
+ while (n) {
1636
+ if (n === container) return true;
1637
+ const slot = n.assignedSlot;
1638
+ if (slot) {
1639
+ n = slot;
1640
+ continue;
1641
+ }
1642
+ const parent = n.parentNode;
1643
+ n = parent instanceof ShadowRoot ? parent.host : parent;
1644
+ }
1645
+ return false;
1646
+ };
1465
1647
  var trapStack = [];
1466
1648
  var installFocusTrap = (container, options = {}) => {
1467
1649
  if (typeof document === "undefined") return () => {
@@ -1471,7 +1653,13 @@ var installFocusTrap = (container, options = {}) => {
1471
1653
  const isActive = () => trapStack[trapStack.length - 1] === token;
1472
1654
  const previouslyFocused = document.activeElement;
1473
1655
  const focusInitial = () => {
1474
- const initial = typeof options.initialFocus === "string" ? container.querySelector(options.initialFocus) : options.initialFocus ?? focusables(container)[0] ?? container;
1656
+ const spec = options.initialFocus;
1657
+ if (spec === false) {
1658
+ if (!container.hasAttribute("tabindex")) container.tabIndex = -1;
1659
+ container.focus({ preventScroll: true });
1660
+ return;
1661
+ }
1662
+ const initial = typeof spec === "string" ? container.querySelector(spec) : spec ?? focusables(container)[0] ?? container;
1475
1663
  initial?.focus({ preventScroll: true });
1476
1664
  };
1477
1665
  focusInitial();
@@ -1501,7 +1689,7 @@ var installFocusTrap = (container, options = {}) => {
1501
1689
  const handleFocusIn = (e) => {
1502
1690
  if (!isActive()) return;
1503
1691
  const target = e.target;
1504
- if (target && !container.contains(target)) {
1692
+ if (target && !containsComposed(container, target)) {
1505
1693
  const list = focusables(container);
1506
1694
  list[0]?.focus({ preventScroll: true });
1507
1695
  }
@@ -1538,8 +1726,14 @@ var lockBodyScroll = () => {
1538
1726
  position: body.style.position,
1539
1727
  top: body.style.top,
1540
1728
  width: body.style.width,
1729
+ paddingRight: body.style.paddingRight,
1541
1730
  scrollY: window.scrollY
1542
1731
  };
1732
+ const scrollbarGap = window.innerWidth - document.documentElement.clientWidth;
1733
+ if (scrollbarGap > 0) {
1734
+ const current = parseFloat(getComputedStyle(body).paddingRight) || 0;
1735
+ body.style.paddingRight = `${current + scrollbarGap}px`;
1736
+ }
1543
1737
  body.style.overflow = "hidden";
1544
1738
  body.style.position = "fixed";
1545
1739
  body.style.top = `-${savedStyles.scrollY}px`;
@@ -1557,6 +1751,7 @@ var lockBodyScroll = () => {
1557
1751
  body.style.position = savedStyles.position;
1558
1752
  body.style.top = savedStyles.top;
1559
1753
  body.style.width = savedStyles.width;
1754
+ body.style.paddingRight = savedStyles.paddingRight;
1560
1755
  window.scrollTo(0, savedStyles.scrollY);
1561
1756
  savedStyles = null;
1562
1757
  }
@@ -1769,12 +1964,14 @@ var installGestures = (handle, mode, callbacks) => {
1769
1964
  handle.addEventListener("pointermove", onPointerMove);
1770
1965
  handle.addEventListener("pointerup", finishGesture);
1771
1966
  handle.addEventListener("pointercancel", onPointerCancel);
1967
+ const prevTouchAction = handle.style.touchAction;
1772
1968
  handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
1773
1969
  return () => {
1774
1970
  handle.removeEventListener("pointerdown", onPointerDown);
1775
1971
  handle.removeEventListener("pointermove", onPointerMove);
1776
1972
  handle.removeEventListener("pointerup", finishGesture);
1777
1973
  handle.removeEventListener("pointercancel", onPointerCancel);
1974
+ handle.style.touchAction = prevTouchAction;
1778
1975
  if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
1779
1976
  handle.releasePointerCapture(activePointerId);
1780
1977
  }
@@ -1901,7 +2098,7 @@ var GestureController = class {
1901
2098
  this.isDragging_ = false;
1902
2099
  this.keyboardDismissed = false;
1903
2100
  this.deps.getRoot()?.removeAttribute("data-dragging");
1904
- this.deps.element.style.willChange = "auto";
2101
+ this.deps.element.style.willChange = "";
1905
2102
  }
1906
2103
  };
1907
2104
 
@@ -2300,8 +2497,7 @@ function resolveEngineOptions(opts, extras) {
2300
2497
  };
2301
2498
  }
2302
2499
 
2303
- // src/core/BottomSheetEngine.ts
2304
- var HAPTIC_DURATION_MS = 8;
2500
+ // src/core/primitives/teardown-stack.ts
2305
2501
  var TeardownStack = class {
2306
2502
  constructor() {
2307
2503
  __publicField(this, "fns", []);
@@ -2321,6 +2517,9 @@ var TeardownStack = class {
2321
2517
  }
2322
2518
  }
2323
2519
  };
2520
+
2521
+ // src/core/BottomSheetEngine.ts
2522
+ var HAPTIC_DURATION_MS = 8;
2324
2523
  var BottomSheetEngine = class {
2325
2524
  constructor(opts) {
2326
2525
  __publicField(this, "id", nextInstanceId("bs"));
@@ -2345,6 +2544,7 @@ var BottomSheetEngine = class {
2345
2544
  __publicField(this, "disableDragFlag");
2346
2545
  __publicField(this, "closeOnRouteChange");
2347
2546
  __publicField(this, "maxHeightCap");
2547
+ __publicField(this, "maxHeightRaw");
2348
2548
  __publicField(this, "snapPointsRaw");
2349
2549
  __publicField(this, "snaps");
2350
2550
  __publicField(this, "activeId");
@@ -2380,6 +2580,7 @@ var BottomSheetEngine = class {
2380
2580
  __publicField(this, "detachScrimStages", null);
2381
2581
  __publicField(this, "stackEffectEnabled", false);
2382
2582
  __publicField(this, "stackEffectPrimed", false);
2583
+ __publicField(this, "fitDeps");
2383
2584
  __publicField(this, "transformTemplate");
2384
2585
  const resolved = resolveEngineOptions(opts, {
2385
2586
  shouldApplyInertSiblings: () => {
@@ -2452,12 +2653,19 @@ var BottomSheetEngine = class {
2452
2653
  }
2453
2654
  this.activeId = resolved.initialId;
2454
2655
  auditVhUsage(this.snapPointsRaw);
2656
+ this.auditDuplicateSnapIds(this.snapPointsRaw);
2455
2657
  this.rootEl = this.element.closest(".bs-root");
2658
+ this.fitDeps = {
2659
+ element: this.element,
2660
+ scrollContainer: this.scrollContainer,
2661
+ mode: this.mode,
2662
+ getMaxHeightCap: () => this.maxHeightCap
2663
+ };
2456
2664
  this.snaps = new SnapResolver(
2457
2665
  this.snapPointsRaw,
2458
2666
  resolved.initialAllowed,
2459
2667
  this.mode,
2460
- () => this.measureFitSize(),
2668
+ () => measureFitSize(this.fitDeps),
2461
2669
  (maxAxisSize) => {
2462
2670
  this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
2463
2671
  }
@@ -2491,7 +2699,18 @@ var BottomSheetEngine = class {
2491
2699
  io.observe(this.element);
2492
2700
  this.teardowns.add(() => io.disconnect());
2493
2701
  }
2494
- this.installFitObserver();
2702
+ this.teardowns.add(
2703
+ installFitObserver({
2704
+ handle: this.handle,
2705
+ scrollContainer: this.scrollContainer,
2706
+ hasFitSnap: () => this.snapPointsRaw.some(
2707
+ (p) => p.size === "fit" || p.size === "content"
2708
+ ),
2709
+ isDestroyed: () => this.destroyed,
2710
+ isDragging: () => this.gesture?.isDragging ?? false,
2711
+ recompute: () => this.recompute()
2712
+ })
2713
+ );
2495
2714
  if (resolved.radius !== void 0) this.setRadius(resolved.radius);
2496
2715
  if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
2497
2716
  this.applyAutoAriaLabelledBy();
@@ -2642,27 +2861,33 @@ var BottomSheetEngine = class {
2642
2861
  } else {
2643
2862
  await this.animation.animateTo(target.size, velocityPxPerMs);
2644
2863
  }
2645
- this.opening = false;
2646
2864
  externalSignal?.removeEventListener("abort", onExternalAbort);
2647
2865
  if (signal.aborted) return;
2648
- this.scrollCache.restore(id, previousSize, target.size);
2866
+ this.opening = false;
2867
+ this.completeSnap(id, target.size, previousSize, wasClosed, false);
2868
+ }
2869
+ completeSnap(id, targetSize, previousSize, wasClosed, withHaptic) {
2870
+ this.scrollCache.restore(id, previousSize, targetSize);
2649
2871
  this.updateAriaSlider();
2650
2872
  this.emit("snap", {
2651
2873
  id,
2652
2874
  size: this.size,
2653
2875
  progress: this.computeProgress(this.size)
2654
2876
  });
2655
- if (wasClosed && target.size > 0) {
2656
- this.emit("open", { id });
2657
- this.handleOpen();
2658
- notifyLinkedSheets(this.linkedSheets, this);
2659
- this.emit("opened", { id });
2660
- }
2661
- if (target.size === 0) {
2662
- this.emit("close", void 0);
2663
- this.handleClose();
2664
- this.emit("closed", void 0);
2665
- }
2877
+ if (withHaptic) this.haptic();
2878
+ if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
2879
+ if (targetSize === 0) this.emitCloseSequence();
2880
+ }
2881
+ emitOpenSequence(id) {
2882
+ this.emit("open", { id });
2883
+ this.handleOpen();
2884
+ notifyLinkedSheets(this.linkedSheets, this);
2885
+ this.emit("opened", { id });
2886
+ }
2887
+ emitCloseSequence() {
2888
+ this.emit("close", void 0);
2889
+ this.handleClose();
2890
+ this.emit("closed", void 0);
2666
2891
  }
2667
2892
  async dragTo(targetSize, velocityOrOpts = 0) {
2668
2893
  if (this.destroyed) return;
@@ -2683,19 +2908,31 @@ var BottomSheetEngine = class {
2683
2908
  }
2684
2909
  open(id) {
2685
2910
  if (this.destroyed) return Promise.resolve();
2686
- const target = id ?? this.snaps.getAllowedIds().find((a) => a !== "closed") ?? this.activeId;
2911
+ const target = id ?? this.snaps.getAllowedIds().find((a) => (this.snaps.findById(a)?.size ?? 0) > 0) ?? this.activeId;
2687
2912
  return this.snapTo(target);
2688
2913
  }
2689
2914
  close(reason = "programmatic") {
2690
2915
  if (this.destroyed) return Promise.resolve();
2691
2916
  if (this.disableCloseFlag) return Promise.resolve();
2692
2917
  if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
2693
- const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
2918
+ const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds().find((a) => this.snaps.findById(a)?.size === 0) ?? this.snaps.getAllowedIds()[0];
2694
2919
  return this.snapTo(closedId ?? this.activeId);
2695
2920
  }
2696
2921
  canDismiss() {
2697
2922
  return !this.persistent && !this.disableCloseFlag && !this.destroyed;
2698
2923
  }
2924
+ setPersistent(value) {
2925
+ if (this.destroyed) return;
2926
+ this.persistent = value;
2927
+ }
2928
+ setDisableClose(value) {
2929
+ if (this.destroyed) return;
2930
+ this.disableCloseFlag = value;
2931
+ }
2932
+ setDisableDrag(value) {
2933
+ if (this.destroyed) return;
2934
+ this.disableDragFlag = value;
2935
+ }
2699
2936
  isTop() {
2700
2937
  return this.isTopSheet;
2701
2938
  }
@@ -2732,18 +2969,23 @@ var BottomSheetEngine = class {
2732
2969
  axis === "height" ? "max-height" : "max-width",
2733
2970
  value
2734
2971
  );
2735
- if (typeof h === "number") {
2736
- this.maxHeightCap = h;
2737
- this.recompute();
2738
- } else if (typeof window !== "undefined") {
2739
- const probe2 = document.createElement("div");
2740
- probe2.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;${axis === "height" ? "height" : "width"}:${value};`;
2741
- document.body.appendChild(probe2);
2742
- const measured = axis === "height" ? probe2.offsetHeight : probe2.offsetWidth;
2743
- probe2.remove();
2744
- this.maxHeightCap = measured > 0 ? measured : void 0;
2745
- this.recompute();
2972
+ this.maxHeightRaw = h;
2973
+ this.resolveMaxHeightCap();
2974
+ this.recompute();
2975
+ }
2976
+ resolveMaxHeightCap() {
2977
+ const raw = this.maxHeightRaw;
2978
+ if (raw === void 0) {
2979
+ this.maxHeightCap = void 0;
2980
+ return;
2746
2981
  }
2982
+ if (typeof raw === "number") {
2983
+ this.maxHeightCap = raw;
2984
+ return;
2985
+ }
2986
+ if (typeof window === "undefined") return;
2987
+ const measured = resolveSnap(raw, this.mode);
2988
+ this.maxHeightCap = measured > 0 ? measured : void 0;
2747
2989
  }
2748
2990
  clampToMaxHeight() {
2749
2991
  if (this.maxHeightCap === void 0) return;
@@ -2874,6 +3116,7 @@ var BottomSheetEngine = class {
2874
3116
  this.newCycle();
2875
3117
  this.snapPointsRaw = points;
2876
3118
  auditVhUsage(points);
3119
+ this.auditDuplicateSnapIds(points);
2877
3120
  this.snaps.setRaw(points);
2878
3121
  if (allowed) this.snaps.setAllowedIds(allowed);
2879
3122
  this.scrollCache.clear();
@@ -2886,6 +3129,7 @@ var BottomSheetEngine = class {
2886
3129
  }
2887
3130
  recompute() {
2888
3131
  if (this.destroyed) return;
3132
+ this.resolveMaxHeightCap();
2889
3133
  this.snaps.recompute();
2890
3134
  this.clampToMaxHeight();
2891
3135
  this.scrim.invalidateOpacityCache();
@@ -2897,129 +3141,6 @@ var BottomSheetEngine = class {
2897
3141
  this.updateAriaSlider();
2898
3142
  }
2899
3143
  }
2900
- contentTargets() {
2901
- const scroller = this.scrollContainer;
2902
- if (!scroller) return [];
2903
- const hasSlot = typeof HTMLSlotElement !== "undefined";
2904
- const out = [];
2905
- for (const child of Array.from(scroller.children)) {
2906
- if (hasSlot && child instanceof HTMLSlotElement) {
2907
- for (const el of child.assignedElements()) out.push(el);
2908
- } else {
2909
- out.push(child);
2910
- }
2911
- }
2912
- return out;
2913
- }
2914
- measureSheetNatural(vertical) {
2915
- const el = this.element;
2916
- const content = this.scrollContainer;
2917
- if (!content) {
2918
- return vertical ? el.offsetHeight : el.offsetWidth;
2919
- }
2920
- const axis = vertical ? "height" : "width";
2921
- const sheetStyle = el.style;
2922
- const cs = content.style;
2923
- const prevSheet = sheetStyle[axis];
2924
- const prevFlex = cs.flex;
2925
- const prevContent = vertical ? cs.height : cs.width;
2926
- sheetStyle[axis] = "auto";
2927
- cs.flex = "none";
2928
- if (vertical) cs.height = "auto";
2929
- else cs.width = "auto";
2930
- const poked = vertical ? el.offsetHeight : el.offsetWidth;
2931
- const contentBox = vertical ? content.clientHeight : content.clientWidth;
2932
- const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
2933
- const natural = Math.max(poked, poked - contentBox + contentScroll);
2934
- sheetStyle[axis] = prevSheet;
2935
- cs.flex = prevFlex;
2936
- if (vertical) cs.height = prevContent;
2937
- else cs.width = prevContent;
2938
- return natural;
2939
- }
2940
- measureFitSize() {
2941
- const vertical = layoutAxis(this.mode) === "height";
2942
- const natural = this.measureSheetNatural(vertical);
2943
- const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
2944
- if (typeof window === "undefined") return capped;
2945
- const viewport = this.containingExtent(vertical);
2946
- return viewport > 0 ? Math.min(capped, viewport) : capped;
2947
- }
2948
- // The fit cap is the sheet's containing block, not always the window: a
2949
- // position:fixed sheet nested under a transform/filter/will-change ancestor
2950
- // is clipped to that ancestor, so capping by window.innerHeight oversizes the
2951
- // sheet and the content/footer get clipped. offsetParent resolves to that
2952
- // ancestor when present, and is null (→ viewport) for a plain fixed sheet.
2953
- containingExtent(vertical) {
2954
- const op = this.element.offsetParent;
2955
- if (op && op !== document.body && op !== document.documentElement) {
2956
- return vertical ? op.clientHeight : op.clientWidth;
2957
- }
2958
- return vertical ? window.innerHeight : window.innerWidth;
2959
- }
2960
- installFitObserver() {
2961
- if (typeof ResizeObserver === "undefined") return;
2962
- if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
2963
- return;
2964
- let raf = 0;
2965
- const schedule = () => {
2966
- if (raf) return;
2967
- raf = requestAnimationFrame(() => {
2968
- raf = 0;
2969
- if (this.destroyed || this.gesture?.isDragging) return;
2970
- this.recompute();
2971
- });
2972
- };
2973
- const ro = new ResizeObserver(schedule);
2974
- ro.observe(this.handle);
2975
- const scroller = this.scrollContainer;
2976
- const observed = /* @__PURE__ */ new Set();
2977
- const slots = /* @__PURE__ */ new Set();
2978
- const hasSlot = typeof HTMLSlotElement !== "undefined";
2979
- const onSlotChange = () => resync();
2980
- const trackSlots = () => {
2981
- if (!scroller || !hasSlot) return;
2982
- for (const child of Array.from(scroller.children)) {
2983
- if (child instanceof HTMLSlotElement && !slots.has(child)) {
2984
- child.addEventListener("slotchange", onSlotChange);
2985
- slots.add(child);
2986
- }
2987
- }
2988
- };
2989
- const resync = () => {
2990
- trackSlots();
2991
- const targets = this.contentTargets();
2992
- for (const el of observed) {
2993
- if (!targets.includes(el)) {
2994
- ro.unobserve(el);
2995
- observed.delete(el);
2996
- }
2997
- }
2998
- for (const el of targets) {
2999
- if (!observed.has(el)) {
3000
- ro.observe(el);
3001
- observed.add(el);
3002
- }
3003
- }
3004
- schedule();
3005
- };
3006
- let mo;
3007
- if (scroller) {
3008
- resync();
3009
- if (typeof MutationObserver !== "undefined") {
3010
- mo = new MutationObserver(resync);
3011
- mo.observe(scroller, { childList: true });
3012
- }
3013
- }
3014
- this.teardowns.add(() => {
3015
- ro.disconnect();
3016
- mo?.disconnect();
3017
- for (const slot of slots) {
3018
- slot.removeEventListener("slotchange", onSlotChange);
3019
- }
3020
- if (raf) cancelAnimationFrame(raf);
3021
- });
3022
- }
3023
3144
  destroy() {
3024
3145
  this.destroyed = true;
3025
3146
  this.opening = false;
@@ -3037,9 +3158,10 @@ var BottomSheetEngine = class {
3037
3158
  this.backdrop.style.opacity = "";
3038
3159
  this.backdrop.style.pointerEvents = "";
3039
3160
  }
3040
- if (this.anchorHost) {
3041
- this.anchorHost.style.removeProperty("--bs-size");
3042
- this.anchorHost.style.removeProperty("--bs-progress");
3161
+ for (const host of [this.anchorHost, this.scrimParent, this.rootEl]) {
3162
+ if (!host) continue;
3163
+ host.style.removeProperty("--bs-size");
3164
+ host.style.removeProperty("--bs-progress");
3043
3165
  }
3044
3166
  if (this.screenComponent) {
3045
3167
  this.screenComponent.style.opacity = "";
@@ -3053,6 +3175,7 @@ var BottomSheetEngine = class {
3053
3175
  }
3054
3176
  newCycle() {
3055
3177
  this.allowOvershoot = false;
3178
+ this.opening = false;
3056
3179
  this.currentAbort.abort();
3057
3180
  this.currentAbort = new AbortController();
3058
3181
  return this.currentAbort.signal;
@@ -3108,8 +3231,14 @@ var BottomSheetEngine = class {
3108
3231
  this.element.setAttribute("aria-labelledby", titled.id);
3109
3232
  }
3110
3233
  recomputeSnaps() {
3234
+ this.resolveMaxHeightCap();
3235
+ this.snaps.setRaw(this.snapPointsRaw);
3236
+ this.clampToMaxHeight();
3237
+ this.scrim.invalidateOpacityCache();
3238
+ }
3239
+ auditDuplicateSnapIds(points) {
3111
3240
  const seen = /* @__PURE__ */ new Set();
3112
- for (const p of this.snapPointsRaw) {
3241
+ for (const p of points) {
3113
3242
  if (seen.has(p.id)) {
3114
3243
  console.warn(
3115
3244
  `[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
@@ -3117,9 +3246,6 @@ var BottomSheetEngine = class {
3117
3246
  }
3118
3247
  seen.add(p.id);
3119
3248
  }
3120
- this.snaps.setRaw(this.snapPointsRaw);
3121
- this.clampToMaxHeight();
3122
- this.scrim.invalidateOpacityCache();
3123
3249
  }
3124
3250
  getAllowedRange() {
3125
3251
  return this.snaps.getAllowedRange();
@@ -3307,9 +3433,15 @@ var BottomSheetEngine = class {
3307
3433
  flickVelocity: this.flickVelocity,
3308
3434
  dragThreshold: this.dragThreshold
3309
3435
  });
3310
- if (!target) return;
3436
+ if (!target) {
3437
+ this.clearWillChangeIfIdle();
3438
+ return;
3439
+ }
3311
3440
  const previousId = this.activeId;
3312
- if (target.id === previousId && target.size === this.size) return;
3441
+ if (target.id === previousId && target.size === this.size) {
3442
+ this.clearWillChangeIfIdle();
3443
+ return;
3444
+ }
3313
3445
  if (this.emitBeforeSnap(target, previousId)) {
3314
3446
  const restore = this.snaps.findById(previousId);
3315
3447
  if (restore) {
@@ -3332,27 +3464,19 @@ var BottomSheetEngine = class {
3332
3464
  if (signal.aborted) return;
3333
3465
  this.allowOvershoot = false;
3334
3466
  this.opening = false;
3335
- this.scrollCache.restore(target.id, previousSize, target.size);
3336
- this.updateAriaSlider();
3337
- this.emit("snap", {
3338
- id: target.id,
3339
- size: this.size,
3340
- progress: this.computeProgress(this.size)
3341
- });
3342
- this.haptic();
3343
- if (previousSnapSize === 0 && target.size > 0) {
3344
- this.emit("open", { id: target.id });
3345
- this.handleOpen();
3346
- notifyLinkedSheets(this.linkedSheets, this);
3347
- this.emit("opened", { id: target.id });
3348
- }
3349
- if (target.size === 0) {
3350
- this.emit("close", void 0);
3351
- this.handleClose();
3352
- this.emit("closed", void 0);
3353
- }
3467
+ this.completeSnap(
3468
+ target.id,
3469
+ target.size,
3470
+ previousSize,
3471
+ previousSnapSize === 0,
3472
+ true
3473
+ );
3354
3474
  });
3355
3475
  }
3476
+ clearWillChangeIfIdle() {
3477
+ if (this.animation.isAnimating || this.gesture?.isDragging) return;
3478
+ this.element.style.willChange = "";
3479
+ }
3356
3480
  haptic() {
3357
3481
  if (typeof navigator !== "undefined" && "vibrate" in navigator) {
3358
3482
  try {
@@ -3433,14 +3557,9 @@ var BottomSheetEngine = class {
3433
3557
  progress: this.computeProgress(this.size)
3434
3558
  });
3435
3559
  if (target.size > 0 && !this.lifecycle.isInstalled) {
3436
- this.emit("open", { id: target.id });
3437
- this.handleOpen();
3438
- notifyLinkedSheets(this.linkedSheets, this);
3439
- this.emit("opened", { id: target.id });
3560
+ this.emitOpenSequence(target.id);
3440
3561
  } else if (target.size === 0 && this.lifecycle.isInstalled) {
3441
- this.emit("close", void 0);
3442
- this.handleClose();
3443
- this.emit("closed", void 0);
3562
+ this.emitCloseSequence();
3444
3563
  }
3445
3564
  }
3446
3565
  handleClose() {
@@ -3450,11 +3569,45 @@ var BottomSheetEngine = class {
3450
3569
  }
3451
3570
  };
3452
3571
 
3572
+ // src/core/features/teleport.ts
3573
+ var resolveTeleportTarget = (target) => {
3574
+ if (!target) return null;
3575
+ if (typeof target !== "string") return target;
3576
+ if (typeof document === "undefined") return null;
3577
+ if (target === "body") return document.body;
3578
+ return document.querySelector(target);
3579
+ };
3580
+ var teleportElements = (els, target) => {
3581
+ const records = [];
3582
+ for (const el of els) {
3583
+ if (!el || el.parentNode === target) continue;
3584
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3585
+ target.appendChild(el);
3586
+ }
3587
+ return () => {
3588
+ for (let i = records.length - 1; i >= 0; i--) {
3589
+ const { el, parent, next } = records[i];
3590
+ if (parent && parent.isConnected) {
3591
+ const before = next && next.parentNode === parent ? next : null;
3592
+ try {
3593
+ parent.insertBefore(el, before);
3594
+ } catch {
3595
+ el.parentNode?.removeChild(el);
3596
+ }
3597
+ } else {
3598
+ el.parentNode?.removeChild(el);
3599
+ }
3600
+ }
3601
+ };
3602
+ };
3603
+
3453
3604
  // src/solid/index.tsx
3454
3605
  var _tmpl$ = /* @__PURE__ */ template(`<div class=bs-header>`);
3455
3606
  var _tmpl$2 = /* @__PURE__ */ template(`<div class=bs-footer>`);
3456
- var _tmpl$3 = /* @__PURE__ */ template(`<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"></div><div class=bs-content tabindex=0 role=region aria-label="Sheet content"></div><span class=bs-sr-only role=status aria-live=polite>`);
3457
- var _tmpl$4 = /* @__PURE__ */ template(`<div class=bs-backdrop>`);
3607
+ var _tmpl$3 = /* @__PURE__ */ template(`<div class=bs-button-slot data-side=left>`);
3608
+ var _tmpl$4 = /* @__PURE__ */ template(`<div class=bs-button-slot data-side=right>`);
3609
+ var _tmpl$5 = /* @__PURE__ */ template(`<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"></div><div class=bs-content tabindex=0 role=region aria-label="Sheet content"></div><span class=bs-sr-only role=status aria-live=polite>`);
3610
+ var _tmpl$6 = /* @__PURE__ */ template(`<div class=bs-backdrop>`);
3458
3611
  var BottomSheet = (props) => {
3459
3612
  let sheetEl;
3460
3613
  let handleEl;
@@ -3470,6 +3623,7 @@ var BottomSheet = (props) => {
3470
3623
  progress: 0
3471
3624
  });
3472
3625
  let engine = null;
3626
+ let restoreTeleport = null;
3473
3627
  onMount(() => {
3474
3628
  if (!sheetEl) return;
3475
3629
  const engineOpts = {
@@ -3496,10 +3650,15 @@ var BottomSheet = (props) => {
3496
3650
  disableClose: props.disableClose,
3497
3651
  disableDrag: props.disableDrag,
3498
3652
  closeOnRouteChange: props.closeOnRouteChange,
3653
+ stackEffect: props.stackEffect,
3499
3654
  returnFocusTo: props.returnFocusTo
3500
3655
  };
3501
3656
  engine = new BottomSheetEngine(engineOpts);
3502
3657
  props.engineRef?.(engine);
3658
+ const teleportTarget = props.teleport === false ? null : resolveTeleportTarget(props.teleportTo);
3659
+ if (teleportTarget) {
3660
+ restoreTeleport = teleportElements([backdropEl, scrimEl, sheetEl], teleportTarget);
3661
+ }
3503
3662
  const sync = () => {
3504
3663
  if (!engine) return;
3505
3664
  const s = engine.state;
@@ -3513,6 +3672,7 @@ var BottomSheet = (props) => {
3513
3672
  sync();
3514
3673
  props.onSnap?.(payload.id);
3515
3674
  });
3675
+ engine.on("before-snap", (payload) => props.onBeforeSnap?.(payload));
3516
3676
  engine.on("dragstart", sync);
3517
3677
  engine.on("dragend", sync);
3518
3678
  if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropEl) {
@@ -3526,6 +3686,8 @@ var BottomSheet = (props) => {
3526
3686
  }
3527
3687
  });
3528
3688
  onCleanup(() => {
3689
+ restoreTeleport?.();
3690
+ restoreTeleport = null;
3529
3691
  engine?.destroy();
3530
3692
  engine = null;
3531
3693
  props.engineRef?.(null);
@@ -3542,17 +3704,35 @@ var BottomSheet = (props) => {
3542
3704
  }, {
3543
3705
  defer: true
3544
3706
  }));
3707
+ createEffect(on(() => props.persistent, (value, prev) => {
3708
+ if (!engine || prev === void 0 || value === void 0) return;
3709
+ engine.setPersistent(value);
3710
+ }, {
3711
+ defer: true
3712
+ }));
3713
+ createEffect(on(() => props.disableClose, (value, prev) => {
3714
+ if (!engine || prev === void 0 || value === void 0) return;
3715
+ engine.setDisableClose(value);
3716
+ }, {
3717
+ defer: true
3718
+ }));
3719
+ createEffect(on(() => props.disableDrag, (value, prev) => {
3720
+ if (!engine || prev === void 0 || value === void 0) return;
3721
+ engine.setDisableDrag(value);
3722
+ }, {
3723
+ defer: true
3724
+ }));
3545
3725
  const showBackdrop = createMemo(() => props.backdrop !== false);
3546
3726
  const mode = createMemo(() => props.mode ?? "bottom");
3547
3727
  const ariaLabel = createMemo(() => props.ariaLabel ?? "Bottom sheet");
3548
3728
  return (() => {
3549
- var _el$ = _tmpl$3(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.firstChild, _el$6 = _el$4.nextSibling, _el$8 = _el$6.nextSibling;
3729
+ var _el$ = _tmpl$5(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.firstChild, _el$6 = _el$4.nextSibling, _el$8 = _el$6.nextSibling;
3550
3730
  insert(_el$, (() => {
3551
3731
  var _c$ = memo(() => !!showBackdrop());
3552
3732
  return () => _c$() ? (() => {
3553
- var _el$9 = _tmpl$4();
3554
- use((el) => backdropEl = el, _el$9);
3555
- return _el$9;
3733
+ var _el$1 = _tmpl$6();
3734
+ use((el) => backdropEl = el, _el$1);
3735
+ return _el$1;
3556
3736
  })() : null;
3557
3737
  })(), _el$2);
3558
3738
  use((el) => scrimEl = el, _el$2);
@@ -3582,6 +3762,28 @@ var BottomSheet = (props) => {
3582
3762
  }
3583
3763
  }), _el$8);
3584
3764
  insert(_el$8, () => state().activeId);
3765
+ insert(_el$, createComponent(Show, {
3766
+ get when() {
3767
+ return props.leftButton;
3768
+ },
3769
+ get children() {
3770
+ var _el$9 = _tmpl$3();
3771
+ insert(_el$9, () => props.leftButton);
3772
+ effect(() => setAttribute(_el$9, "data-mode", mode()));
3773
+ return _el$9;
3774
+ }
3775
+ }), null);
3776
+ insert(_el$, createComponent(Show, {
3777
+ get when() {
3778
+ return props.rightButton;
3779
+ },
3780
+ get children() {
3781
+ var _el$0 = _tmpl$4();
3782
+ insert(_el$0, () => props.rightButton);
3783
+ effect(() => setAttribute(_el$0, "data-mode", mode()));
3784
+ return _el$0;
3785
+ }
3786
+ }), null);
3585
3787
  effect((_p$) => {
3586
3788
  var _v$ = mode(), _v$2 = state().activeId, _v$3 = props.focusTrap ? "true" : void 0, _v$4 = ariaLabel();
3587
3789
  _v$ !== _p$.e && setAttribute(_el$3, "data-mode", _p$.e = _v$);