@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.js CHANGED
@@ -10,10 +10,10 @@ var __export = (target, all) => {
10
10
  };
11
11
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
12
12
 
13
- // src/core/lifecycle/sheetStack.ts
13
+ // src/core/lifecycle/sheet-stack.ts
14
14
  var BASE_Z, STEP, SheetStack, sheetStack;
15
- var init_sheetStack = __esm({
16
- "src/core/lifecycle/sheetStack.ts"() {
15
+ var init_sheet_stack = __esm({
16
+ "src/core/lifecycle/sheet-stack.ts"() {
17
17
  BASE_Z = 100;
18
18
  STEP = 10;
19
19
  SheetStack = class {
@@ -154,10 +154,10 @@ var init_event_bus = __esm({
154
154
  }
155
155
  });
156
156
 
157
- // src/core/primitives/cssLength.ts
157
+ // src/core/primitives/css-length.ts
158
158
  var probe, PROBE_ATTR, ensureProbe, isViewportAxisVertical, viewportSize, PERCENT, resolveSnap;
159
- var init_cssLength = __esm({
160
- "src/core/primitives/cssLength.ts"() {
159
+ var init_css_length = __esm({
160
+ "src/core/primitives/css-length.ts"() {
161
161
  probe = null;
162
162
  PROBE_ATTR = "data-bs-probe";
163
163
  ensureProbe = (axis) => {
@@ -213,14 +213,14 @@ var init_cssLength = __esm({
213
213
  }
214
214
  });
215
215
 
216
- // src/core/primitives/devWarn.ts
216
+ // src/core/primitives/dev-warn.ts
217
217
  function devWarn(...args) {
218
218
  if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production" && typeof console !== "undefined") {
219
219
  console.warn(...args);
220
220
  }
221
221
  }
222
- var init_devWarn = __esm({
223
- "src/core/primitives/devWarn.ts"() {
222
+ var init_dev_warn = __esm({
223
+ "src/core/primitives/dev-warn.ts"() {
224
224
  }
225
225
  });
226
226
 
@@ -228,8 +228,8 @@ var init_devWarn = __esm({
228
228
  var resolveSnapList, VH_NOT_DVH, auditVhUsage, findNearest, allowedRange, findById, MOUSE_FLICK_VELOCITY, MOUSE_DRAG_THRESHOLD, DIRECTIONAL_INTENT_VELOCITY, findDragSettleTarget;
229
229
  var init_snap_points = __esm({
230
230
  "src/core/primitives/snap-points.ts"() {
231
- init_cssLength();
232
- init_devWarn();
231
+ init_css_length();
232
+ init_dev_warn();
233
233
  resolveSnapList = (points, mode, measureFit) => points.map((p) => {
234
234
  const raw = resolveSnap(p.size, mode, measureFit);
235
235
  if (!Number.isFinite(raw) || raw < 0) {
@@ -322,7 +322,7 @@ function emitCancelable(emit, base, warnLabel) {
322
322
  }
323
323
  var init_cancelable_emit = __esm({
324
324
  "src/core/primitives/cancelable-emit.ts"() {
325
- init_devWarn();
325
+ init_dev_warn();
326
326
  }
327
327
  });
328
328
 
@@ -868,7 +868,7 @@ var init_scrim_controller = __esm({
868
868
  init_snap_points();
869
869
  init_hot_path_thresholds();
870
870
  init_opacity_dedup();
871
- init_devWarn();
871
+ init_dev_warn();
872
872
  init_overlay_position();
873
873
  VALID_CSS_LENGTH = /^-?\d+(?:\.\d+)?(?:px|em|rem|%)$/;
874
874
  DEFAULT_SCRIM_DIM = "rgba(0, 0, 0, 0.4)";
@@ -1658,10 +1658,10 @@ var init_animation_runner = __esm({
1658
1658
  }
1659
1659
  });
1660
1660
 
1661
- // src/core/lifecycle/focusTrap.ts
1661
+ // src/core/lifecycle/focus-trap.ts
1662
1662
  var FOCUSABLE, isVisible, collectFocusables, focusables, containsComposed, trapStack, installFocusTrap;
1663
- var init_focusTrap = __esm({
1664
- "src/core/lifecycle/focusTrap.ts"() {
1663
+ var init_focus_trap = __esm({
1664
+ "src/core/lifecycle/focus-trap.ts"() {
1665
1665
  FOCUSABLE = [
1666
1666
  "a[href]",
1667
1667
  "area[href]",
@@ -1781,10 +1781,10 @@ var init_focusTrap = __esm({
1781
1781
  }
1782
1782
  });
1783
1783
 
1784
- // src/core/lifecycle/scrollLock.ts
1784
+ // src/core/lifecycle/scroll-lock.ts
1785
1785
  var lockCount, savedStyles, lockBodyScroll;
1786
- var init_scrollLock = __esm({
1787
- "src/core/lifecycle/scrollLock.ts"() {
1786
+ var init_scroll_lock = __esm({
1787
+ "src/core/lifecycle/scroll-lock.ts"() {
1788
1788
  lockCount = 0;
1789
1789
  savedStyles = null;
1790
1790
  lockBodyScroll = () => {
@@ -1867,8 +1867,8 @@ var init_inert_siblings = __esm({
1867
1867
  var LifecycleController;
1868
1868
  var init_lifecycle_controller = __esm({
1869
1869
  "src/core/controllers/lifecycle-controller.ts"() {
1870
- init_focusTrap();
1871
- init_scrollLock();
1870
+ init_focus_trap();
1871
+ init_scroll_lock();
1872
1872
  init_inert_siblings();
1873
1873
  LifecycleController = class {
1874
1874
  constructor(deps, opts) {
@@ -1983,30 +1983,44 @@ var init_gestures = __esm({
1983
1983
  this.size = 0;
1984
1984
  }
1985
1985
  };
1986
- installGestures = (handle, mode, callbacks) => {
1986
+ installGestures = (handle, mode, callbacks, options = {}) => {
1987
1987
  let activePointerId = null;
1988
1988
  let activePointerType = "touch";
1989
1989
  let startCoord = 0;
1990
1990
  let lastCoord = 0;
1991
+ let pendingStart = false;
1991
1992
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
1992
1993
  const MAX_SAMPLES = 32;
1993
1994
  const samples = new SampleRing(MAX_SAMPLES);
1994
1995
  const axis = isAxisVertical(mode) ? "Y" : "X";
1995
1996
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1996
1997
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
1998
+ const capture = (pointerId) => {
1999
+ try {
2000
+ handle.setPointerCapture(pointerId);
2001
+ } catch {
2002
+ }
2003
+ };
2004
+ const releaseTracking = () => {
2005
+ activePointerId = null;
2006
+ pendingStart = false;
2007
+ samples.reset();
2008
+ };
1997
2009
  const onPointerDown = (e) => {
1998
2010
  if (activePointerId !== null) return;
1999
2011
  if (e.button !== void 0 && e.button !== 0) return;
2012
+ if (options.shouldStart && !options.shouldStart(e)) return;
2000
2013
  activePointerId = e.pointerId;
2001
2014
  activePointerType = e.pointerType || "touch";
2002
2015
  startCoord = coordOf(e);
2003
2016
  lastCoord = startCoord;
2004
2017
  samples.reset();
2005
2018
  samples.push(e.timeStamp, startCoord);
2006
- try {
2007
- handle.setPointerCapture(e.pointerId);
2008
- } catch {
2019
+ if (options.deferStart) {
2020
+ pendingStart = true;
2021
+ return;
2009
2022
  }
2023
+ capture(e.pointerId);
2010
2024
  callbacks.onStart(startCoord, activePointerType);
2011
2025
  };
2012
2026
  const onPointerMove = (e) => {
@@ -2014,6 +2028,22 @@ var init_gestures = __esm({
2014
2028
  const coord = coordOf(e);
2015
2029
  const rawDelta = coord - startCoord;
2016
2030
  const delta = rawDelta * sign;
2031
+ if (pendingStart) {
2032
+ const verdict = options.deferStart(e, delta);
2033
+ if (verdict === false) {
2034
+ releaseTracking();
2035
+ return;
2036
+ }
2037
+ if (verdict !== true) return;
2038
+ pendingStart = false;
2039
+ startCoord = coord;
2040
+ lastCoord = coord;
2041
+ samples.reset();
2042
+ samples.push(e.timeStamp, coord);
2043
+ capture(e.pointerId);
2044
+ callbacks.onStart(startCoord, activePointerType);
2045
+ return;
2046
+ }
2017
2047
  lastCoord = coord;
2018
2048
  samples.push(e.timeStamp, coord);
2019
2049
  const cutoff = e.timeStamp - VELOCITY_WINDOW_MS(activePointerType);
@@ -2022,6 +2052,10 @@ var init_gestures = __esm({
2022
2052
  };
2023
2053
  const finishGesture = (e) => {
2024
2054
  if (e.pointerId !== activePointerId) return;
2055
+ if (pendingStart) {
2056
+ releaseTracking();
2057
+ return;
2058
+ }
2025
2059
  const rawDelta = lastCoord - startCoord;
2026
2060
  const delta = rawDelta * sign;
2027
2061
  let velocity = 0;
@@ -2044,22 +2078,26 @@ var init_gestures = __esm({
2044
2078
  };
2045
2079
  const onPointerCancel = (e) => {
2046
2080
  if (e.pointerId !== activePointerId) return;
2047
- activePointerId = null;
2048
- samples.reset();
2081
+ const wasPending = pendingStart;
2082
+ releaseTracking();
2083
+ if (wasPending) return;
2049
2084
  callbacks.onCancel?.();
2050
2085
  };
2051
2086
  handle.addEventListener("pointerdown", onPointerDown);
2052
2087
  handle.addEventListener("pointermove", onPointerMove);
2053
2088
  handle.addEventListener("pointerup", finishGesture);
2054
2089
  handle.addEventListener("pointercancel", onPointerCancel);
2090
+ const managesTouchAction = options.manageTouchAction !== false;
2055
2091
  const prevTouchAction = handle.style.touchAction;
2056
- handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
2092
+ if (managesTouchAction) {
2093
+ handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
2094
+ }
2057
2095
  return () => {
2058
2096
  handle.removeEventListener("pointerdown", onPointerDown);
2059
2097
  handle.removeEventListener("pointermove", onPointerMove);
2060
2098
  handle.removeEventListener("pointerup", finishGesture);
2061
2099
  handle.removeEventListener("pointercancel", onPointerCancel);
2062
- handle.style.touchAction = prevTouchAction;
2100
+ if (managesTouchAction) handle.style.touchAction = prevTouchAction;
2063
2101
  if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
2064
2102
  handle.releasePointerCapture(activePointerId);
2065
2103
  }
@@ -2194,7 +2232,7 @@ var init_gesture_controller = __esm({
2194
2232
  const restoreTo = this.dragStartSize;
2195
2233
  void this.deps.animateTo(restoreTo, 0);
2196
2234
  }
2197
- });
2235
+ }, this.deps.gestureOptions);
2198
2236
  return this.detach;
2199
2237
  }
2200
2238
  forceClearDragState() {
@@ -2208,6 +2246,55 @@ var init_gesture_controller = __esm({
2208
2246
  }
2209
2247
  });
2210
2248
 
2249
+ // src/core/primitives/drag-zones.ts
2250
+ function isDragAllowedFrom(target, mode) {
2251
+ const el = asElement(target);
2252
+ if (!el) return mode !== "zones";
2253
+ if (el.closest(NO_DRAG_SELECTOR)) return false;
2254
+ if (mode === "zones") return el.closest(DRAG_ZONE_SELECTOR) !== null;
2255
+ return true;
2256
+ }
2257
+ var DRAG_ZONE_SELECTOR, NO_DRAG_SELECTOR, asElement;
2258
+ var init_drag_zones = __esm({
2259
+ "src/core/primitives/drag-zones.ts"() {
2260
+ DRAG_ZONE_SELECTOR = "[data-bs-drag]";
2261
+ NO_DRAG_SELECTOR = "[data-bs-no-drag]";
2262
+ asElement = (target) => {
2263
+ const candidate = target;
2264
+ return candidate && typeof candidate.closest === "function" ? candidate : null;
2265
+ };
2266
+ }
2267
+ });
2268
+
2269
+ // src/core/primitives/content-gesture.ts
2270
+ function decideContentGesture(input) {
2271
+ const slop = input.slop ?? CONTENT_DRAG_SLOP;
2272
+ if (Math.abs(input.delta) < slop) return "pending";
2273
+ if (input.scrollTop > 0) return "scroll";
2274
+ if (input.delta > 0 && input.atMaxSnap) return "scroll";
2275
+ return "drag";
2276
+ }
2277
+ var CONTENT_DRAG_SLOP;
2278
+ var init_content_gesture = __esm({
2279
+ "src/core/primitives/content-gesture.ts"() {
2280
+ CONTENT_DRAG_SLOP = 6;
2281
+ }
2282
+ });
2283
+
2284
+ // src/core/primitives/touch-scroll-guard.ts
2285
+ function installTouchScrollGuard(surface, isDragging) {
2286
+ const onTouchMove = (e) => {
2287
+ if (!isDragging()) return;
2288
+ if (e.cancelable) e.preventDefault();
2289
+ };
2290
+ surface.addEventListener("touchmove", onTouchMove, { passive: false });
2291
+ return () => surface.removeEventListener("touchmove", onTouchMove);
2292
+ }
2293
+ var init_touch_scroll_guard = __esm({
2294
+ "src/core/primitives/touch-scroll-guard.ts"() {
2295
+ }
2296
+ });
2297
+
2211
2298
  // src/core/primitives/aria-slider-writer.ts
2212
2299
  var AriaSliderWriter;
2213
2300
  var init_aria_slider_writer = __esm({
@@ -2589,6 +2676,8 @@ function resolveEngineOptions(opts, extras) {
2589
2676
  mode: opts.mode ?? "bottom",
2590
2677
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2591
2678
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2679
+ dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
2680
+ dragFromContent: opts.dragFromContent ?? true,
2592
2681
  rubberBandEnabled: opts.rubberBand ?? true,
2593
2682
  closeOnBack: opts.closeOnBack ?? false,
2594
2683
  persistent: opts.persistent ?? false,
@@ -2676,13 +2765,13 @@ var init_teardown_stack = __esm({
2676
2765
  var HAPTIC_DURATION_MS, BottomSheetCore;
2677
2766
  var init_BottomSheetCore = __esm({
2678
2767
  "src/core/BottomSheetCore.ts"() {
2679
- init_sheetStack();
2768
+ init_sheet_stack();
2680
2769
  init_transform();
2681
2770
  init_instance_id();
2682
2771
  init_event_bus();
2683
2772
  init_snap_points();
2684
2773
  init_cancelable_emit();
2685
- init_devWarn();
2774
+ init_dev_warn();
2686
2775
  init_snap_resolver();
2687
2776
  init_linked_sheets();
2688
2777
  init_resize_observer();
@@ -2694,6 +2783,9 @@ var init_BottomSheetCore = __esm({
2694
2783
  init_animation_runner();
2695
2784
  init_lifecycle_controller();
2696
2785
  init_gesture_controller();
2786
+ init_drag_zones();
2787
+ init_content_gesture();
2788
+ init_touch_scroll_guard();
2697
2789
  init_aria_slider_writer();
2698
2790
  init_hot_path_thresholds();
2699
2791
  init_scroll_cache();
@@ -2715,6 +2807,8 @@ var init_BottomSheetCore = __esm({
2715
2807
  __publicField(this, "mode");
2716
2808
  __publicField(this, "flickVelocity");
2717
2809
  __publicField(this, "dragThreshold");
2810
+ __publicField(this, "dragFromMode");
2811
+ __publicField(this, "dragFromContentDefault");
2718
2812
  __publicField(this, "rubberBandEnabled");
2719
2813
  __publicField(this, "scrim");
2720
2814
  __publicField(this, "aria");
@@ -2732,8 +2826,11 @@ var init_BottomSheetCore = __esm({
2732
2826
  __publicField(this, "activeId");
2733
2827
  __publicField(this, "size", 0);
2734
2828
  __publicField(this, "gesture");
2829
+ __publicField(this, "contentGesture");
2830
+ __publicField(this, "detachSheetGesture", null);
2735
2831
  __publicField(this, "rootEl", null);
2736
2832
  __publicField(this, "destroyed", false);
2833
+ __publicField(this, "restClosed", false);
2737
2834
  __publicField(this, "currentViewTransition", null);
2738
2835
  __publicField(this, "currentAbort", new AbortController());
2739
2836
  __publicField(this, "sizeWriteSentinel", new WriteSentinel());
@@ -2786,6 +2883,8 @@ var init_BottomSheetCore = __esm({
2786
2883
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2787
2884
  this.flickVelocity = resolved.flickVelocity;
2788
2885
  this.dragThreshold = resolved.dragThreshold;
2886
+ this.dragFromMode = resolved.dragFrom;
2887
+ this.dragFromContentDefault = resolved.dragFromContent;
2789
2888
  this.rubberBandEnabled = resolved.rubberBandEnabled;
2790
2889
  this.scrim = new ScrimController(
2791
2890
  {
@@ -2812,7 +2911,7 @@ var init_BottomSheetCore = __esm({
2812
2911
  getRootEl: () => this.rootEl,
2813
2912
  applySize: (size) => this.applySize(size),
2814
2913
  getSize: () => this.size,
2815
- isDragging: () => this.gesture?.isDragging ?? false,
2914
+ isDragging: () => this.isDraggingAny(),
2816
2915
  applyAux: (size) => this.applySize(size, true),
2817
2916
  getTransformFor: (size) => this.transformTemplate(this.snaps.getMaxAxisSize() - size)
2818
2917
  },
@@ -2873,6 +2972,7 @@ var init_BottomSheetCore = __esm({
2873
2972
  const initial = this.snaps.findById(this.activeId);
2874
2973
  if (initial) this.size = initial.size;
2875
2974
  this.applySize(this.size);
2975
+ this.setRestClosed(this.size === 0);
2876
2976
  this.updateAriaSlider();
2877
2977
  this.scrollCache = createScrollCache({
2878
2978
  scrollContainer: this.scrollContainer,
@@ -2903,7 +3003,7 @@ var init_BottomSheetCore = __esm({
2903
3003
  (p) => p.size === "fit" || p.size === "content"
2904
3004
  ),
2905
3005
  isDestroyed: () => this.destroyed,
2906
- isDragging: () => this.gesture?.isDragging ?? false,
3006
+ isDragging: () => this.isDraggingAny(),
2907
3007
  recompute: () => this.recompute()
2908
3008
  })
2909
3009
  );
@@ -2929,7 +3029,7 @@ var init_BottomSheetCore = __esm({
2929
3029
  autoCollapseAfter
2930
3030
  },
2931
3031
  isDestroyed: () => this.destroyed,
2932
- isDragging: () => this.gesture?.isDragging ?? false,
3032
+ isDragging: () => this.isDraggingAny(),
2933
3033
  isAnimating: () => this.animation.isAnimating,
2934
3034
  isTopSheet: () => this.isTopSheet,
2935
3035
  isVerticalAxis: () => this.mode === "bottom" || this.mode === "top",
@@ -2959,6 +3059,7 @@ var init_BottomSheetCore = __esm({
2959
3059
  void this.snapTo(id);
2960
3060
  },
2961
3061
  close: (reason) => this.close(reason),
3062
+ attachDragSurface: (surface, kind) => this.attachDragSurface(surface, kind),
2962
3063
  on: (event, fn) => this.on(event, fn),
2963
3064
  addTeardown: (fn) => this.teardowns.add(fn)
2964
3065
  };
@@ -2987,7 +3088,7 @@ var init_BottomSheetCore = __esm({
2987
3088
  return {
2988
3089
  size: this.size,
2989
3090
  activeId: this.activeId,
2990
- isDragging: this.gesture?.isDragging ?? false,
3091
+ isDragging: this.isDraggingAny(),
2991
3092
  isAnimating: this.animation.isAnimating,
2992
3093
  progress: this.computeProgress(this.size)
2993
3094
  };
@@ -3107,9 +3208,16 @@ var init_BottomSheetCore = __esm({
3107
3208
  progress: this.computeProgress(this.size)
3108
3209
  });
3109
3210
  if (withHaptic) this.haptic();
3211
+ this.setRestClosed(targetSize === 0);
3110
3212
  if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
3111
3213
  if (targetSize === 0) this.emitCloseSequence();
3112
3214
  }
3215
+ setRestClosed(closed) {
3216
+ if (closed === this.restClosed) return;
3217
+ this.restClosed = closed;
3218
+ if (closed) this.element.setAttribute("data-bs-rest", "closed");
3219
+ else this.element.removeAttribute("data-bs-rest");
3220
+ }
3113
3221
  emitOpenSequence(id) {
3114
3222
  this.emit("open", { id });
3115
3223
  this.handleOpen();
@@ -3165,6 +3273,20 @@ var init_BottomSheetCore = __esm({
3165
3273
  if (this.destroyed) return;
3166
3274
  this.disableDragFlag = value;
3167
3275
  }
3276
+ setDragFromContent(value) {
3277
+ if (this.destroyed) return;
3278
+ this.dragFromContentDefault = value;
3279
+ }
3280
+ setDragFrom(mode) {
3281
+ if (this.destroyed || mode === this.dragFromMode) return;
3282
+ this.gesture?.forceClearDragState();
3283
+ this.detachSheetGesture?.();
3284
+ this.dragFromMode = mode;
3285
+ this.mountSheetGesture();
3286
+ }
3287
+ getDragFrom() {
3288
+ return this.dragFromMode;
3289
+ }
3168
3290
  isTop() {
3169
3291
  return this.isTopSheet;
3170
3292
  }
@@ -3319,12 +3441,24 @@ var init_BottomSheetCore = __esm({
3319
3441
  auditVhUsage(points);
3320
3442
  this.auditDuplicateSnapIds(points);
3321
3443
  this.snaps.setRaw(points);
3322
- if (allowed) this.snaps.setAllowedIds(allowed);
3444
+ if (allowed) {
3445
+ this.snaps.setAllowedIds(allowed);
3446
+ } else {
3447
+ const present = this.snaps.getResolvedSnaps().map((s) => s.id);
3448
+ const kept = this.snaps.getAllowedIds().filter((id) => present.includes(id));
3449
+ this.snaps.setAllowedIds(kept.length ? kept : present);
3450
+ }
3323
3451
  this.scrollCache.clear();
3324
3452
  this.scrim.invalidateOpacityCache();
3325
3453
  const current = this.snaps.findById(this.activeId);
3326
3454
  if (current) {
3327
3455
  this.applySize(current.size);
3456
+ } else {
3457
+ const fallback = this.snaps.getResolvedSnaps().find((s) => this.snaps.getAllowedIds().includes(s.id)) ?? this.snaps.getResolvedSnaps()[0];
3458
+ if (fallback) {
3459
+ this.activeId = fallback.id;
3460
+ this.applySize(fallback.size);
3461
+ }
3328
3462
  }
3329
3463
  this.updateAriaSlider();
3330
3464
  }
@@ -3334,7 +3468,7 @@ var init_BottomSheetCore = __esm({
3334
3468
  this.snaps.recompute();
3335
3469
  this.maxHeight.clampTo();
3336
3470
  this.scrim.invalidateOpacityCache();
3337
- if (this.gesture?.isDragging) return;
3471
+ if (this.isDraggingAny()) return;
3338
3472
  this.healActiveSnap();
3339
3473
  }
3340
3474
  healActiveSnap() {
@@ -3356,6 +3490,8 @@ var init_BottomSheetCore = __esm({
3356
3490
  this.bus.clear();
3357
3491
  this.animation.cancel();
3358
3492
  this.gesture?.forceClearDragState();
3493
+ this.contentGesture?.forceClearDragState();
3494
+ this.setRestClosed(false);
3359
3495
  this.teardowns.drain();
3360
3496
  this.scrim.destroy();
3361
3497
  this.animation.destroy();
@@ -3468,11 +3604,12 @@ var init_BottomSheetCore = __esm({
3468
3604
  const scale = Math.max(1 - depth * 0.04, 0.86);
3469
3605
  this.element.style.scale = scale === 1 ? "" : String(scale);
3470
3606
  }
3471
- attach() {
3472
- this.gesture = new GestureController({
3473
- handle: this.handle,
3607
+ buildGestureDeps(surface, gestureOptions) {
3608
+ return {
3609
+ handle: surface,
3474
3610
  element: this.element,
3475
3611
  mode: this.mode,
3612
+ gestureOptions,
3476
3613
  getRoot: () => this.rootEl,
3477
3614
  getDragContext: () => {
3478
3615
  const buf = this.dragContextBuf;
@@ -3491,8 +3628,88 @@ var init_BottomSheetCore = __esm({
3491
3628
  settleAfterDrag: (delta, velocity, kind) => this.settleAfterDrag(delta, velocity, kind),
3492
3629
  emit: (event, payload) => this.emit(event, payload),
3493
3630
  listenerCount: (event) => this.bus.listenerCount(event)
3631
+ };
3632
+ }
3633
+ isContentDragAllowed() {
3634
+ if (this.disableDragFlag) return false;
3635
+ const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3636
+ return point?.dragFromContent ?? this.dragFromContentDefault;
3637
+ }
3638
+ decideContentDrag(surface, e, delta) {
3639
+ if (this.destroyed) return false;
3640
+ if (e.pointerType === "mouse") return false;
3641
+ if (this.gesture?.isDragging) return false;
3642
+ if (!this.isContentDragAllowed()) return false;
3643
+ if (!isDragAllowedFrom(e.target, "sheet")) return false;
3644
+ const decision = decideContentGesture({
3645
+ delta,
3646
+ scrollTop: surface.scrollTop,
3647
+ atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3648
+ });
3649
+ if (decision === "pending") return null;
3650
+ return decision === "drag";
3651
+ }
3652
+ attachDragSurface(surface, kind) {
3653
+ if (this.destroyed || kind !== "content") return;
3654
+ if (this.contentGesture) return;
3655
+ const controller = new GestureController(
3656
+ this.buildGestureDeps(surface, {
3657
+ manageTouchAction: false,
3658
+ deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
3659
+ })
3660
+ );
3661
+ this.contentGesture = controller;
3662
+ const detachGestures = controller.install();
3663
+ const detachGuard = installTouchScrollGuard(
3664
+ surface,
3665
+ () => controller.isDragging
3666
+ );
3667
+ return () => {
3668
+ detachGuard();
3669
+ detachGestures();
3670
+ if (this.contentGesture === controller) this.contentGesture = void 0;
3671
+ };
3672
+ }
3673
+ sheetDragSurface() {
3674
+ return this.dragFromMode === "handle" ? this.handle : this.element;
3675
+ }
3676
+ canStartSheetDrag(e) {
3677
+ if (this.contentGesture?.isDragging) return false;
3678
+ const target = e.target;
3679
+ const scoped = typeof target?.closest === "function";
3680
+ if (scoped && target.closest(NO_DRAG_SELECTOR)) return false;
3681
+ if (this.handle !== this.element && scoped && this.handle.contains(target)) {
3682
+ return true;
3683
+ }
3684
+ if (!isDragAllowedFrom(e.target, this.dragFromMode)) return false;
3685
+ if (this.dragFromMode === "handle") return true;
3686
+ if (this.scrollContainer && scoped && this.scrollContainer.contains(target) && !target.closest(DRAG_ZONE_SELECTOR)) {
3687
+ return false;
3688
+ }
3689
+ return true;
3690
+ }
3691
+ mountSheetGesture() {
3692
+ const surface = this.sheetDragSurface();
3693
+ const controller = new GestureController(
3694
+ this.buildGestureDeps(surface, {
3695
+ shouldStart: (e) => this.canStartSheetDrag(e),
3696
+ manageTouchAction: this.dragFromMode === "handle"
3697
+ })
3698
+ );
3699
+ this.gesture = controller;
3700
+ const detachGestures = controller.install();
3701
+ const detachGuard = this.dragFromMode === "handle" ? null : installTouchScrollGuard(surface, () => controller.isDragging);
3702
+ this.detachSheetGesture = () => {
3703
+ detachGuard?.();
3704
+ detachGestures();
3705
+ };
3706
+ }
3707
+ attach() {
3708
+ this.mountSheetGesture();
3709
+ this.teardowns.add(() => {
3710
+ this.detachSheetGesture?.();
3711
+ this.detachSheetGesture = null;
3494
3712
  });
3495
- this.teardowns.add(this.gesture.install());
3496
3713
  try {
3497
3714
  this.attachFeatures();
3498
3715
  } catch (err) {
@@ -3529,7 +3746,7 @@ var init_BottomSheetCore = __esm({
3529
3746
  element: this.element,
3530
3747
  getMode: () => this.mode,
3531
3748
  isDestroyed: () => this.destroyed,
3532
- isDragging: () => this.gesture?.isDragging ?? false,
3749
+ isDragging: () => this.isDraggingAny(),
3533
3750
  resolveActiveSnap: () => this.snaps.findById(this.activeId),
3534
3751
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
3535
3752
  getSize: () => this.size,
@@ -3627,8 +3844,11 @@ var init_BottomSheetCore = __esm({
3627
3844
  );
3628
3845
  });
3629
3846
  }
3847
+ isDraggingAny() {
3848
+ return (this.gesture?.isDragging ?? false) || (this.contentGesture?.isDragging ?? false);
3849
+ }
3630
3850
  clearWillChangeIfIdle() {
3631
- if (this.animation.isAnimating || this.gesture?.isDragging) return;
3851
+ if (this.animation.isAnimating || this.isDraggingAny()) return;
3632
3852
  this.element.style.willChange = "";
3633
3853
  }
3634
3854
  haptic() {
@@ -3641,8 +3861,9 @@ var init_BottomSheetCore = __esm({
3641
3861
  }
3642
3862
  applySize(size, skipTransform = false) {
3643
3863
  const cap = this.snaps.getMaxAxisSize();
3644
- const clamped = cap > 0 && size > cap && !this.gesture?.isDragging && !this.allowOvershoot ? cap : size;
3864
+ const clamped = cap > 0 && size > cap && !this.isDraggingAny() && !this.allowOvershoot ? cap : size;
3645
3865
  this.size = clamped;
3866
+ if (clamped > 0) this.setRestClosed(false);
3646
3867
  const offset = cap - clamped;
3647
3868
  const style = this.element.style;
3648
3869
  if (!skipTransform) style.transform = this.transformTemplate(offset);
@@ -4042,54 +4263,13 @@ var init_auto_collapse = __esm({
4042
4263
  }
4043
4264
  });
4044
4265
 
4045
- // src/core/features/content-swipe.ts
4046
- function installContentSwipe(deps) {
4047
- const { container } = deps;
4048
- let startY = 0;
4049
- let startScrollTop = 0;
4050
- let moved = false;
4051
- const onTouchStart = (e) => {
4052
- const t = e.touches[0];
4053
- if (!t) return;
4054
- startY = t.clientY;
4055
- startScrollTop = container.scrollTop;
4056
- moved = false;
4057
- };
4058
- const onTouchMove = (e) => {
4059
- const t = e.touches[0];
4060
- if (!t) return;
4061
- if (Math.abs(t.clientY - startY) > CONTENT_PULL_THRESHOLD) moved = true;
4062
- };
4063
- const onTouchEnd = (e) => {
4064
- if (!moved) return;
4065
- if (deps.isDragging() || deps.isAnimating()) return;
4066
- if (container.scrollTop !== startScrollTop) return;
4067
- const t = e.changedTouches[0];
4068
- if (!t) return;
4069
- const deltaY = t.clientY - startY;
4070
- const atTop = container.scrollTop <= 0;
4071
- const allowed = deps.getAllowedIds();
4072
- const idx = allowed.indexOf(deps.getActiveId());
4073
- if (idx === -1) return;
4074
- if (atTop && deltaY > CONTENT_PULL_THRESHOLD && idx > 0) {
4075
- deps.snapTo(allowed[idx - 1]);
4076
- } else if (deltaY < -CONTENT_PULL_THRESHOLD && idx < allowed.length - 1) {
4077
- deps.snapTo(allowed[idx + 1]);
4078
- }
4079
- };
4080
- container.addEventListener("touchstart", onTouchStart, { passive: true });
4081
- container.addEventListener("touchmove", onTouchMove, { passive: true });
4082
- container.addEventListener("touchend", onTouchEnd, { passive: true });
4083
- return () => {
4084
- container.removeEventListener("touchstart", onTouchStart);
4085
- container.removeEventListener("touchmove", onTouchMove);
4086
- container.removeEventListener("touchend", onTouchEnd);
4087
- };
4266
+ // src/core/features/content-drag.ts
4267
+ function installContentDrag(deps) {
4268
+ const detach = deps.attachDragSurface(deps.container, "content");
4269
+ return () => detach?.();
4088
4270
  }
4089
- var CONTENT_PULL_THRESHOLD;
4090
- var init_content_swipe = __esm({
4091
- "src/core/features/content-swipe.ts"() {
4092
- CONTENT_PULL_THRESHOLD = 60;
4271
+ var init_content_drag = __esm({
4272
+ "src/core/features/content-drag.ts"() {
4093
4273
  }
4094
4274
  });
4095
4275
 
@@ -4203,13 +4383,9 @@ function contentSwipeFeature() {
4203
4383
  stage: "attach",
4204
4384
  install: (ctx) => {
4205
4385
  if (!ctx.scrollContainer) return;
4206
- return installContentSwipe({
4386
+ return installContentDrag({
4207
4387
  container: ctx.scrollContainer,
4208
- isDragging: ctx.isDragging,
4209
- isAnimating: ctx.isAnimating,
4210
- getAllowedIds: ctx.allowedIdsBySize,
4211
- getActiveId: ctx.getActiveId,
4212
- snapTo: ctx.snapTo
4388
+ attachDragSurface: ctx.attachDragSurface
4213
4389
  });
4214
4390
  }
4215
4391
  };
@@ -4244,7 +4420,7 @@ var init_engine_features = __esm({
4244
4420
  init_route();
4245
4421
  init_persist();
4246
4422
  init_auto_collapse();
4247
- init_content_swipe();
4423
+ init_content_drag();
4248
4424
  init_visual_viewport();
4249
4425
  init_teardown_stack();
4250
4426
  }
@@ -4287,7 +4463,7 @@ var init_BottomSheetEngine = __esm({
4287
4463
  var baseStyles;
4288
4464
  var init_baseStyles = __esm({
4289
4465
  "src/web-component/baseStyles.ts"() {
4290
- 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}}`;
4466
+ 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}}`;
4291
4467
  }
4292
4468
  });
4293
4469
 
@@ -4384,7 +4560,7 @@ var init_shadow_tree = __esm({
4384
4560
  });
4385
4561
 
4386
4562
  // src/web-component/attributes.ts
4387
- 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;
4563
+ 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;
4388
4564
  var init_attributes = __esm({
4389
4565
  "src/web-component/attributes.ts"() {
4390
4566
  ATTR_SNAP_POINTS = "snap-points";
@@ -4402,6 +4578,8 @@ var init_attributes = __esm({
4402
4578
  ATTR_PERSISTENT = "persistent";
4403
4579
  ATTR_DISABLE_CLOSE = "disable-close";
4404
4580
  ATTR_DISABLE_DRAG = "disable-drag";
4581
+ ATTR_DRAG_FROM = "drag-from";
4582
+ ATTR_DRAG_FROM_CONTENT = "drag-from-content";
4405
4583
  ATTR_CLOSE_ON_ROUTE_CHANGE = "close-on-route-change";
4406
4584
  ATTR_RADIUS = "radius";
4407
4585
  ATTR_MAX_HEIGHT = "max-height";
@@ -4417,7 +4595,9 @@ var init_attributes = __esm({
4417
4595
  ATTR_SNAP,
4418
4596
  ATTR_PERSISTENT,
4419
4597
  ATTR_DISABLE_CLOSE,
4420
- ATTR_DISABLE_DRAG
4598
+ ATTR_DISABLE_DRAG,
4599
+ ATTR_DRAG_FROM,
4600
+ ATTR_DRAG_FROM_CONTENT
4421
4601
  ]);
4422
4602
  OBSERVED_ATTRS = [
4423
4603
  ATTR_SNAP_POINTS,
@@ -4434,6 +4614,8 @@ var init_attributes = __esm({
4434
4614
  ATTR_PERSISTENT,
4435
4615
  ATTR_DISABLE_CLOSE,
4436
4616
  ATTR_DISABLE_DRAG,
4617
+ ATTR_DRAG_FROM,
4618
+ ATTR_DRAG_FROM_CONTENT,
4437
4619
  ATTR_CLOSE_ON_ROUTE_CHANGE,
4438
4620
  ATTR_RADIUS,
4439
4621
  ATTR_MAX_HEIGHT,
@@ -4470,6 +4652,12 @@ var init_attributes = __esm({
4470
4652
  VALID_ANIMATIONS = ["spring", "tween", "ios-spring", "material-bounce", "linear", "snappy"];
4471
4653
  parseMode = (raw) => raw && VALID_MODES.includes(raw) ? raw : "bottom";
4472
4654
  parseAnimation = (raw) => raw && VALID_ANIMATIONS.includes(raw) ? raw : void 0;
4655
+ VALID_DRAG_FROM = [
4656
+ "handle",
4657
+ "sheet",
4658
+ "zones"
4659
+ ];
4660
+ parseDragFrom = (raw) => raw && VALID_DRAG_FROM.includes(raw) ? raw : void 0;
4473
4661
  parseList = (raw) => raw ? raw.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
4474
4662
  parseDimension = (raw) => {
4475
4663
  if (raw === null) return void 0;
@@ -4618,6 +4806,14 @@ var init_BottomSheetElement = __esm({
4618
4806
  case ATTR_DISABLE_DRAG:
4619
4807
  this.engine.setDisableDrag(value === "true");
4620
4808
  break;
4809
+ case ATTR_DRAG_FROM_CONTENT:
4810
+ this.engine.setDragFromContent(value !== "false");
4811
+ break;
4812
+ case ATTR_DRAG_FROM: {
4813
+ const mode = parseDragFrom(value);
4814
+ if (mode) this.engine.setDragFrom(mode);
4815
+ break;
4816
+ }
4621
4817
  case ATTR_SNAP:
4622
4818
  if (value && value !== this.engine.state.activeId) {
4623
4819
  void this.engine.snapTo(value);
@@ -4688,6 +4884,8 @@ var init_BottomSheetElement = __esm({
4688
4884
  persistent: this.getAttribute(ATTR_PERSISTENT) === "true",
4689
4885
  disableClose: this.getAttribute(ATTR_DISABLE_CLOSE) === "true",
4690
4886
  disableDrag: this.getAttribute(ATTR_DISABLE_DRAG) === "true",
4887
+ dragFrom: parseDragFrom(this.getAttribute(ATTR_DRAG_FROM)),
4888
+ dragFromContent: this.getAttribute(ATTR_DRAG_FROM_CONTENT) === null ? void 0 : this.getAttribute(ATTR_DRAG_FROM_CONTENT) !== "false",
4691
4889
  closeOnRouteChange: this.getAttribute(ATTR_CLOSE_ON_ROUTE_CHANGE) === "true",
4692
4890
  radius: parseDimension(this.getAttribute(ATTR_RADIUS)),
4693
4891
  maxHeight: parseDimension(this.getAttribute(ATTR_MAX_HEIGHT)),