@surdeddd/bottom-sheet 0.13.0 → 0.20.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 (66) hide show
  1. package/README.md +46 -0
  2. package/dist/{BottomSheetCore-D16lsa6g.d.ts → BottomSheetCore-Cgn8b_6A.d.ts} +36 -2
  3. package/dist/{BottomSheetCore-CsIjyq7C.d.cts → BottomSheetCore-VPJZcKcg.d.cts} +36 -2
  4. package/dist/{BottomSheetEngine-BYjAVrmd.d.cts → BottomSheetEngine-B8C2CwF9.d.cts} +1 -1
  5. package/dist/{BottomSheetEngine-YuCNugZn.d.ts → BottomSheetEngine-DwYR_ygJ.d.ts} +1 -1
  6. package/dist/core.cjs +328 -33
  7. package/dist/core.d.cts +2 -2
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +328 -33
  10. package/dist/debug.d.cts +1 -1
  11. package/dist/debug.d.ts +1 -1
  12. package/dist/element.cjs +404 -108
  13. package/dist/element.d.cts +2 -2
  14. package/dist/element.d.ts +2 -2
  15. package/dist/element.iife.global.js +2 -2
  16. package/dist/element.js +404 -108
  17. package/dist/features.cjs +6 -50
  18. package/dist/features.d.cts +4 -4
  19. package/dist/features.d.ts +4 -4
  20. package/dist/features.js +6 -50
  21. package/dist/index-CnfbOKx0.d.cts +9 -0
  22. package/dist/index-DcMkhXAy.d.ts +9 -0
  23. package/dist/index.cjs +335 -829
  24. package/dist/index.d.cts +44 -47
  25. package/dist/index.d.ts +44 -47
  26. package/dist/index.js +336 -816
  27. package/dist/integrations/formik.d.cts +1 -1
  28. package/dist/integrations/formik.d.ts +1 -1
  29. package/dist/integrations/react-hook-form.d.cts +1 -1
  30. package/dist/integrations/react-hook-form.d.ts +1 -1
  31. package/dist/overlay.cjs +5 -5
  32. package/dist/overlay.js +5 -5
  33. package/dist/preact.d.cts +2 -2
  34. package/dist/preact.d.ts +2 -2
  35. package/dist/qwik-lib/index.qwik.cjs +323 -83
  36. package/dist/qwik-lib/index.qwik.mjs +323 -83
  37. package/dist/qwik.cjs +342 -83
  38. package/dist/qwik.d.cts +4 -2
  39. package/dist/qwik.d.ts +4 -2
  40. package/dist/qwik.js +342 -83
  41. package/dist/react.cjs +347 -85
  42. package/dist/react.d.cts +3 -4
  43. package/dist/react.d.ts +3 -4
  44. package/dist/react.js +347 -85
  45. package/dist/solid.cjs +348 -83
  46. package/dist/solid.d.cts +37 -1
  47. package/dist/solid.d.ts +37 -1
  48. package/dist/solid.js +348 -83
  49. package/dist/solid.source.jsx +356 -83
  50. package/dist/styles.css +24 -4
  51. package/dist/svelte-core.cjs +334 -83
  52. package/dist/svelte-core.js +334 -83
  53. package/dist/svelte-src/BottomSheet.svelte +14 -0
  54. package/dist/svelte.cjs +344 -83
  55. package/dist/svelte.d.cts +2 -0
  56. package/dist/svelte.d.ts +2 -0
  57. package/dist/svelte.js +344 -83
  58. package/dist/vue.cjs +350 -83
  59. package/dist/vue.js +350 -83
  60. package/dist/webgl.cjs +673 -0
  61. package/dist/webgl.d.cts +17 -0
  62. package/dist/webgl.d.ts +17 -0
  63. package/dist/webgl.js +671 -0
  64. package/package.json +64 -40
  65. package/dist/index-DdYLOIIT.d.ts +0 -15
  66. package/dist/index-dfrzw-lI.d.cts +0 -15
package/dist/core.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
 
5
- // src/core/lifecycle/sheetStack.ts
5
+ // src/core/lifecycle/sheet-stack.ts
6
6
  var BASE_Z = 100;
7
7
  var STEP = 10;
8
8
  var SheetStack = class {
@@ -127,7 +127,7 @@ function createEventBus() {
127
127
  };
128
128
  }
129
129
 
130
- // src/core/primitives/cssLength.ts
130
+ // src/core/primitives/css-length.ts
131
131
  var probe = null;
132
132
  var PROBE_ATTR = "data-bs-probe";
133
133
  var ensureProbe = (axis) => {
@@ -181,7 +181,7 @@ var resolveSnap = (point, mode, measureFit) => {
181
181
  return Math.max(0, el.getBoundingClientRect().width);
182
182
  };
183
183
 
184
- // src/core/primitives/devWarn.ts
184
+ // src/core/primitives/dev-warn.ts
185
185
  function devWarn(...args) {
186
186
  if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
187
187
  console.warn(...args);
@@ -313,6 +313,11 @@ var SnapResolver = class {
313
313
  this.raw = raw;
314
314
  this.recompute();
315
315
  }
316
+ setMode(mode) {
317
+ if (mode === this.mode) return;
318
+ this.mode = mode;
319
+ this.recompute();
320
+ }
316
321
  setAllowedIds(ids) {
317
322
  this.allowedIds = ids;
318
323
  this.rangeCache = null;
@@ -896,6 +901,11 @@ var ScrimController = class {
896
901
  if (this.isDestroyed()) return;
897
902
  this.applyScrimStyles({ interactive });
898
903
  }
904
+ setSheetMode(mode) {
905
+ if (this.isDestroyed() || mode === this.mode) return;
906
+ this.mode = mode;
907
+ this.invalidateOpacityCache();
908
+ }
899
909
  setScrimMode(mode, applySize) {
900
910
  if (this.isDestroyed()) return;
901
911
  if (mode === this.scrimMode) return;
@@ -1514,7 +1524,7 @@ var AnimationRunner = class {
1514
1524
  }
1515
1525
  };
1516
1526
 
1517
- // src/core/lifecycle/focusTrap.ts
1527
+ // src/core/lifecycle/focus-trap.ts
1518
1528
  var FOCUSABLE = [
1519
1529
  "a[href]",
1520
1530
  "area[href]",
@@ -1632,7 +1642,7 @@ var installFocusTrap = (container, options = {}) => {
1632
1642
  };
1633
1643
  };
1634
1644
 
1635
- // src/core/lifecycle/scrollLock.ts
1645
+ // src/core/lifecycle/scroll-lock.ts
1636
1646
  var lockCount = 0;
1637
1647
  var savedStyles = null;
1638
1648
  var lockBodyScroll = () => {
@@ -1814,30 +1824,47 @@ var SampleRing = class {
1814
1824
  this.size = 0;
1815
1825
  }
1816
1826
  };
1817
- var installGestures = (handle, mode, callbacks) => {
1827
+ var installGestures = (handle, mode, callbacks, options = {}) => {
1818
1828
  let activePointerId = null;
1819
1829
  let activePointerType = "touch";
1820
1830
  let startCoord = 0;
1831
+ let startCross = 0;
1821
1832
  let lastCoord = 0;
1833
+ let pendingStart = false;
1822
1834
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
1823
1835
  const MAX_SAMPLES = 32;
1824
1836
  const samples = new SampleRing(MAX_SAMPLES);
1825
1837
  const axis = isAxisVertical(mode) ? "Y" : "X";
1826
1838
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1827
1839
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
1840
+ const crossOf = (e) => axis === "Y" ? e.clientX : e.clientY;
1841
+ const capture = (pointerId) => {
1842
+ try {
1843
+ handle.setPointerCapture(pointerId);
1844
+ } catch {
1845
+ }
1846
+ };
1847
+ const releaseTracking = () => {
1848
+ activePointerId = null;
1849
+ pendingStart = false;
1850
+ samples.reset();
1851
+ };
1828
1852
  const onPointerDown = (e) => {
1829
1853
  if (activePointerId !== null) return;
1830
1854
  if (e.button !== void 0 && e.button !== 0) return;
1855
+ if (options.shouldStart && !options.shouldStart(e)) return;
1831
1856
  activePointerId = e.pointerId;
1832
1857
  activePointerType = e.pointerType || "touch";
1833
1858
  startCoord = coordOf(e);
1859
+ startCross = crossOf(e);
1834
1860
  lastCoord = startCoord;
1835
1861
  samples.reset();
1836
1862
  samples.push(e.timeStamp, startCoord);
1837
- try {
1838
- handle.setPointerCapture(e.pointerId);
1839
- } catch {
1863
+ if (options.deferStart) {
1864
+ pendingStart = true;
1865
+ return;
1840
1866
  }
1867
+ capture(e.pointerId);
1841
1868
  callbacks.onStart(startCoord, activePointerType);
1842
1869
  };
1843
1870
  const onPointerMove = (e) => {
@@ -1845,6 +1872,22 @@ var installGestures = (handle, mode, callbacks) => {
1845
1872
  const coord = coordOf(e);
1846
1873
  const rawDelta = coord - startCoord;
1847
1874
  const delta = rawDelta * sign;
1875
+ if (pendingStart) {
1876
+ const verdict = options.deferStart(e, delta, crossOf(e) - startCross);
1877
+ if (verdict === false) {
1878
+ releaseTracking();
1879
+ return;
1880
+ }
1881
+ if (verdict !== true) return;
1882
+ pendingStart = false;
1883
+ startCoord = coord;
1884
+ lastCoord = coord;
1885
+ samples.reset();
1886
+ samples.push(e.timeStamp, coord);
1887
+ capture(e.pointerId);
1888
+ callbacks.onStart(startCoord, activePointerType);
1889
+ return;
1890
+ }
1848
1891
  lastCoord = coord;
1849
1892
  samples.push(e.timeStamp, coord);
1850
1893
  const cutoff = e.timeStamp - VELOCITY_WINDOW_MS(activePointerType);
@@ -1853,6 +1896,10 @@ var installGestures = (handle, mode, callbacks) => {
1853
1896
  };
1854
1897
  const finishGesture = (e) => {
1855
1898
  if (e.pointerId !== activePointerId) return;
1899
+ if (pendingStart) {
1900
+ releaseTracking();
1901
+ return;
1902
+ }
1856
1903
  const rawDelta = lastCoord - startCoord;
1857
1904
  const delta = rawDelta * sign;
1858
1905
  let velocity = 0;
@@ -1875,22 +1922,26 @@ var installGestures = (handle, mode, callbacks) => {
1875
1922
  };
1876
1923
  const onPointerCancel = (e) => {
1877
1924
  if (e.pointerId !== activePointerId) return;
1878
- activePointerId = null;
1879
- samples.reset();
1925
+ const wasPending = pendingStart;
1926
+ releaseTracking();
1927
+ if (wasPending) return;
1880
1928
  callbacks.onCancel?.();
1881
1929
  };
1882
1930
  handle.addEventListener("pointerdown", onPointerDown);
1883
1931
  handle.addEventListener("pointermove", onPointerMove);
1884
1932
  handle.addEventListener("pointerup", finishGesture);
1885
1933
  handle.addEventListener("pointercancel", onPointerCancel);
1934
+ const managesTouchAction = options.manageTouchAction !== false;
1886
1935
  const prevTouchAction = handle.style.touchAction;
1887
- handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
1936
+ if (managesTouchAction) {
1937
+ handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
1938
+ }
1888
1939
  return () => {
1889
1940
  handle.removeEventListener("pointerdown", onPointerDown);
1890
1941
  handle.removeEventListener("pointermove", onPointerMove);
1891
1942
  handle.removeEventListener("pointerup", finishGesture);
1892
1943
  handle.removeEventListener("pointercancel", onPointerCancel);
1893
- handle.style.touchAction = prevTouchAction;
1944
+ if (managesTouchAction) handle.style.touchAction = prevTouchAction;
1894
1945
  if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
1895
1946
  handle.releasePointerCapture(activePointerId);
1896
1947
  }
@@ -2009,7 +2060,7 @@ var GestureController = class {
2009
2060
  const restoreTo = this.dragStartSize;
2010
2061
  void this.deps.animateTo(restoreTo, 0);
2011
2062
  }
2012
- });
2063
+ }, this.deps.gestureOptions);
2013
2064
  return this.detach;
2014
2065
  }
2015
2066
  forceClearDragState() {
@@ -2021,6 +2072,74 @@ var GestureController = class {
2021
2072
  }
2022
2073
  };
2023
2074
 
2075
+ // src/core/primitives/drag-zones.ts
2076
+ var DRAG_ZONE_SELECTOR = "[data-bs-drag]";
2077
+ var NO_DRAG_SELECTOR = "[data-bs-no-drag]";
2078
+ var asElement = (target) => {
2079
+ const candidate = target;
2080
+ return candidate && typeof candidate.closest === "function" ? candidate : null;
2081
+ };
2082
+ function isDragAllowedFrom(target, mode) {
2083
+ const el = asElement(target);
2084
+ if (!el) return mode !== "zones";
2085
+ if (el.closest(NO_DRAG_SELECTOR)) return false;
2086
+ if (mode === "zones") return el.closest(DRAG_ZONE_SELECTOR) !== null;
2087
+ return true;
2088
+ }
2089
+
2090
+ // src/core/primitives/content-gesture.ts
2091
+ var CONTENT_DRAG_SLOP = 6;
2092
+ function decideContentGesture(input) {
2093
+ const slop = input.slop ?? CONTENT_DRAG_SLOP;
2094
+ const cross = input.crossDelta ?? 0;
2095
+ const sharesScrollAxis = input.sharesScrollAxis ?? true;
2096
+ if (!sharesScrollAxis) {
2097
+ if (Math.abs(input.delta) < slop && Math.abs(cross) < slop) return "pending";
2098
+ if (Math.abs(input.delta) <= Math.abs(cross)) return "scroll";
2099
+ return "drag";
2100
+ }
2101
+ if (Math.abs(input.delta) < slop) return "pending";
2102
+ if (input.scrollTop > 0) return "scroll";
2103
+ if (input.delta > 0 && input.atMaxSnap) return "scroll";
2104
+ return "drag";
2105
+ }
2106
+
2107
+ // src/core/primitives/logical-mode.ts
2108
+ var isLogicalMode = (mode) => mode === "start" || mode === "end";
2109
+ var readDirection = (el) => {
2110
+ if (!el) return "ltr";
2111
+ if (typeof getComputedStyle === "function") {
2112
+ try {
2113
+ if (getComputedStyle(el).direction === "rtl") return "rtl";
2114
+ } catch {
2115
+ }
2116
+ }
2117
+ try {
2118
+ const marked = el.closest?.("[dir]");
2119
+ if (marked) {
2120
+ return marked.getAttribute("dir")?.toLowerCase() === "rtl" ? "rtl" : "ltr";
2121
+ }
2122
+ } catch {
2123
+ }
2124
+ return "ltr";
2125
+ };
2126
+ var resolveMode = (mode, el) => {
2127
+ if (!isLogicalMode(mode)) return mode;
2128
+ const rtl = readDirection(el) === "rtl";
2129
+ if (mode === "start") return rtl ? "right" : "left";
2130
+ return rtl ? "left" : "right";
2131
+ };
2132
+
2133
+ // src/core/primitives/touch-scroll-guard.ts
2134
+ function installTouchScrollGuard(surface, isDragging) {
2135
+ const onTouchMove = (e) => {
2136
+ if (!isDragging()) return;
2137
+ if (e.cancelable) e.preventDefault();
2138
+ };
2139
+ surface.addEventListener("touchmove", onTouchMove, { passive: false });
2140
+ return () => surface.removeEventListener("touchmove", onTouchMove);
2141
+ }
2142
+
2024
2143
  // src/core/primitives/aria-slider-writer.ts
2025
2144
  var AriaSliderWriter = class {
2026
2145
  constructor(handle, mode) {
@@ -2373,9 +2492,11 @@ function resolveEngineOptions(opts, extras) {
2373
2492
  }
2374
2493
  }
2375
2494
  return {
2376
- mode: opts.mode ?? "bottom",
2495
+ mode: resolveMode(opts.mode ?? "bottom", opts.element),
2377
2496
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2378
2497
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2498
+ dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
2499
+ dragFromContent: opts.dragFromContent ?? true,
2379
2500
  rubberBandEnabled: opts.rubberBand ?? true,
2380
2501
  closeOnBack: opts.closeOnBack ?? false,
2381
2502
  persistent: opts.persistent ?? false,
@@ -2461,6 +2582,8 @@ var BottomSheetCore = class {
2461
2582
  __publicField(this, "mode");
2462
2583
  __publicField(this, "flickVelocity");
2463
2584
  __publicField(this, "dragThreshold");
2585
+ __publicField(this, "dragFromMode");
2586
+ __publicField(this, "dragFromContentDefault");
2464
2587
  __publicField(this, "rubberBandEnabled");
2465
2588
  __publicField(this, "scrim");
2466
2589
  __publicField(this, "aria");
@@ -2473,13 +2596,18 @@ var BottomSheetCore = class {
2473
2596
  __publicField(this, "disableDragFlag");
2474
2597
  __publicField(this, "closeOnRouteChange");
2475
2598
  __publicField(this, "maxHeight");
2599
+ __publicField(this, "maxHeightDeps");
2476
2600
  __publicField(this, "snapPointsRaw");
2477
2601
  __publicField(this, "snaps");
2478
2602
  __publicField(this, "activeId");
2479
2603
  __publicField(this, "size", 0);
2480
2604
  __publicField(this, "gesture");
2605
+ __publicField(this, "contentGesture");
2606
+ __publicField(this, "detachSheetGesture", null);
2607
+ __publicField(this, "detachSliderKeyboard", null);
2481
2608
  __publicField(this, "rootEl", null);
2482
2609
  __publicField(this, "destroyed", false);
2610
+ __publicField(this, "restClosed", false);
2483
2611
  __publicField(this, "currentViewTransition", null);
2484
2612
  __publicField(this, "currentAbort", new AbortController());
2485
2613
  __publicField(this, "sizeWriteSentinel", new WriteSentinel());
@@ -2528,10 +2656,13 @@ var BottomSheetCore = class {
2528
2656
  this.screenComponent = opts.scrim ?? opts.screenComponent;
2529
2657
  this.scrimParent = this.screenComponent?.parentElement ?? null;
2530
2658
  this.mode = resolved.mode;
2659
+ this.element.dataset.mode = this.mode;
2531
2660
  this.transformTemplate = buildTransformTemplate(this.mode);
2532
2661
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2533
2662
  this.flickVelocity = resolved.flickVelocity;
2534
2663
  this.dragThreshold = resolved.dragThreshold;
2664
+ this.dragFromMode = resolved.dragFrom;
2665
+ this.dragFromContentDefault = resolved.dragFromContent;
2535
2666
  this.rubberBandEnabled = resolved.rubberBandEnabled;
2536
2667
  this.scrim = new ScrimController(
2537
2668
  {
@@ -2558,7 +2689,7 @@ var BottomSheetCore = class {
2558
2689
  getRootEl: () => this.rootEl,
2559
2690
  applySize: (size) => this.applySize(size),
2560
2691
  getSize: () => this.size,
2561
- isDragging: () => this.gesture?.isDragging ?? false,
2692
+ isDragging: () => this.isDraggingAny(),
2562
2693
  applyAux: (size) => this.applySize(size, true),
2563
2694
  getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2564
2695
  },
@@ -2592,7 +2723,7 @@ var BottomSheetCore = class {
2592
2723
  auditVhUsage(this.snapPointsRaw);
2593
2724
  this.auditDuplicateSnapIds(this.snapPointsRaw);
2594
2725
  this.rootEl = this.element.closest(".bs-root");
2595
- this.maxHeight = createMaxHeightController({
2726
+ this.maxHeightDeps = {
2596
2727
  element: this.element,
2597
2728
  mode: this.mode,
2598
2729
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
@@ -2600,7 +2731,8 @@ var BottomSheetCore = class {
2600
2731
  this.snaps.setMaxAxisSize(size);
2601
2732
  },
2602
2733
  recompute: () => this.recompute()
2603
- });
2734
+ };
2735
+ this.maxHeight = createMaxHeightController(this.maxHeightDeps);
2604
2736
  this.fitDeps = {
2605
2737
  element: this.element,
2606
2738
  scrollContainer: this.scrollContainer,
@@ -2619,6 +2751,7 @@ var BottomSheetCore = class {
2619
2751
  const initial = this.snaps.findById(this.activeId);
2620
2752
  if (initial) this.size = initial.size;
2621
2753
  this.applySize(this.size);
2754
+ this.setRestClosed(this.size === 0);
2622
2755
  this.updateAriaSlider();
2623
2756
  this.scrollCache = createScrollCache({
2624
2757
  scrollContainer: this.scrollContainer,
@@ -2649,7 +2782,7 @@ var BottomSheetCore = class {
2649
2782
  (p) => p.size === "fit" || p.size === "content"
2650
2783
  ),
2651
2784
  isDestroyed: () => this.destroyed,
2652
- isDragging: () => this.gesture?.isDragging ?? false,
2785
+ isDragging: () => this.isDraggingAny(),
2653
2786
  recompute: () => this.recompute()
2654
2787
  })
2655
2788
  );
@@ -2675,7 +2808,7 @@ var BottomSheetCore = class {
2675
2808
  autoCollapseAfter
2676
2809
  },
2677
2810
  isDestroyed: () => this.destroyed,
2678
- isDragging: () => this.gesture?.isDragging ?? false,
2811
+ isDragging: () => this.isDraggingAny(),
2679
2812
  isAnimating: () => this.animation.isAnimating,
2680
2813
  isTopSheet: () => this.isTopSheet,
2681
2814
  isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
@@ -2705,6 +2838,7 @@ var BottomSheetCore = class {
2705
2838
  void this.snapTo(id);
2706
2839
  },
2707
2840
  close: (reason) => this.close(reason),
2841
+ attachDragSurface: (surface, kind) => this.attachDragSurface(surface, kind),
2708
2842
  on: (event, fn) => this.on(event, fn),
2709
2843
  addTeardown: (fn) => this.teardowns.add(fn)
2710
2844
  };
@@ -2733,7 +2867,7 @@ var BottomSheetCore = class {
2733
2867
  return {
2734
2868
  size: this.size,
2735
2869
  activeId: this.activeId,
2736
- isDragging: this.gesture?.isDragging ?? false,
2870
+ isDragging: this.isDraggingAny(),
2737
2871
  isAnimating: this.animation.isAnimating,
2738
2872
  progress: this.computeProgress(this.size)
2739
2873
  };
@@ -2853,9 +2987,16 @@ var BottomSheetCore = class {
2853
2987
  progress: this.computeProgress(this.size)
2854
2988
  });
2855
2989
  if (withHaptic) this.haptic();
2990
+ this.setRestClosed(targetSize === 0);
2856
2991
  if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
2857
2992
  if (targetSize === 0) this.emitCloseSequence();
2858
2993
  }
2994
+ setRestClosed(closed) {
2995
+ if (closed === this.restClosed) return;
2996
+ this.restClosed = closed;
2997
+ if (closed) this.element.setAttribute("data-bs-rest", "closed");
2998
+ else this.element.removeAttribute("data-bs-rest");
2999
+ }
2859
3000
  emitOpenSequence(id) {
2860
3001
  this.emit("open", { id });
2861
3002
  this.handleOpen();
@@ -2911,6 +3052,51 @@ var BottomSheetCore = class {
2911
3052
  if (this.destroyed) return;
2912
3053
  this.disableDragFlag = value;
2913
3054
  }
3055
+ setDragFromContent(value) {
3056
+ if (this.destroyed) return;
3057
+ this.dragFromContentDefault = value;
3058
+ }
3059
+ setDragFrom(mode) {
3060
+ if (this.destroyed || mode === this.dragFromMode) return;
3061
+ this.gesture?.forceClearDragState();
3062
+ this.detachSheetGesture?.();
3063
+ this.dragFromMode = mode;
3064
+ this.mountSheetGesture();
3065
+ }
3066
+ getDragFrom() {
3067
+ return this.dragFromMode;
3068
+ }
3069
+ setMode(mode) {
3070
+ if (this.destroyed) return;
3071
+ const next = resolveMode(mode, this.element);
3072
+ if (next === this.mode) return;
3073
+ const wasVertical = this.mode === "bottom" || this.mode === "top";
3074
+ const nowVertical = next === "bottom" || next === "top";
3075
+ this.gesture?.forceClearDragState();
3076
+ this.detachSheetGesture?.();
3077
+ this.animation.cancel();
3078
+ this.element.style.removeProperty(layoutAxis(this.mode));
3079
+ this.mode = next;
3080
+ this.element.dataset.mode = next;
3081
+ this.transformTemplate = buildTransformTemplate(next);
3082
+ this.maxHeightDeps.mode = next;
3083
+ this.fitDeps.mode = next;
3084
+ this.snaps.setMode(next);
3085
+ this.scrim.setSheetMode(next);
3086
+ if (wasVertical !== nowVertical) {
3087
+ this.aria = new AriaSliderWriter(this.handle, next);
3088
+ }
3089
+ this.detachSliderKeyboard?.();
3090
+ this.mountSliderKeyboard();
3091
+ this.mountSheetGesture();
3092
+ this.recompute();
3093
+ const active = this.snaps.findById(this.activeId);
3094
+ if (active) this.applySize(active.size);
3095
+ this.updateAriaSlider();
3096
+ }
3097
+ getMode() {
3098
+ return this.mode;
3099
+ }
2914
3100
  isTop() {
2915
3101
  return this.isTopSheet;
2916
3102
  }
@@ -3065,12 +3251,24 @@ var BottomSheetCore = class {
3065
3251
  auditVhUsage(points);
3066
3252
  this.auditDuplicateSnapIds(points);
3067
3253
  this.snaps.setRaw(points);
3068
- if (allowed) this.snaps.setAllowedIds(allowed);
3254
+ if (allowed) {
3255
+ this.snaps.setAllowedIds(allowed);
3256
+ } else {
3257
+ const present = this.snaps.getResolvedSnaps().map((s) => s.id);
3258
+ const kept = this.snaps.getAllowedIds().filter((id) => present.includes(id));
3259
+ this.snaps.setAllowedIds(kept.length ? kept : present);
3260
+ }
3069
3261
  this.scrollCache.clear();
3070
3262
  this.scrim.invalidateOpacityCache();
3071
3263
  const current = this.snaps.findById(this.activeId);
3072
3264
  if (current) {
3073
3265
  this.applySize(current.size);
3266
+ } else {
3267
+ const fallback = this.snaps.getResolvedSnaps().find((s) => this.snaps.getAllowedIds().includes(s.id)) ?? this.snaps.getResolvedSnaps()[0];
3268
+ if (fallback) {
3269
+ this.activeId = fallback.id;
3270
+ this.applySize(fallback.size);
3271
+ }
3074
3272
  }
3075
3273
  this.updateAriaSlider();
3076
3274
  }
@@ -3080,7 +3278,7 @@ var BottomSheetCore = class {
3080
3278
  this.snaps.recompute();
3081
3279
  this.maxHeight.clampTo();
3082
3280
  this.scrim.invalidateOpacityCache();
3083
- if (this.gesture?.isDragging) return;
3281
+ if (this.isDraggingAny()) return;
3084
3282
  this.healActiveSnap();
3085
3283
  }
3086
3284
  healActiveSnap() {
@@ -3102,6 +3300,8 @@ var BottomSheetCore = class {
3102
3300
  this.bus.clear();
3103
3301
  this.animation.cancel();
3104
3302
  this.gesture?.forceClearDragState();
3303
+ this.contentGesture?.forceClearDragState();
3304
+ this.setRestClosed(false);
3105
3305
  this.teardowns.drain();
3106
3306
  this.scrim.destroy();
3107
3307
  this.animation.destroy();
@@ -3214,11 +3414,12 @@ var BottomSheetCore = class {
3214
3414
  const scale = Math.max(1 - depth * 0.04, 0.86);
3215
3415
  this.element.style.scale = scale === 1 ? "" : String(scale);
3216
3416
  }
3217
- attach() {
3218
- this.gesture = new GestureController({
3219
- handle: this.handle,
3417
+ buildGestureDeps(surface, gestureOptions) {
3418
+ return {
3419
+ handle: surface,
3220
3420
  element: this.element,
3221
3421
  mode: this.mode,
3422
+ gestureOptions,
3222
3423
  getRoot: () => this.rootEl,
3223
3424
  getDragContext: () => {
3224
3425
  const buf = this.dragContextBuf;
@@ -3237,8 +3438,90 @@ var BottomSheetCore = class {
3237
3438
  settleAfterDrag: (delta, velocity, kind) => this.settleAfterDrag(delta, velocity, kind),
3238
3439
  emit: (event, payload) => this.emit(event, payload),
3239
3440
  listenerCount: (event) => this.bus.listenerCount(event)
3441
+ };
3442
+ }
3443
+ isContentDragAllowed() {
3444
+ if (this.disableDragFlag) return false;
3445
+ const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3446
+ return point?.dragFromContent ?? this.dragFromContentDefault;
3447
+ }
3448
+ decideContentDrag(surface, e, delta, crossDelta) {
3449
+ if (this.destroyed) return false;
3450
+ if (e.pointerType === "mouse") return false;
3451
+ if (this.gesture?.isDragging) return false;
3452
+ if (!this.isContentDragAllowed()) return false;
3453
+ if (!isDragAllowedFrom(e.target, "sheet")) return false;
3454
+ const decision = decideContentGesture({
3455
+ delta,
3456
+ crossDelta,
3457
+ sharesScrollAxis: this.mode === "bottom" || this.mode === "top",
3458
+ scrollTop: surface.scrollTop,
3459
+ atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3460
+ });
3461
+ if (decision === "pending") return null;
3462
+ return decision === "drag";
3463
+ }
3464
+ attachDragSurface(surface, kind) {
3465
+ if (this.destroyed || kind !== "content") return;
3466
+ if (this.contentGesture) return;
3467
+ const controller = new GestureController(
3468
+ this.buildGestureDeps(surface, {
3469
+ manageTouchAction: false,
3470
+ deferStart: (e, delta, crossDelta) => this.decideContentDrag(surface, e, delta, crossDelta)
3471
+ })
3472
+ );
3473
+ this.contentGesture = controller;
3474
+ const detachGestures = controller.install();
3475
+ const detachGuard = installTouchScrollGuard(
3476
+ surface,
3477
+ () => controller.isDragging
3478
+ );
3479
+ return () => {
3480
+ detachGuard();
3481
+ detachGestures();
3482
+ if (this.contentGesture === controller) this.contentGesture = void 0;
3483
+ };
3484
+ }
3485
+ sheetDragSurface() {
3486
+ return this.dragFromMode === "handle" ? this.handle : this.element;
3487
+ }
3488
+ canStartSheetDrag(e) {
3489
+ if (this.contentGesture?.isDragging) return false;
3490
+ const target = e.target;
3491
+ const scoped = typeof target?.closest === "function";
3492
+ if (scoped && target.closest(NO_DRAG_SELECTOR)) return false;
3493
+ if (this.handle !== this.element && scoped && this.handle.contains(target)) {
3494
+ return true;
3495
+ }
3496
+ if (!isDragAllowedFrom(e.target, this.dragFromMode)) return false;
3497
+ if (this.dragFromMode === "handle") return true;
3498
+ if (this.scrollContainer && scoped && this.scrollContainer.contains(target) && !target.closest(DRAG_ZONE_SELECTOR)) {
3499
+ return false;
3500
+ }
3501
+ return true;
3502
+ }
3503
+ mountSheetGesture() {
3504
+ const surface = this.sheetDragSurface();
3505
+ const controller = new GestureController(
3506
+ this.buildGestureDeps(surface, {
3507
+ shouldStart: (e) => this.canStartSheetDrag(e),
3508
+ manageTouchAction: this.dragFromMode === "handle"
3509
+ })
3510
+ );
3511
+ this.gesture = controller;
3512
+ const detachGestures = controller.install();
3513
+ const detachGuard = this.dragFromMode === "handle" ? null : installTouchScrollGuard(surface, () => controller.isDragging);
3514
+ this.detachSheetGesture = () => {
3515
+ detachGuard?.();
3516
+ detachGestures();
3517
+ };
3518
+ }
3519
+ attach() {
3520
+ this.mountSheetGesture();
3521
+ this.teardowns.add(() => {
3522
+ this.detachSheetGesture?.();
3523
+ this.detachSheetGesture = null;
3240
3524
  });
3241
- this.teardowns.add(this.gesture.install());
3242
3525
  try {
3243
3526
  this.attachFeatures();
3244
3527
  } catch (err) {
@@ -3275,7 +3558,7 @@ var BottomSheetCore = class {
3275
3558
  element: this.element,
3276
3559
  getMode: () => this.mode,
3277
3560
  isDestroyed: () => this.destroyed,
3278
- isDragging: () => this.gesture?.isDragging ?? false,
3561
+ isDragging: () => this.isDraggingAny(),
3279
3562
  resolveActiveSnap: () => this.snaps.findById(this.activeId),
3280
3563
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
3281
3564
  getSize: () => this.size,
@@ -3310,7 +3593,11 @@ var BottomSheetCore = class {
3310
3593
  );
3311
3594
  }
3312
3595
  }
3313
- this.teardowns.add(installSliderKeyboard({
3596
+ this.mountSliderKeyboard();
3597
+ this.scrim.attach();
3598
+ }
3599
+ mountSliderKeyboard() {
3600
+ const detach = installSliderKeyboard({
3314
3601
  handle: this.handle,
3315
3602
  mode: this.mode,
3316
3603
  isDestroyed: () => this.destroyed,
@@ -3319,8 +3606,12 @@ var BottomSheetCore = class {
3319
3606
  snapTo: (id) => {
3320
3607
  void this.snapTo(id);
3321
3608
  }
3322
- }));
3323
- this.scrim.attach();
3609
+ });
3610
+ this.detachSliderKeyboard = detach;
3611
+ this.teardowns.add(() => {
3612
+ this.detachSliderKeyboard?.();
3613
+ this.detachSliderKeyboard = null;
3614
+ });
3324
3615
  }
3325
3616
  settleAfterDrag(delta, velocity, kind = "touch") {
3326
3617
  const signal = this.newCycle();
@@ -3373,8 +3664,11 @@ var BottomSheetCore = class {
3373
3664
  );
3374
3665
  });
3375
3666
  }
3667
+ isDraggingAny() {
3668
+ return (this.gesture?.isDragging ?? false) || (this.contentGesture?.isDragging ?? false);
3669
+ }
3376
3670
  clearWillChangeIfIdle() {
3377
- if (this.animation.isAnimating || this.gesture?.isDragging) return;
3671
+ if (this.animation.isAnimating || this.isDraggingAny()) return;
3378
3672
  this.element.style.willChange = "";
3379
3673
  }
3380
3674
  haptic() {
@@ -3387,8 +3681,9 @@ var BottomSheetCore = class {
3387
3681
  }
3388
3682
  applySize(size, skipTransform = false) {
3389
3683
  const cap = this.snaps.getMaxAxisSize();
3390
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3684
+ const clamped = cap > 0 && size > cap && !this.isDraggingAny() && !this.allowOvershoot ? cap : size;
3391
3685
  this.size = clamped;
3686
+ if (clamped > 0) this.setRestClosed(false);
3392
3687
  const offset = cap - clamped;
3393
3688
  const style = this.element.style;
3394
3689
  if (!skipTransform) style.transform = this.transformTemplate(offset);
package/dist/debug.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { E as EngineState, d as SheetEventMap } from './BottomSheetCore-CsIjyq7C.cjs';
1
+ import { E as EngineState, S as SheetEventMap } from './BottomSheetCore-VPJZcKcg.cjs';
2
2
  import './transform-jVfAikE9.cjs';
3
3
 
4
4
  type DebugOverlayPosition = "top-left" | "top-right" | "bottom-left" | "bottom-right";
package/dist/debug.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { E as EngineState, d as SheetEventMap } from './BottomSheetCore-D16lsa6g.js';
1
+ import { E as EngineState, S as SheetEventMap } from './BottomSheetCore-Cgn8b_6A.js';
2
2
  import './transform-jVfAikE9.js';
3
3
 
4
4
  type DebugOverlayPosition = "top-left" | "top-right" | "bottom-left" | "bottom-right";