@surdeddd/bottom-sheet 0.13.0 → 0.14.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 +33 -0
  2. package/dist/{BottomSheetCore-CsIjyq7C.d.cts → BottomSheetCore-Cp7dWy91.d.cts} +26 -1
  3. package/dist/{BottomSheetCore-D16lsa6g.d.ts → BottomSheetCore-DJYwWOqt.d.ts} +26 -1
  4. package/dist/{BottomSheetEngine-BYjAVrmd.d.cts → BottomSheetEngine-Lm7HIVHv.d.cts} +1 -1
  5. package/dist/{BottomSheetEngine-YuCNugZn.d.ts → BottomSheetEngine-O5PbeKfe.d.ts} +1 -1
  6. package/dist/core.cjs +231 -27
  7. package/dist/core.d.cts +2 -2
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +231 -27
  10. package/dist/debug.d.cts +1 -1
  11. package/dist/debug.d.ts +1 -1
  12. package/dist/element.cjs +300 -102
  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 +300 -102
  17. package/dist/features.cjs +6 -50
  18. package/dist/features.d.cts +2 -2
  19. package/dist/features.d.ts +2 -2
  20. package/dist/features.js +6 -50
  21. package/dist/index-Bb5TRmyg.d.cts +9 -0
  22. package/dist/index-Cl9ebCP2.d.ts +9 -0
  23. package/dist/index.cjs +238 -823
  24. package/dist/index.d.cts +42 -45
  25. package/dist/index.d.ts +42 -45
  26. package/dist/index.js +239 -810
  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 +228 -77
  36. package/dist/qwik-lib/index.qwik.mjs +228 -77
  37. package/dist/qwik.cjs +245 -77
  38. package/dist/qwik.d.cts +4 -2
  39. package/dist/qwik.d.ts +4 -2
  40. package/dist/qwik.js +245 -77
  41. package/dist/react.cjs +250 -79
  42. package/dist/react.d.cts +3 -4
  43. package/dist/react.d.ts +3 -4
  44. package/dist/react.js +250 -79
  45. package/dist/solid.cjs +251 -77
  46. package/dist/solid.d.cts +27 -0
  47. package/dist/solid.d.ts +27 -0
  48. package/dist/solid.js +251 -77
  49. package/dist/solid.source.jsx +259 -77
  50. package/dist/styles.css +24 -4
  51. package/dist/svelte-core.cjs +237 -77
  52. package/dist/svelte-core.js +237 -77
  53. package/dist/svelte-src/BottomSheet.svelte +14 -0
  54. package/dist/svelte.cjs +247 -77
  55. package/dist/svelte.d.cts +2 -0
  56. package/dist/svelte.d.ts +2 -0
  57. package/dist/svelte.js +247 -77
  58. package/dist/vue.cjs +253 -77
  59. package/dist/vue.js +253 -77
  60. package/dist/webgl.cjs +583 -0
  61. package/dist/webgl.d.cts +17 -0
  62. package/dist/webgl.d.ts +17 -0
  63. package/dist/webgl.js +581 -0
  64. package/package.json +36 -12
  65. package/dist/index-DdYLOIIT.d.ts +0 -15
  66. package/dist/index-dfrzw-lI.d.cts +0 -15
package/dist/element.cjs CHANGED
@@ -12,10 +12,10 @@ var __export = (target, all) => {
12
12
  };
13
13
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
14
14
 
15
- // src/core/lifecycle/sheetStack.ts
15
+ // src/core/lifecycle/sheet-stack.ts
16
16
  var BASE_Z, STEP, SheetStack, sheetStack;
17
- var init_sheetStack = __esm({
18
- "src/core/lifecycle/sheetStack.ts"() {
17
+ var init_sheet_stack = __esm({
18
+ "src/core/lifecycle/sheet-stack.ts"() {
19
19
  BASE_Z = 100;
20
20
  STEP = 10;
21
21
  SheetStack = class {
@@ -156,10 +156,10 @@ var init_event_bus = __esm({
156
156
  }
157
157
  });
158
158
 
159
- // src/core/primitives/cssLength.ts
159
+ // src/core/primitives/css-length.ts
160
160
  var probe, PROBE_ATTR, ensureProbe, isViewportAxisVertical, viewportSize, PERCENT, resolveSnap;
161
- var init_cssLength = __esm({
162
- "src/core/primitives/cssLength.ts"() {
161
+ var init_css_length = __esm({
162
+ "src/core/primitives/css-length.ts"() {
163
163
  probe = null;
164
164
  PROBE_ATTR = "data-bs-probe";
165
165
  ensureProbe = (axis) => {
@@ -215,14 +215,14 @@ var init_cssLength = __esm({
215
215
  }
216
216
  });
217
217
 
218
- // src/core/primitives/devWarn.ts
218
+ // src/core/primitives/dev-warn.ts
219
219
  function devWarn(...args) {
220
220
  if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
221
221
  console.warn(...args);
222
222
  }
223
223
  }
224
- var init_devWarn = __esm({
225
- "src/core/primitives/devWarn.ts"() {
224
+ var init_dev_warn = __esm({
225
+ "src/core/primitives/dev-warn.ts"() {
226
226
  }
227
227
  });
228
228
 
@@ -230,8 +230,8 @@ var init_devWarn = __esm({
230
230
  var resolveSnapList, VH_NOT_DVH, auditVhUsage, findNearest, allowedRange, findById, MOUSE_FLICK_VELOCITY, MOUSE_DRAG_THRESHOLD, DIRECTIONAL_INTENT_VELOCITY, findDragSettleTarget;
231
231
  var init_snap_points = __esm({
232
232
  "src/core/primitives/snap-points.ts"() {
233
- init_cssLength();
234
- init_devWarn();
233
+ init_css_length();
234
+ init_dev_warn();
235
235
  resolveSnapList = (points, mode, measureFit) => points.map((p) => {
236
236
  const raw = resolveSnap(p.size, mode, measureFit);
237
237
  if (!Number.isFinite(raw) || raw < 0) {
@@ -324,7 +324,7 @@ function emitCancelable(emit, base, warnLabel) {
324
324
  }
325
325
  var init_cancelable_emit = __esm({
326
326
  "src/core/primitives/cancelable-emit.ts"() {
327
- init_devWarn();
327
+ init_dev_warn();
328
328
  }
329
329
  });
330
330
 
@@ -870,7 +870,7 @@ var init_scrim_controller = __esm({
870
870
  init_snap_points();
871
871
  init_hot_path_thresholds();
872
872
  init_opacity_dedup();
873
- init_devWarn();
873
+ init_dev_warn();
874
874
  init_overlay_position();
875
875
  VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
876
876
  DEFAULT_SCRIM_DIM = "rgba(0, 0, 0, 0.4)";
@@ -1660,10 +1660,10 @@ var init_animation_runner = __esm({
1660
1660
  }
1661
1661
  });
1662
1662
 
1663
- // src/core/lifecycle/focusTrap.ts
1663
+ // src/core/lifecycle/focus-trap.ts
1664
1664
  var FOCUSABLE, isVisible, collectFocusables, focusables, containsComposed, trapStack, installFocusTrap;
1665
- var init_focusTrap = __esm({
1666
- "src/core/lifecycle/focusTrap.ts"() {
1665
+ var init_focus_trap = __esm({
1666
+ "src/core/lifecycle/focus-trap.ts"() {
1667
1667
  FOCUSABLE = [
1668
1668
  "a[href]",
1669
1669
  "area[href]",
@@ -1783,10 +1783,10 @@ var init_focusTrap = __esm({
1783
1783
  }
1784
1784
  });
1785
1785
 
1786
- // src/core/lifecycle/scrollLock.ts
1786
+ // src/core/lifecycle/scroll-lock.ts
1787
1787
  var lockCount, savedStyles, lockBodyScroll;
1788
- var init_scrollLock = __esm({
1789
- "src/core/lifecycle/scrollLock.ts"() {
1788
+ var init_scroll_lock = __esm({
1789
+ "src/core/lifecycle/scroll-lock.ts"() {
1790
1790
  lockCount = 0;
1791
1791
  savedStyles = null;
1792
1792
  lockBodyScroll = () => {
@@ -1869,8 +1869,8 @@ var init_inert_siblings = __esm({
1869
1869
  var LifecycleController;
1870
1870
  var init_lifecycle_controller = __esm({
1871
1871
  "src/core/controllers/lifecycle-controller.ts"() {
1872
- init_focusTrap();
1873
- init_scrollLock();
1872
+ init_focus_trap();
1873
+ init_scroll_lock();
1874
1874
  init_inert_siblings();
1875
1875
  LifecycleController = class {
1876
1876
  constructor(deps, opts) {
@@ -1985,30 +1985,44 @@ var init_gestures = __esm({
1985
1985
  this.size = 0;
1986
1986
  }
1987
1987
  };
1988
- installGestures = (handle, mode, callbacks) => {
1988
+ installGestures = (handle, mode, callbacks, options = {}) => {
1989
1989
  let activePointerId = null;
1990
1990
  let activePointerType = "touch";
1991
1991
  let startCoord = 0;
1992
1992
  let lastCoord = 0;
1993
+ let pendingStart = false;
1993
1994
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
1994
1995
  const MAX_SAMPLES = 32;
1995
1996
  const samples = new SampleRing(MAX_SAMPLES);
1996
1997
  const axis = isAxisVertical(mode) ? "Y" : "X";
1997
1998
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1998
1999
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
2000
+ const capture = (pointerId) => {
2001
+ try {
2002
+ handle.setPointerCapture(pointerId);
2003
+ } catch {
2004
+ }
2005
+ };
2006
+ const releaseTracking = () => {
2007
+ activePointerId = null;
2008
+ pendingStart = false;
2009
+ samples.reset();
2010
+ };
1999
2011
  const onPointerDown = (e) => {
2000
2012
  if (activePointerId !== null) return;
2001
2013
  if (e.button !== void 0 && e.button !== 0) return;
2014
+ if (options.shouldStart && !options.shouldStart(e)) return;
2002
2015
  activePointerId = e.pointerId;
2003
2016
  activePointerType = e.pointerType || "touch";
2004
2017
  startCoord = coordOf(e);
2005
2018
  lastCoord = startCoord;
2006
2019
  samples.reset();
2007
2020
  samples.push(e.timeStamp, startCoord);
2008
- try {
2009
- handle.setPointerCapture(e.pointerId);
2010
- } catch {
2021
+ if (options.deferStart) {
2022
+ pendingStart = true;
2023
+ return;
2011
2024
  }
2025
+ capture(e.pointerId);
2012
2026
  callbacks.onStart(startCoord, activePointerType);
2013
2027
  };
2014
2028
  const onPointerMove = (e) => {
@@ -2016,6 +2030,22 @@ var init_gestures = __esm({
2016
2030
  const coord = coordOf(e);
2017
2031
  const rawDelta = coord - startCoord;
2018
2032
  const delta = rawDelta * sign;
2033
+ if (pendingStart) {
2034
+ const verdict = options.deferStart(e, delta);
2035
+ if (verdict === false) {
2036
+ releaseTracking();
2037
+ return;
2038
+ }
2039
+ if (verdict !== true) return;
2040
+ pendingStart = false;
2041
+ startCoord = coord;
2042
+ lastCoord = coord;
2043
+ samples.reset();
2044
+ samples.push(e.timeStamp, coord);
2045
+ capture(e.pointerId);
2046
+ callbacks.onStart(startCoord, activePointerType);
2047
+ return;
2048
+ }
2019
2049
  lastCoord = coord;
2020
2050
  samples.push(e.timeStamp, coord);
2021
2051
  const cutoff = e.timeStamp - VELOCITY_WINDOW_MS(activePointerType);
@@ -2024,6 +2054,10 @@ var init_gestures = __esm({
2024
2054
  };
2025
2055
  const finishGesture = (e) => {
2026
2056
  if (e.pointerId !== activePointerId) return;
2057
+ if (pendingStart) {
2058
+ releaseTracking();
2059
+ return;
2060
+ }
2027
2061
  const rawDelta = lastCoord - startCoord;
2028
2062
  const delta = rawDelta * sign;
2029
2063
  let velocity = 0;
@@ -2046,22 +2080,26 @@ var init_gestures = __esm({
2046
2080
  };
2047
2081
  const onPointerCancel = (e) => {
2048
2082
  if (e.pointerId !== activePointerId) return;
2049
- activePointerId = null;
2050
- samples.reset();
2083
+ const wasPending = pendingStart;
2084
+ releaseTracking();
2085
+ if (wasPending) return;
2051
2086
  callbacks.onCancel?.();
2052
2087
  };
2053
2088
  handle.addEventListener("pointerdown", onPointerDown);
2054
2089
  handle.addEventListener("pointermove", onPointerMove);
2055
2090
  handle.addEventListener("pointerup", finishGesture);
2056
2091
  handle.addEventListener("pointercancel", onPointerCancel);
2092
+ const managesTouchAction = options.manageTouchAction !== false;
2057
2093
  const prevTouchAction = handle.style.touchAction;
2058
- handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
2094
+ if (managesTouchAction) {
2095
+ handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
2096
+ }
2059
2097
  return () => {
2060
2098
  handle.removeEventListener("pointerdown", onPointerDown);
2061
2099
  handle.removeEventListener("pointermove", onPointerMove);
2062
2100
  handle.removeEventListener("pointerup", finishGesture);
2063
2101
  handle.removeEventListener("pointercancel", onPointerCancel);
2064
- handle.style.touchAction = prevTouchAction;
2102
+ if (managesTouchAction) handle.style.touchAction = prevTouchAction;
2065
2103
  if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
2066
2104
  handle.releasePointerCapture(activePointerId);
2067
2105
  }
@@ -2196,7 +2234,7 @@ var init_gesture_controller = __esm({
2196
2234
  const restoreTo = this.dragStartSize;
2197
2235
  void this.deps.animateTo(restoreTo, 0);
2198
2236
  }
2199
- });
2237
+ }, this.deps.gestureOptions);
2200
2238
  return this.detach;
2201
2239
  }
2202
2240
  forceClearDragState() {
@@ -2210,6 +2248,55 @@ var init_gesture_controller = __esm({
2210
2248
  }
2211
2249
  });
2212
2250
 
2251
+ // src/core/primitives/drag-zones.ts
2252
+ function isDragAllowedFrom(target, mode) {
2253
+ const el = asElement(target);
2254
+ if (!el) return mode !== "zones";
2255
+ if (el.closest(NO_DRAG_SELECTOR)) return false;
2256
+ if (mode === "zones") return el.closest(DRAG_ZONE_SELECTOR) !== null;
2257
+ return true;
2258
+ }
2259
+ var DRAG_ZONE_SELECTOR, NO_DRAG_SELECTOR, asElement;
2260
+ var init_drag_zones = __esm({
2261
+ "src/core/primitives/drag-zones.ts"() {
2262
+ DRAG_ZONE_SELECTOR = "[data-bs-drag]";
2263
+ NO_DRAG_SELECTOR = "[data-bs-no-drag]";
2264
+ asElement = (target) => {
2265
+ const candidate = target;
2266
+ return candidate && typeof candidate.closest === "function" ? candidate : null;
2267
+ };
2268
+ }
2269
+ });
2270
+
2271
+ // src/core/primitives/content-gesture.ts
2272
+ function decideContentGesture(input) {
2273
+ const slop = input.slop ?? CONTENT_DRAG_SLOP;
2274
+ if (Math.abs(input.delta) < slop) return "pending";
2275
+ if (input.scrollTop > 0) return "scroll";
2276
+ if (input.delta > 0 && input.atMaxSnap) return "scroll";
2277
+ return "drag";
2278
+ }
2279
+ var CONTENT_DRAG_SLOP;
2280
+ var init_content_gesture = __esm({
2281
+ "src/core/primitives/content-gesture.ts"() {
2282
+ CONTENT_DRAG_SLOP = 6;
2283
+ }
2284
+ });
2285
+
2286
+ // src/core/primitives/touch-scroll-guard.ts
2287
+ function installTouchScrollGuard(surface, isDragging) {
2288
+ const onTouchMove = (e) => {
2289
+ if (!isDragging()) return;
2290
+ if (e.cancelable) e.preventDefault();
2291
+ };
2292
+ surface.addEventListener("touchmove", onTouchMove, { passive: false });
2293
+ return () => surface.removeEventListener("touchmove", onTouchMove);
2294
+ }
2295
+ var init_touch_scroll_guard = __esm({
2296
+ "src/core/primitives/touch-scroll-guard.ts"() {
2297
+ }
2298
+ });
2299
+
2213
2300
  // src/core/primitives/aria-slider-writer.ts
2214
2301
  var AriaSliderWriter;
2215
2302
  var init_aria_slider_writer = __esm({
@@ -2591,6 +2678,8 @@ function resolveEngineOptions(opts, extras) {
2591
2678
  mode: opts.mode ?? "bottom",
2592
2679
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2593
2680
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2681
+ dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
2682
+ dragFromContent: opts.dragFromContent ?? true,
2594
2683
  rubberBandEnabled: opts.rubberBand ?? true,
2595
2684
  closeOnBack: opts.closeOnBack ?? false,
2596
2685
  persistent: opts.persistent ?? false,
@@ -2678,13 +2767,13 @@ var init_teardown_stack = __esm({
2678
2767
  var HAPTIC_DURATION_MS, BottomSheetCore;
2679
2768
  var init_BottomSheetCore = __esm({
2680
2769
  "src/core/BottomSheetCore.ts"() {
2681
- init_sheetStack();
2770
+ init_sheet_stack();
2682
2771
  init_transform();
2683
2772
  init_instance_id();
2684
2773
  init_event_bus();
2685
2774
  init_snap_points();
2686
2775
  init_cancelable_emit();
2687
- init_devWarn();
2776
+ init_dev_warn();
2688
2777
  init_snap_resolver();
2689
2778
  init_linked_sheets();
2690
2779
  init_resize_observer();
@@ -2696,6 +2785,9 @@ var init_BottomSheetCore = __esm({
2696
2785
  init_animation_runner();
2697
2786
  init_lifecycle_controller();
2698
2787
  init_gesture_controller();
2788
+ init_drag_zones();
2789
+ init_content_gesture();
2790
+ init_touch_scroll_guard();
2699
2791
  init_aria_slider_writer();
2700
2792
  init_hot_path_thresholds();
2701
2793
  init_scroll_cache();
@@ -2717,6 +2809,8 @@ var init_BottomSheetCore = __esm({
2717
2809
  __publicField(this, "mode");
2718
2810
  __publicField(this, "flickVelocity");
2719
2811
  __publicField(this, "dragThreshold");
2812
+ __publicField(this, "dragFromMode");
2813
+ __publicField(this, "dragFromContentDefault");
2720
2814
  __publicField(this, "rubberBandEnabled");
2721
2815
  __publicField(this, "scrim");
2722
2816
  __publicField(this, "aria");
@@ -2734,8 +2828,11 @@ var init_BottomSheetCore = __esm({
2734
2828
  __publicField(this, "activeId");
2735
2829
  __publicField(this, "size", 0);
2736
2830
  __publicField(this, "gesture");
2831
+ __publicField(this, "contentGesture");
2832
+ __publicField(this, "detachSheetGesture", null);
2737
2833
  __publicField(this, "rootEl", null);
2738
2834
  __publicField(this, "destroyed", false);
2835
+ __publicField(this, "restClosed", false);
2739
2836
  __publicField(this, "currentViewTransition", null);
2740
2837
  __publicField(this, "currentAbort", new AbortController());
2741
2838
  __publicField(this, "sizeWriteSentinel", new WriteSentinel());
@@ -2788,6 +2885,8 @@ var init_BottomSheetCore = __esm({
2788
2885
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2789
2886
  this.flickVelocity = resolved.flickVelocity;
2790
2887
  this.dragThreshold = resolved.dragThreshold;
2888
+ this.dragFromMode = resolved.dragFrom;
2889
+ this.dragFromContentDefault = resolved.dragFromContent;
2791
2890
  this.rubberBandEnabled = resolved.rubberBandEnabled;
2792
2891
  this.scrim = new ScrimController(
2793
2892
  {
@@ -2814,7 +2913,7 @@ var init_BottomSheetCore = __esm({
2814
2913
  getRootEl: () => this.rootEl,
2815
2914
  applySize: (size) => this.applySize(size),
2816
2915
  getSize: () => this.size,
2817
- isDragging: () => this.gesture?.isDragging ?? false,
2916
+ isDragging: () => this.isDraggingAny(),
2818
2917
  applyAux: (size) => this.applySize(size, true),
2819
2918
  getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2820
2919
  },
@@ -2875,6 +2974,7 @@ var init_BottomSheetCore = __esm({
2875
2974
  const initial = this.snaps.findById(this.activeId);
2876
2975
  if (initial) this.size = initial.size;
2877
2976
  this.applySize(this.size);
2977
+ this.setRestClosed(this.size === 0);
2878
2978
  this.updateAriaSlider();
2879
2979
  this.scrollCache = createScrollCache({
2880
2980
  scrollContainer: this.scrollContainer,
@@ -2905,7 +3005,7 @@ var init_BottomSheetCore = __esm({
2905
3005
  (p) => p.size === "fit" || p.size === "content"
2906
3006
  ),
2907
3007
  isDestroyed: () => this.destroyed,
2908
- isDragging: () => this.gesture?.isDragging ?? false,
3008
+ isDragging: () => this.isDraggingAny(),
2909
3009
  recompute: () => this.recompute()
2910
3010
  })
2911
3011
  );
@@ -2931,7 +3031,7 @@ var init_BottomSheetCore = __esm({
2931
3031
  autoCollapseAfter
2932
3032
  },
2933
3033
  isDestroyed: () => this.destroyed,
2934
- isDragging: () => this.gesture?.isDragging ?? false,
3034
+ isDragging: () => this.isDraggingAny(),
2935
3035
  isAnimating: () => this.animation.isAnimating,
2936
3036
  isTopSheet: () => this.isTopSheet,
2937
3037
  isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
@@ -2961,6 +3061,7 @@ var init_BottomSheetCore = __esm({
2961
3061
  void this.snapTo(id);
2962
3062
  },
2963
3063
  close: (reason) => this.close(reason),
3064
+ attachDragSurface: (surface, kind) => this.attachDragSurface(surface, kind),
2964
3065
  on: (event, fn) => this.on(event, fn),
2965
3066
  addTeardown: (fn) => this.teardowns.add(fn)
2966
3067
  };
@@ -2989,7 +3090,7 @@ var init_BottomSheetCore = __esm({
2989
3090
  return {
2990
3091
  size: this.size,
2991
3092
  activeId: this.activeId,
2992
- isDragging: this.gesture?.isDragging ?? false,
3093
+ isDragging: this.isDraggingAny(),
2993
3094
  isAnimating: this.animation.isAnimating,
2994
3095
  progress: this.computeProgress(this.size)
2995
3096
  };
@@ -3109,9 +3210,16 @@ var init_BottomSheetCore = __esm({
3109
3210
  progress: this.computeProgress(this.size)
3110
3211
  });
3111
3212
  if (withHaptic) this.haptic();
3213
+ this.setRestClosed(targetSize === 0);
3112
3214
  if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
3113
3215
  if (targetSize === 0) this.emitCloseSequence();
3114
3216
  }
3217
+ setRestClosed(closed) {
3218
+ if (closed === this.restClosed) return;
3219
+ this.restClosed = closed;
3220
+ if (closed) this.element.setAttribute("data-bs-rest", "closed");
3221
+ else this.element.removeAttribute("data-bs-rest");
3222
+ }
3115
3223
  emitOpenSequence(id) {
3116
3224
  this.emit("open", { id });
3117
3225
  this.handleOpen();
@@ -3167,6 +3275,20 @@ var init_BottomSheetCore = __esm({
3167
3275
  if (this.destroyed) return;
3168
3276
  this.disableDragFlag = value;
3169
3277
  }
3278
+ setDragFromContent(value) {
3279
+ if (this.destroyed) return;
3280
+ this.dragFromContentDefault = value;
3281
+ }
3282
+ setDragFrom(mode) {
3283
+ if (this.destroyed || mode === this.dragFromMode) return;
3284
+ this.gesture?.forceClearDragState();
3285
+ this.detachSheetGesture?.();
3286
+ this.dragFromMode = mode;
3287
+ this.mountSheetGesture();
3288
+ }
3289
+ getDragFrom() {
3290
+ return this.dragFromMode;
3291
+ }
3170
3292
  isTop() {
3171
3293
  return this.isTopSheet;
3172
3294
  }
@@ -3321,12 +3443,24 @@ var init_BottomSheetCore = __esm({
3321
3443
  auditVhUsage(points);
3322
3444
  this.auditDuplicateSnapIds(points);
3323
3445
  this.snaps.setRaw(points);
3324
- if (allowed) this.snaps.setAllowedIds(allowed);
3446
+ if (allowed) {
3447
+ this.snaps.setAllowedIds(allowed);
3448
+ } else {
3449
+ const present = this.snaps.getResolvedSnaps().map((s) => s.id);
3450
+ const kept = this.snaps.getAllowedIds().filter((id) => present.includes(id));
3451
+ this.snaps.setAllowedIds(kept.length ? kept : present);
3452
+ }
3325
3453
  this.scrollCache.clear();
3326
3454
  this.scrim.invalidateOpacityCache();
3327
3455
  const current = this.snaps.findById(this.activeId);
3328
3456
  if (current) {
3329
3457
  this.applySize(current.size);
3458
+ } else {
3459
+ const fallback = this.snaps.getResolvedSnaps().find((s) => this.snaps.getAllowedIds().includes(s.id)) ?? this.snaps.getResolvedSnaps()[0];
3460
+ if (fallback) {
3461
+ this.activeId = fallback.id;
3462
+ this.applySize(fallback.size);
3463
+ }
3330
3464
  }
3331
3465
  this.updateAriaSlider();
3332
3466
  }
@@ -3336,7 +3470,7 @@ var init_BottomSheetCore = __esm({
3336
3470
  this.snaps.recompute();
3337
3471
  this.maxHeight.clampTo();
3338
3472
  this.scrim.invalidateOpacityCache();
3339
- if (this.gesture?.isDragging) return;
3473
+ if (this.isDraggingAny()) return;
3340
3474
  this.healActiveSnap();
3341
3475
  }
3342
3476
  healActiveSnap() {
@@ -3358,6 +3492,8 @@ var init_BottomSheetCore = __esm({
3358
3492
  this.bus.clear();
3359
3493
  this.animation.cancel();
3360
3494
  this.gesture?.forceClearDragState();
3495
+ this.contentGesture?.forceClearDragState();
3496
+ this.setRestClosed(false);
3361
3497
  this.teardowns.drain();
3362
3498
  this.scrim.destroy();
3363
3499
  this.animation.destroy();
@@ -3470,11 +3606,12 @@ var init_BottomSheetCore = __esm({
3470
3606
  const scale = Math.max(1 - depth * 0.04, 0.86);
3471
3607
  this.element.style.scale = scale === 1 ? "" : String(scale);
3472
3608
  }
3473
- attach() {
3474
- this.gesture = new GestureController({
3475
- handle: this.handle,
3609
+ buildGestureDeps(surface, gestureOptions) {
3610
+ return {
3611
+ handle: surface,
3476
3612
  element: this.element,
3477
3613
  mode: this.mode,
3614
+ gestureOptions,
3478
3615
  getRoot: () => this.rootEl,
3479
3616
  getDragContext: () => {
3480
3617
  const buf = this.dragContextBuf;
@@ -3493,8 +3630,88 @@ var init_BottomSheetCore = __esm({
3493
3630
  settleAfterDrag: (delta, velocity, kind) => this.settleAfterDrag(delta, velocity, kind),
3494
3631
  emit: (event, payload) => this.emit(event, payload),
3495
3632
  listenerCount: (event) => this.bus.listenerCount(event)
3633
+ };
3634
+ }
3635
+ isContentDragAllowed() {
3636
+ if (this.disableDragFlag) return false;
3637
+ const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3638
+ return point?.dragFromContent ?? this.dragFromContentDefault;
3639
+ }
3640
+ decideContentDrag(surface, e, delta) {
3641
+ if (this.destroyed) return false;
3642
+ if (e.pointerType === "mouse") return false;
3643
+ if (this.gesture?.isDragging) return false;
3644
+ if (!this.isContentDragAllowed()) return false;
3645
+ if (!isDragAllowedFrom(e.target, "sheet")) return false;
3646
+ const decision = decideContentGesture({
3647
+ delta,
3648
+ scrollTop: surface.scrollTop,
3649
+ atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3650
+ });
3651
+ if (decision === "pending") return null;
3652
+ return decision === "drag";
3653
+ }
3654
+ attachDragSurface(surface, kind) {
3655
+ if (this.destroyed || kind !== "content") return;
3656
+ if (this.contentGesture) return;
3657
+ const controller = new GestureController(
3658
+ this.buildGestureDeps(surface, {
3659
+ manageTouchAction: false,
3660
+ deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
3661
+ })
3662
+ );
3663
+ this.contentGesture = controller;
3664
+ const detachGestures = controller.install();
3665
+ const detachGuard = installTouchScrollGuard(
3666
+ surface,
3667
+ () => controller.isDragging
3668
+ );
3669
+ return () => {
3670
+ detachGuard();
3671
+ detachGestures();
3672
+ if (this.contentGesture === controller) this.contentGesture = void 0;
3673
+ };
3674
+ }
3675
+ sheetDragSurface() {
3676
+ return this.dragFromMode === "handle" ? this.handle : this.element;
3677
+ }
3678
+ canStartSheetDrag(e) {
3679
+ if (this.contentGesture?.isDragging) return false;
3680
+ const target = e.target;
3681
+ const scoped = typeof target?.closest === "function";
3682
+ if (scoped && target.closest(NO_DRAG_SELECTOR)) return false;
3683
+ if (this.handle !== this.element && scoped && this.handle.contains(target)) {
3684
+ return true;
3685
+ }
3686
+ if (!isDragAllowedFrom(e.target, this.dragFromMode)) return false;
3687
+ if (this.dragFromMode === "handle") return true;
3688
+ if (this.scrollContainer && scoped && this.scrollContainer.contains(target) && !target.closest(DRAG_ZONE_SELECTOR)) {
3689
+ return false;
3690
+ }
3691
+ return true;
3692
+ }
3693
+ mountSheetGesture() {
3694
+ const surface = this.sheetDragSurface();
3695
+ const controller = new GestureController(
3696
+ this.buildGestureDeps(surface, {
3697
+ shouldStart: (e) => this.canStartSheetDrag(e),
3698
+ manageTouchAction: this.dragFromMode === "handle"
3699
+ })
3700
+ );
3701
+ this.gesture = controller;
3702
+ const detachGestures = controller.install();
3703
+ const detachGuard = this.dragFromMode === "handle" ? null : installTouchScrollGuard(surface, () => controller.isDragging);
3704
+ this.detachSheetGesture = () => {
3705
+ detachGuard?.();
3706
+ detachGestures();
3707
+ };
3708
+ }
3709
+ attach() {
3710
+ this.mountSheetGesture();
3711
+ this.teardowns.add(() => {
3712
+ this.detachSheetGesture?.();
3713
+ this.detachSheetGesture = null;
3496
3714
  });
3497
- this.teardowns.add(this.gesture.install());
3498
3715
  try {
3499
3716
  this.attachFeatures();
3500
3717
  } catch (err) {
@@ -3531,7 +3748,7 @@ var init_BottomSheetCore = __esm({
3531
3748
  element: this.element,
3532
3749
  getMode: () => this.mode,
3533
3750
  isDestroyed: () => this.destroyed,
3534
- isDragging: () => this.gesture?.isDragging ?? false,
3751
+ isDragging: () => this.isDraggingAny(),
3535
3752
  resolveActiveSnap: () => this.snaps.findById(this.activeId),
3536
3753
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
3537
3754
  getSize: () => this.size,
@@ -3629,8 +3846,11 @@ var init_BottomSheetCore = __esm({
3629
3846
  );
3630
3847
  });
3631
3848
  }
3849
+ isDraggingAny() {
3850
+ return (this.gesture?.isDragging ?? false) || (this.contentGesture?.isDragging ?? false);
3851
+ }
3632
3852
  clearWillChangeIfIdle() {
3633
- if (this.animation.isAnimating || this.gesture?.isDragging) return;
3853
+ if (this.animation.isAnimating || this.isDraggingAny()) return;
3634
3854
  this.element.style.willChange = "";
3635
3855
  }
3636
3856
  haptic() {
@@ -3643,8 +3863,9 @@ var init_BottomSheetCore = __esm({
3643
3863
  }
3644
3864
  applySize(size, skipTransform = false) {
3645
3865
  const cap = this.snaps.getMaxAxisSize();
3646
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3866
+ const clamped = cap > 0 && size > cap && !this.isDraggingAny() && !this.allowOvershoot ? cap : size;
3647
3867
  this.size = clamped;
3868
+ if (clamped > 0) this.setRestClosed(false);
3648
3869
  const offset = cap - clamped;
3649
3870
  const style = this.element.style;
3650
3871
  if (!skipTransform) style.transform = this.transformTemplate(offset);
@@ -4044,54 +4265,13 @@ var init_auto_collapse = __esm({
4044
4265
  }
4045
4266
  });
4046
4267
 
4047
- // src/core/features/content-swipe.ts
4048
- function installContentSwipe(deps) {
4049
- const { container } = deps;
4050
- let startY = 0;
4051
- let startScrollTop = 0;
4052
- let moved = false;
4053
- const onTouchStart = (e) => {
4054
- const t = e.touches[0];
4055
- if (!t) return;
4056
- startY = t.clientY;
4057
- startScrollTop = container.scrollTop;
4058
- moved = false;
4059
- };
4060
- const onTouchMove = (e) => {
4061
- const t = e.touches[0];
4062
- if (!t) return;
4063
- if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
4064
- };
4065
- const onTouchEnd = (e) => {
4066
- if (!moved) return;
4067
- if (deps.isDragging() || deps.isAnimating()) return;
4068
- if (container.scrollTop !== startScrollTop) return;
4069
- const t = e.changedTouches[0];
4070
- if (!t) return;
4071
- const deltaY = t.clientY - startY;
4072
- const atTop = container.scrollTop <= 0;
4073
- const allowed = deps.getAllowedIds();
4074
- const idx = allowed.indexOf(deps.getActiveId());
4075
- if (idx === -1) return;
4076
- if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
4077
- deps.snapTo(allowed[idx - 1]);
4078
- } else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
4079
- deps.snapTo(allowed[idx + 1]);
4080
- }
4081
- };
4082
- container.addEventListener("touchstart", onTouchStart, { passive: true });
4083
- container.addEventListener("touchmove", onTouchMove, { passive: true });
4084
- container.addEventListener("touchend", onTouchEnd, { passive: true });
4085
- return () => {
4086
- container.removeEventListener("touchstart", onTouchStart);
4087
- container.removeEventListener("touchmove", onTouchMove);
4088
- container.removeEventListener("touchend", onTouchEnd);
4089
- };
4268
+ // src/core/features/content-drag.ts
4269
+ function installContentDrag(deps) {
4270
+ const detach = deps.attachDragSurface(deps.container, "content");
4271
+ return () => detach?.();
4090
4272
  }
4091
- var CONTENT_PULL_THRESHOLD;
4092
- var init_content_swipe = __esm({
4093
- "src/core/features/content-swipe.ts"() {
4094
- CONTENT_PULL_THRESHOLD = 60;
4273
+ var init_content_drag = __esm({
4274
+ "src/core/features/content-drag.ts"() {
4095
4275
  }
4096
4276
  });
4097
4277
 
@@ -4205,13 +4385,9 @@ function contentSwipeFeature() {
4205
4385
  stage: "attach",
4206
4386
  install: (ctx) => {
4207
4387
  if (!ctx.scrollContainer) return;
4208
- return installContentSwipe({
4388
+ return installContentDrag({
4209
4389
  container: ctx.scrollContainer,
4210
- isDragging: ctx.isDragging,
4211
- isAnimating: ctx.isAnimating,
4212
- getAllowedIds: ctx.allowedIdsBySize,
4213
- getActiveId: ctx.getActiveId,
4214
- snapTo: ctx.snapTo
4390
+ attachDragSurface: ctx.attachDragSurface
4215
4391
  });
4216
4392
  }
4217
4393
  };
@@ -4246,7 +4422,7 @@ var init_engine_features = __esm({
4246
4422
  init_route();
4247
4423
  init_persist();
4248
4424
  init_auto_collapse();
4249
- init_content_swipe();
4425
+ init_content_drag();
4250
4426
  init_visual_viewport();
4251
4427
  init_teardown_stack();
4252
4428
  }
@@ -4289,7 +4465,7 @@ var init_BottomSheetEngine = __esm({
4289
4465
  var baseStyles;
4290
4466
  var init_baseStyles = __esm({
4291
4467
  "src/web-component/baseStyles.ts"() {
4292
- baseStyles = `:where(.bs-root){--bs-surface-d:#ffffff;--bs-surface-border-d:rgba(225,227,237,1);--bs-radius-d:20px;--bs-handle-color-d:rgba(26,22,20,0.3);--bs-handle-width:40px;--bs-handle-height:5px;--bs-z-backdrop:90;--bs-z-sheet:100;--bs-backdrop-color-d:rgba(0,0,0,0.5);--bs-scrim-color-d:transparent;--bs-scrim-blur:0px;--bs-z-scrim:calc(var(--bs-z-sheet) - 1);--bs-size:0px;--bs-progress:0}.bs-backdrop{position:fixed;inset:0;background:var(--bs-backdrop-color,var(--bs-backdrop-color-d));opacity:0;pointer-events:none;z-index:var(--bs-z-backdrop);transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-backdrop,.bs-root[data-animating="true"] .bs-backdrop{transition:none}.bs-sheet{position:fixed;background:var(--bs-surface,var(--bs-surface-d));box-shadow:var(--bs-shadow,var(--bs-shadow-auto,none));z-index:var(--bs-z-sheet);pointer-events:auto;overflow:hidden;display:flex;flex-direction:column;-webkit-tap-highlight-color:transparent;user-select:none;overscroll-behavior:contain}.bs-sheet[data-mode="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));padding-bottom:env(safe-area-inset-bottom);--bs-shadow-auto:0 calc(var(--bs-progress,0) * -2px - 3px) calc(var(--bs-progress,0) * 18px + 12px) rgba(0,0,0,calc(var(--bs-progress,0) * 0.15 + 0.12))}.bs-sheet[data-mode="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom:1px solid var(--bs-surface-border,var(--bs-surface-border-d));flex-direction:column-reverse;--bs-shadow-auto:0 3px 12px rgba(0,0,0,0.12);padding-top:env(safe-area-inset-top)}.bs-sheet[data-mode="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:3px 0 12px rgba(0,0,0,0.12)}.bs-sheet[data-mode="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:-3px 0 12px rgba(0,0,0,0.12)}.bs-sheet[data-mode="left"] .bs-content{padding-right:36px}.bs-sheet[data-mode="right"] .bs-content{padding-left:36px}.bs-handle{flex-shrink:0;min-height:44px;display:flex;flex-direction:column;justify-content:center;padding:var(--bs-handle-padding,8px 16px 4px);cursor:grab;touch-action:none;user-select:none;background:var(--bs-surface,var(--bs-surface-d));-webkit-tap-highlight-color:transparent;outline:none;position:relative}.bs-handle:active{cursor:grabbing}.bs-handle:focus-visible{outline:2px solid currentColor;outline-offset:-2px;border-radius:var(--bs-radius,var(--bs-radius-d))}.bs-handle::before{content:"";display:block;width:var(--bs-handle-width);height:var(--bs-handle-height);background:var(--bs-handle-color,var(--bs-handle-color-d));border-radius:calc(var(--bs-handle-height) / 2);margin:0 auto 8px;transition:width 0.15s ease,background 0.15s ease,transform 0.15s ease;pointer-events:none}.bs-sheet[data-mode="left"] .bs-handle,.bs-sheet[data-mode="right"] .bs-handle{position:absolute;top:0;bottom:0;width:28px;min-width:0;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0;background:var(--bs-surface,var(--bs-surface-d));z-index:1;overflow:hidden}.bs-sheet[data-mode="left"] .bs-handle>*,.bs-sheet[data-mode="right"] .bs-handle>*{display:none}.bs-sheet[data-mode="left"] .bs-handle{right:0;border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="right"] .bs-handle{left:0;border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="left"] .bs-handle::before,.bs-sheet[data-mode="right"] .bs-handle::before{width:var(--bs-handle-height);height:var(--bs-handle-width);margin:0}.bs-sheet:hover .bs-handle::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 15%)}.bs-handle:active::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 35%);transform:scaleX(1.15)}.bs-handle.bs-handle--ticks::after{content:"";display:block;position:absolute;left:50%;bottom:6px;transform:translateX(-50%);width:calc(var(--bs-handle-width) * 2);height:3px;background-image:radial-gradient( circle,var(--bs-handle-color,var(--bs-handle-color-d)) 0 1.5px,transparent 1.6px );background-size:8px 3px;background-repeat:repeat-x;background-position:center;opacity:0;transition:opacity 0.18s ease-out;pointer-events:none}.bs-root[data-dragging="true"] .bs-handle.bs-handle--ticks::after{opacity:0.4}.bs-sheet[data-mode="top"] .bs-handle.bs-handle--ticks::after{bottom:auto;top:6px}.bs-sheet[data-mode="left"] .bs-handle.bs-handle--ticks::after,.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{left:50%;top:50%;bottom:auto;transform:translate(-50%,-50%);width:3px;height:calc(var(--bs-handle-width) * 2);background-size:3px 8px;background-repeat:repeat-y;margin-left:calc(var(--bs-handle-height) + 6px)}.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{margin-left:calc(-1 * (var(--bs-handle-height) + 6px))}.bs-header{flex:0 0 auto;min-height:var(--bs-header-min-height,0px);padding:var(--bs-header-padding,0 16px 8px);background:var(--bs-surface,var(--bs-surface-d))}.bs-content{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;user-select:text;padding:var(--bs-content-padding,0 16px 16px)}.bs-footer{flex:0 0 auto;padding:var(--bs-footer-padding,12px 16px calc(12px + env(safe-area-inset-bottom)));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));background:var(--bs-surface,var(--bs-surface-d))}.bs-sheet[data-mode="bottom"]:has(.bs-footer:not([hidden]):has(*)){padding-bottom:0}.bs-header:not(:has(*)),.bs-footer:not(:has(*)),.bs-header[hidden],.bs-footer[hidden]{display:none}.bs-screen{position:absolute;inset:0;pointer-events:none;z-index:var(--bs-z-scrim);background:var(--bs-scrim-color,var(--bs-scrim-color-d));backdrop-filter:blur(var(--bs-scrim-blur,0px));-webkit-backdrop-filter:blur(var(--bs-scrim-blur,0px));transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-screen,.bs-root[data-animating="true"] .bs-screen{transition:none}.bs-scrim-overlay{z-index:calc(var(--bs-z-sheet) + 1);pointer-events:none}.bs-button-slot{position:fixed;z-index:calc(var(--bs-z-sheet) + 1);pointer-events:auto}.bs-button-slot[data-side="left"]{left:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-side="right"]{right:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="top"]{bottom:auto;top:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="left"]{left:calc(var(--bs-size,0px) + 12px);right:auto;bottom:auto;top:16px}.bs-button-slot[data-mode="right"]{right:calc(var(--bs-size,0px) + 12px);left:auto;bottom:auto;top:16px}@media (prefers-reduced-motion:reduce){.bs-backdrop,.bs-handle::before,.bs-button-slot[data-side="left"],.bs-button-slot[data-side="right"]{transition:none !important}}@media (prefers-color-scheme:dark){:where(.bs-root){--bs-surface-d:#1a1a1d;--bs-surface-border-d:rgba(255,255,255,0.08);--bs-handle-color-d:rgba(255,255,255,0.45);--bs-shadow-auto:0 -3px 16px rgba(0,0,0,0.5)}}@media (forced-colors:active){.bs-sheet{border:1px solid CanvasText}.bs-handle::before{background:CanvasText;forced-color-adjust:none}.bs-backdrop,.bs-screen{forced-color-adjust:none}}.bs-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:where(.ovl-root){--ovl-surface:var(--bs-surface,var(--bs-surface-d,#ffffff));--ovl-surface-border:var(--bs-surface-border,var(--bs-surface-border-d,rgba(0,0,0,0.08)));--ovl-shadow:0 -8px 40px rgba(0,0,0,0.35);--ovl-radius:var(--bs-radius,var(--bs-radius-d,20px));--ovl-backdrop-color:rgba(0,0,0,0.5);--ovl-z-backdrop:200;--ovl-z-panel:201}.ovl-backdrop{position:fixed;inset:0;background:var(--ovl-backdrop-color);opacity:0;pointer-events:none;z-index:var(--ovl-z-backdrop)}.ovl-panel{position:fixed;background:var(--ovl-surface);box-shadow:var(--ovl-shadow);z-index:var(--ovl-z-panel);-webkit-tap-highlight-color:transparent;outline:none;transition:transform 0.32s cubic-bezier(0.29,1.24,0.84,0.99),opacity 0.32s ease-out}.ovl-panel[data-state="open"]{transform:translate3d(0,0,0);opacity:1}@starting-style{.ovl-panel[data-edge="bottom"][data-state="open"]{transform:translate3d(0,100%,0);opacity:0}.ovl-panel[data-edge="top"][data-state="open"]{transform:translate3d(0,-100%,0);opacity:0}.ovl-panel[data-edge="left"][data-state="open"]{transform:translate3d(-100%,0,0);opacity:0}.ovl-panel[data-edge="right"][data-state="open"]{transform:translate3d(100%,0,0);opacity:0}}.ovl-panel[data-edge="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--ovl-radius);border-top-right-radius:var(--ovl-radius);border-top:1px solid var(--ovl-surface-border);padding-bottom:env(safe-area-inset-bottom)}.ovl-panel[data-edge="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-bottom:1px solid var(--ovl-surface-border);padding-top:env(safe-area-inset-top)}.ovl-panel[data-edge="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-right:1px solid var(--ovl-surface-border)}.ovl-panel[data-edge="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--ovl-radius);border-bottom-left-radius:var(--ovl-radius);border-left:1px solid var(--ovl-surface-border)}@media (prefers-reduced-motion:reduce){.ovl-panel,.ovl-backdrop{transition:none !important}}`;
4468
+ baseStyles = `:where(.bs-root){--bs-surface-d:#ffffff;--bs-surface-border-d:rgba(225,227,237,1);--bs-radius-d:20px;--bs-handle-color-d:rgba(26,22,20,0.3);--bs-handle-width:40px;--bs-handle-height:5px;--bs-z-backdrop:90;--bs-z-sheet:100;--bs-backdrop-color-d:rgba(0,0,0,0.5);--bs-scrim-color-d:transparent;--bs-scrim-blur:0px;--bs-z-scrim:calc(var(--bs-z-sheet) - 1);--bs-size:0px;--bs-progress:0}.bs-backdrop{position:fixed;inset:0;background:var(--bs-backdrop-color,var(--bs-backdrop-color-d));opacity:0;pointer-events:none;z-index:var(--bs-z-backdrop);transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-backdrop,.bs-root[data-animating="true"] .bs-backdrop{transition:none}.bs-sheet{position:fixed;background:var(--bs-surface,var(--bs-surface-d));box-shadow:var(--bs-shadow,var(--bs-shadow-auto,none));--bs-shadow-fade:clamp(0,calc(var(--bs-progress,0) * 8),1);z-index:var(--bs-z-sheet);pointer-events:auto;overflow:hidden;display:flex;flex-direction:column;-webkit-tap-highlight-color:transparent;user-select:none;overscroll-behavior:contain}.bs-sheet[data-mode="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));padding-bottom:env(safe-area-inset-bottom);--bs-shadow-auto:0 calc(var(--bs-progress,0) * -2px - 3px) calc(var(--bs-progress,0) * 18px + 12px) rgba( 0,0,0,calc(var(--bs-shadow-fade) * (var(--bs-progress,0) * 0.15 + 0.12)) )}.bs-sheet[data-mode="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom:1px solid var(--bs-surface-border,var(--bs-surface-border-d));flex-direction:column-reverse;--bs-shadow-auto:0 3px 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12));padding-top:env(safe-area-inset-top)}.bs-sheet[data-mode="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-right-radius:var(--bs-radius,var(--bs-radius-d));border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:3px 0 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12))}.bs-sheet[data-mode="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--bs-radius,var(--bs-radius-d));border-bottom-left-radius:var(--bs-radius,var(--bs-radius-d));border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d));--bs-shadow-auto:-3px 0 12px rgba(0,0,0,calc(var(--bs-shadow-fade) * 0.12))}.bs-sheet[data-bs-rest="closed"]{box-shadow:none;visibility:hidden}.bs-sheet[data-bs-webgl="on"],.bs-sheet[data-bs-webgl="on"] .bs-handle,.bs-sheet[data-bs-webgl="on"] .bs-header,.bs-sheet[data-bs-webgl="on"] .bs-footer{background:transparent;box-shadow:none}.bs-sheet[data-mode="left"] .bs-content{padding-right:36px}.bs-sheet[data-mode="right"] .bs-content{padding-left:36px}.bs-handle{flex-shrink:0;min-height:44px;display:flex;flex-direction:column;justify-content:center;padding:var(--bs-handle-padding,8px 16px 4px);cursor:grab;touch-action:none;user-select:none;background:var(--bs-surface,var(--bs-surface-d));-webkit-tap-highlight-color:transparent;outline:none;position:relative}.bs-handle:active{cursor:grabbing}.bs-handle:focus-visible{outline:2px solid currentColor;outline-offset:-2px;border-radius:var(--bs-radius,var(--bs-radius-d))}.bs-handle::before{content:"";display:block;width:var(--bs-handle-width);height:var(--bs-handle-height);background:var(--bs-handle-color,var(--bs-handle-color-d));border-radius:calc(var(--bs-handle-height) / 2);margin:0 auto 8px;transition:width 0.15s ease,background 0.15s ease,transform 0.15s ease;pointer-events:none}.bs-sheet[data-mode="left"] .bs-handle,.bs-sheet[data-mode="right"] .bs-handle{position:absolute;top:0;bottom:0;width:28px;min-width:0;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0;background:var(--bs-surface,var(--bs-surface-d));z-index:1;overflow:hidden}.bs-sheet[data-mode="left"] .bs-handle>*,.bs-sheet[data-mode="right"] .bs-handle>*{display:none}.bs-sheet[data-mode="left"] .bs-handle{right:0;border-left:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="right"] .bs-handle{left:0;border-right:1px solid var(--bs-surface-border,var(--bs-surface-border-d))}.bs-sheet[data-mode="left"] .bs-handle::before,.bs-sheet[data-mode="right"] .bs-handle::before{width:var(--bs-handle-height);height:var(--bs-handle-width);margin:0}.bs-sheet:hover .bs-handle::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 15%)}.bs-handle:active::before{background:color-mix(in oklab,var(--bs-handle-color,var(--bs-handle-color-d)),#000 35%);transform:scaleX(1.15)}.bs-handle.bs-handle--ticks::after{content:"";display:block;position:absolute;left:50%;bottom:6px;transform:translateX(-50%);width:calc(var(--bs-handle-width) * 2);height:3px;background-image:radial-gradient( circle,var(--bs-handle-color,var(--bs-handle-color-d)) 0 1.5px,transparent 1.6px );background-size:8px 3px;background-repeat:repeat-x;background-position:center;opacity:0;transition:opacity 0.18s ease-out;pointer-events:none}.bs-root[data-dragging="true"] .bs-handle.bs-handle--ticks::after{opacity:0.4}.bs-sheet[data-mode="top"] .bs-handle.bs-handle--ticks::after{bottom:auto;top:6px}.bs-sheet[data-mode="left"] .bs-handle.bs-handle--ticks::after,.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{left:50%;top:50%;bottom:auto;transform:translate(-50%,-50%);width:3px;height:calc(var(--bs-handle-width) * 2);background-size:3px 8px;background-repeat:repeat-y;margin-left:calc(var(--bs-handle-height) + 6px)}.bs-sheet[data-mode="right"] .bs-handle.bs-handle--ticks::after{margin-left:calc(-1 * (var(--bs-handle-height) + 6px))}.bs-header{flex:0 0 auto;min-height:var(--bs-header-min-height,0px);padding:var(--bs-header-padding,0 16px 8px);background:var(--bs-surface,var(--bs-surface-d))}.bs-content{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;user-select:text;padding:var(--bs-content-padding,0 16px 16px)}.bs-footer{flex:0 0 auto;padding:var(--bs-footer-padding,12px 16px calc(12px + env(safe-area-inset-bottom)));border-top:1px solid var(--bs-surface-border,var(--bs-surface-border-d));background:var(--bs-surface,var(--bs-surface-d))}.bs-sheet[data-mode="bottom"]:has(.bs-footer:not([hidden]):has(*)){padding-bottom:0}.bs-header:not(:has(*)),.bs-footer:not(:has(*)),.bs-header[hidden],.bs-footer[hidden]{display:none}.bs-screen{position:absolute;inset:0;pointer-events:none;z-index:var(--bs-z-scrim);background:var(--bs-scrim-color,var(--bs-scrim-color-d));backdrop-filter:blur(var(--bs-scrim-blur,0px));-webkit-backdrop-filter:blur(var(--bs-scrim-blur,0px));transition:opacity 0.24s cubic-bezier(0.22,1,0.36,1);will-change:opacity}.bs-root[data-dragging="true"] .bs-screen,.bs-root[data-animating="true"] .bs-screen{transition:none}.bs-scrim-overlay{z-index:calc(var(--bs-z-sheet) + 1);pointer-events:none}.bs-button-slot{position:fixed;z-index:calc(var(--bs-z-sheet) + 1);pointer-events:auto}.bs-button-slot[data-side="left"]{left:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-side="right"]{right:16px;bottom:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="top"]{bottom:auto;top:calc(var(--bs-size,0px) + 12px)}.bs-button-slot[data-mode="left"]{left:calc(var(--bs-size,0px) + 12px);right:auto;bottom:auto;top:16px}.bs-button-slot[data-mode="right"]{right:calc(var(--bs-size,0px) + 12px);left:auto;bottom:auto;top:16px}@media (prefers-reduced-motion:reduce){.bs-backdrop,.bs-handle::before,.bs-button-slot[data-side="left"],.bs-button-slot[data-side="right"]{transition:none !important}}@media (prefers-color-scheme:dark){:where(.bs-root){--bs-surface-d:#1a1a1d;--bs-surface-border-d:rgba(255,255,255,0.08);--bs-handle-color-d:rgba(255,255,255,0.45);--bs-shadow-auto:0 -3px 16px rgba(0,0,0,0.5)}}@media (forced-colors:active){.bs-sheet{border:1px solid CanvasText}.bs-handle::before{background:CanvasText;forced-color-adjust:none}.bs-backdrop,.bs-screen{forced-color-adjust:none}}.bs-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:where(.ovl-root){--ovl-surface:var(--bs-surface,var(--bs-surface-d,#ffffff));--ovl-surface-border:var(--bs-surface-border,var(--bs-surface-border-d,rgba(0,0,0,0.08)));--ovl-shadow:0 -8px 40px rgba(0,0,0,0.35);--ovl-radius:var(--bs-radius,var(--bs-radius-d,20px));--ovl-backdrop-color:rgba(0,0,0,0.5);--ovl-z-backdrop:200;--ovl-z-panel:201}.ovl-backdrop{position:fixed;inset:0;background:var(--ovl-backdrop-color);opacity:0;pointer-events:none;z-index:var(--ovl-z-backdrop)}.ovl-panel{position:fixed;background:var(--ovl-surface);box-shadow:var(--ovl-shadow);z-index:var(--ovl-z-panel);-webkit-tap-highlight-color:transparent;outline:none;transition:transform 0.32s cubic-bezier(0.29,1.24,0.84,0.99),opacity 0.32s ease-out}.ovl-panel[data-state="open"]{transform:translate3d(0,0,0);opacity:1}@starting-style{.ovl-panel[data-edge="bottom"][data-state="open"]{transform:translate3d(0,100%,0);opacity:0}.ovl-panel[data-edge="top"][data-state="open"]{transform:translate3d(0,-100%,0);opacity:0}.ovl-panel[data-edge="left"][data-state="open"]{transform:translate3d(-100%,0,0);opacity:0}.ovl-panel[data-edge="right"][data-state="open"]{transform:translate3d(100%,0,0);opacity:0}}.ovl-panel[data-edge="bottom"]{left:0;right:0;bottom:0;width:100%;border-top-left-radius:var(--ovl-radius);border-top-right-radius:var(--ovl-radius);border-top:1px solid var(--ovl-surface-border);padding-bottom:env(safe-area-inset-bottom)}.ovl-panel[data-edge="top"]{left:0;right:0;top:0;width:100%;border-bottom-left-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-bottom:1px solid var(--ovl-surface-border);padding-top:env(safe-area-inset-top)}.ovl-panel[data-edge="left"]{top:0;bottom:0;left:0;height:100%;border-top-right-radius:var(--ovl-radius);border-bottom-right-radius:var(--ovl-radius);border-right:1px solid var(--ovl-surface-border)}.ovl-panel[data-edge="right"]{top:0;bottom:0;right:0;height:100%;border-top-left-radius:var(--ovl-radius);border-bottom-left-radius:var(--ovl-radius);border-left:1px solid var(--ovl-surface-border)}@media (prefers-reduced-motion:reduce){.ovl-panel,.ovl-backdrop{transition:none !important}}`;
4293
4469
  }
4294
4470
  });
4295
4471
 
@@ -4386,7 +4562,7 @@ var init_shadow_tree = __esm({
4386
4562
  });
4387
4563
 
4388
4564
  // src/web-component/attributes.ts
4389
- var ATTR_SNAP_POINTS, ATTR_ALLOWED, ATTR_INITIAL, ATTR_MODE, ATTR_BACKDROP, ATTR_STYLESHEET, ATTR_ANIMATION, ATTR_FOCUS_TRAP, ATTR_CLOSE_ON_ESCAPE, ATTR_LOCK_BODY_SCROLL, ATTR_SHEET_LABEL, ATTR_STACK_EFFECT, ATTR_PERSISTENT, ATTR_DISABLE_CLOSE, ATTR_DISABLE_DRAG, ATTR_CLOSE_ON_ROUTE_CHANGE, ATTR_RADIUS, ATTR_MAX_HEIGHT, ATTR_RETURN_FOCUS_TO, ATTR_BACKDROP_COLOR, ATTR_SCRIM_COLOR, ATTR_SNAP, LIVE_ATTRS, OBSERVED_ATTRS, isValidSnapPoint, DEFAULT_SNAP_POINTS, parseSnapPoints, VALID_MODES, VALID_ANIMATIONS, parseMode, parseAnimation, parseList, parseDimension, ANCHOR_POSITIONS, ANCHOR_ANIMATIONS, parseAnchorOptions;
4565
+ var ATTR_SNAP_POINTS, ATTR_ALLOWED, ATTR_INITIAL, ATTR_MODE, ATTR_BACKDROP, ATTR_STYLESHEET, ATTR_ANIMATION, ATTR_FOCUS_TRAP, ATTR_CLOSE_ON_ESCAPE, ATTR_LOCK_BODY_SCROLL, ATTR_SHEET_LABEL, ATTR_STACK_EFFECT, ATTR_PERSISTENT, ATTR_DISABLE_CLOSE, ATTR_DISABLE_DRAG, ATTR_DRAG_FROM, ATTR_DRAG_FROM_CONTENT, ATTR_CLOSE_ON_ROUTE_CHANGE, ATTR_RADIUS, ATTR_MAX_HEIGHT, ATTR_RETURN_FOCUS_TO, ATTR_BACKDROP_COLOR, ATTR_SCRIM_COLOR, ATTR_SNAP, LIVE_ATTRS, OBSERVED_ATTRS, isValidSnapPoint, DEFAULT_SNAP_POINTS, parseSnapPoints, VALID_MODES, VALID_ANIMATIONS, parseMode, parseAnimation, VALID_DRAG_FROM, parseDragFrom, parseList, parseDimension, ANCHOR_POSITIONS, ANCHOR_ANIMATIONS, parseAnchorOptions;
4390
4566
  var init_attributes = __esm({
4391
4567
  "src/web-component/attributes.ts"() {
4392
4568
  ATTR_SNAP_POINTS = "snap-points";
@@ -4404,6 +4580,8 @@ var init_attributes = __esm({
4404
4580
  ATTR_PERSISTENT = "persistent";
4405
4581
  ATTR_DISABLE_CLOSE = "disable-close";
4406
4582
  ATTR_DISABLE_DRAG = "disable-drag";
4583
+ ATTR_DRAG_FROM = "drag-from";
4584
+ ATTR_DRAG_FROM_CONTENT = "drag-from-content";
4407
4585
  ATTR_CLOSE_ON_ROUTE_CHANGE = "close-on-route-change";
4408
4586
  ATTR_RADIUS = "radius";
4409
4587
  ATTR_MAX_HEIGHT = "max-height";
@@ -4419,7 +4597,9 @@ var init_attributes = __esm({
4419
4597
  ATTR_SNAP,
4420
4598
  ATTR_PERSISTENT,
4421
4599
  ATTR_DISABLE_CLOSE,
4422
- ATTR_DISABLE_DRAG
4600
+ ATTR_DISABLE_DRAG,
4601
+ ATTR_DRAG_FROM,
4602
+ ATTR_DRAG_FROM_CONTENT
4423
4603
  ]);
4424
4604
  OBSERVED_ATTRS = [
4425
4605
  ATTR_SNAP_POINTS,
@@ -4436,6 +4616,8 @@ var init_attributes = __esm({
4436
4616
  ATTR_PERSISTENT,
4437
4617
  ATTR_DISABLE_CLOSE,
4438
4618
  ATTR_DISABLE_DRAG,
4619
+ ATTR_DRAG_FROM,
4620
+ ATTR_DRAG_FROM_CONTENT,
4439
4621
  ATTR_CLOSE_ON_ROUTE_CHANGE,
4440
4622
  ATTR_RADIUS,
4441
4623
  ATTR_MAX_HEIGHT,
@@ -4472,6 +4654,12 @@ var init_attributes = __esm({
4472
4654
  VALID_ANIMATIONS = ["spring", "tween", "ios-spring", "material-bounce", "linear", "snappy"];
4473
4655
  parseMode = (raw) => raw && VALID_MODES.includes(raw) ? raw : "bottom";
4474
4656
  parseAnimation = (raw) => raw && VALID_ANIMATIONS.includes(raw) ? raw : void 0;
4657
+ VALID_DRAG_FROM = [
4658
+ "handle",
4659
+ "sheet",
4660
+ "zones"
4661
+ ];
4662
+ parseDragFrom = (raw) => raw && VALID_DRAG_FROM.includes(raw) ? raw : void 0;
4475
4663
  parseList = (raw) => raw ? raw.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
4476
4664
  parseDimension = (raw) => {
4477
4665
  if (raw === null) return void 0;
@@ -4620,6 +4808,14 @@ var init_BottomSheetElement = __esm({
4620
4808
  case ATTR_DISABLE_DRAG:
4621
4809
  this.engine.setDisableDrag(value === "true");
4622
4810
  break;
4811
+ case ATTR_DRAG_FROM_CONTENT:
4812
+ this.engine.setDragFromContent(value !== "false");
4813
+ break;
4814
+ case ATTR_DRAG_FROM: {
4815
+ const mode = parseDragFrom(value);
4816
+ if (mode) this.engine.setDragFrom(mode);
4817
+ break;
4818
+ }
4623
4819
  case ATTR_SNAP:
4624
4820
  if (value && value !== this.engine.state.activeId) {
4625
4821
  void this.engine.snapTo(value);
@@ -4690,6 +4886,8 @@ var init_BottomSheetElement = __esm({
4690
4886
  persistent: this.getAttribute(ATTR_PERSISTENT) === "true",
4691
4887
  disableClose: this.getAttribute(ATTR_DISABLE_CLOSE) === "true",
4692
4888
  disableDrag: this.getAttribute(ATTR_DISABLE_DRAG) === "true",
4889
+ dragFrom: parseDragFrom(this.getAttribute(ATTR_DRAG_FROM)),
4890
+ dragFromContent: this.getAttribute(ATTR_DRAG_FROM_CONTENT) === null ? void 0 : this.getAttribute(ATTR_DRAG_FROM_CONTENT) !== "false",
4693
4891
  closeOnRouteChange: this.getAttribute(ATTR_CLOSE_ON_ROUTE_CHANGE) === "true",
4694
4892
  radius: parseDimension(this.getAttribute(ATTR_RADIUS)),
4695
4893
  maxHeight: parseDimension(this.getAttribute(ATTR_MAX_HEIGHT)),