@surdeddd/bottom-sheet 0.14.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +13 -0
  2. package/dist/{BottomSheetCore-DJYwWOqt.d.ts → BottomSheetCore-Cgn8b_6A.d.ts} +11 -2
  3. package/dist/{BottomSheetCore-Cp7dWy91.d.cts → BottomSheetCore-VPJZcKcg.d.cts} +11 -2
  4. package/dist/{BottomSheetEngine-Lm7HIVHv.d.cts → BottomSheetEngine-B8C2CwF9.d.cts} +1 -1
  5. package/dist/{BottomSheetEngine-O5PbeKfe.d.ts → BottomSheetEngine-DwYR_ygJ.d.ts} +1 -1
  6. package/dist/core.cjs +100 -9
  7. package/dist/core.d.cts +2 -2
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +100 -9
  10. package/dist/debug.d.cts +1 -1
  11. package/dist/debug.d.ts +1 -1
  12. package/dist/element.cjs +107 -9
  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 +107 -9
  17. package/dist/features.d.cts +4 -4
  18. package/dist/features.d.ts +4 -4
  19. package/dist/{index-Bb5TRmyg.d.cts → index-CnfbOKx0.d.cts} +1 -1
  20. package/dist/{index-Cl9ebCP2.d.ts → index-DcMkhXAy.d.ts} +1 -1
  21. package/dist/index.cjs +100 -9
  22. package/dist/index.d.cts +8 -8
  23. package/dist/index.d.ts +8 -8
  24. package/dist/index.js +100 -9
  25. package/dist/integrations/formik.d.cts +1 -1
  26. package/dist/integrations/formik.d.ts +1 -1
  27. package/dist/integrations/react-hook-form.d.cts +1 -1
  28. package/dist/integrations/react-hook-form.d.ts +1 -1
  29. package/dist/preact.d.cts +2 -2
  30. package/dist/preact.d.ts +2 -2
  31. package/dist/qwik-lib/index.qwik.cjs +98 -9
  32. package/dist/qwik-lib/index.qwik.mjs +98 -9
  33. package/dist/qwik.cjs +100 -9
  34. package/dist/qwik.d.cts +2 -2
  35. package/dist/qwik.d.ts +2 -2
  36. package/dist/qwik.js +100 -9
  37. package/dist/react.cjs +100 -9
  38. package/dist/react.d.cts +3 -3
  39. package/dist/react.d.ts +3 -3
  40. package/dist/react.js +100 -9
  41. package/dist/solid.cjs +100 -9
  42. package/dist/solid.d.cts +10 -1
  43. package/dist/solid.d.ts +10 -1
  44. package/dist/solid.js +100 -9
  45. package/dist/solid.source.jsx +100 -9
  46. package/dist/svelte-core.cjs +100 -9
  47. package/dist/svelte-core.js +100 -9
  48. package/dist/svelte.cjs +100 -9
  49. package/dist/svelte.js +100 -9
  50. package/dist/vue.cjs +101 -10
  51. package/dist/vue.js +101 -10
  52. package/dist/webgl.cjs +154 -34
  53. package/dist/webgl.d.cts +1 -1
  54. package/dist/webgl.d.ts +1 -1
  55. package/dist/webgl.js +154 -34
  56. package/package.json +39 -39
package/dist/index.js CHANGED
@@ -313,6 +313,11 @@ var SnapResolver = class {
313
313
  this.raw = raw;
314
314
  this.recompute();
315
315
  }
316
+ setMode(mode) {
317
+ if (mode === this.mode) return;
318
+ this.mode = mode;
319
+ this.recompute();
320
+ }
316
321
  setAllowedIds(ids) {
317
322
  this.allowedIds = ids;
318
323
  this.rangeCache = null;
@@ -896,6 +901,11 @@ var ScrimController = class {
896
901
  if (this.isDestroyed()) return;
897
902
  this.applyScrimStyles({ interactive });
898
903
  }
904
+ setSheetMode(mode) {
905
+ if (this.isDestroyed() || mode === this.mode) return;
906
+ this.mode = mode;
907
+ this.invalidateOpacityCache();
908
+ }
899
909
  setScrimMode(mode, applySize) {
900
910
  if (this.isDestroyed()) return;
901
911
  if (mode === this.scrimMode) return;
@@ -1818,6 +1828,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1818
1828
  let activePointerId = null;
1819
1829
  let activePointerType = "touch";
1820
1830
  let startCoord = 0;
1831
+ let startCross = 0;
1821
1832
  let lastCoord = 0;
1822
1833
  let pendingStart = false;
1823
1834
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
@@ -1826,6 +1837,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1826
1837
  const axis = isAxisVertical(mode) ? "Y" : "X";
1827
1838
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1828
1839
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
1840
+ const crossOf = (e) => axis === "Y" ? e.clientX : e.clientY;
1829
1841
  const capture = (pointerId) => {
1830
1842
  try {
1831
1843
  handle.setPointerCapture(pointerId);
@@ -1844,6 +1856,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1844
1856
  activePointerId = e.pointerId;
1845
1857
  activePointerType = e.pointerType || "touch";
1846
1858
  startCoord = coordOf(e);
1859
+ startCross = crossOf(e);
1847
1860
  lastCoord = startCoord;
1848
1861
  samples.reset();
1849
1862
  samples.push(e.timeStamp, startCoord);
@@ -1860,7 +1873,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1860
1873
  const rawDelta = coord - startCoord;
1861
1874
  const delta = rawDelta * sign;
1862
1875
  if (pendingStart) {
1863
- const verdict = options.deferStart(e, delta);
1876
+ const verdict = options.deferStart(e, delta, crossOf(e) - startCross);
1864
1877
  if (verdict === false) {
1865
1878
  releaseTracking();
1866
1879
  return;
@@ -2078,12 +2091,45 @@ function isDragAllowedFrom(target, mode) {
2078
2091
  var CONTENT_DRAG_SLOP = 6;
2079
2092
  function decideContentGesture(input) {
2080
2093
  const slop = input.slop ?? CONTENT_DRAG_SLOP;
2094
+ const cross = input.crossDelta ?? 0;
2095
+ const sharesScrollAxis = input.sharesScrollAxis ?? true;
2096
+ if (!sharesScrollAxis) {
2097
+ if (Math.abs(input.delta) < slop && Math.abs(cross) < slop) return "pending";
2098
+ if (Math.abs(input.delta) <= Math.abs(cross)) return "scroll";
2099
+ return "drag";
2100
+ }
2081
2101
  if (Math.abs(input.delta) < slop) return "pending";
2082
2102
  if (input.scrollTop > 0) return "scroll";
2083
2103
  if (input.delta > 0 && input.atMaxSnap) return "scroll";
2084
2104
  return "drag";
2085
2105
  }
2086
2106
 
2107
+ // src/core/primitives/logical-mode.ts
2108
+ var isLogicalMode = (mode) => mode === "start" || mode === "end";
2109
+ var readDirection = (el) => {
2110
+ if (!el) return "ltr";
2111
+ if (typeof getComputedStyle === "function") {
2112
+ try {
2113
+ if (getComputedStyle(el).direction === "rtl") return "rtl";
2114
+ } catch {
2115
+ }
2116
+ }
2117
+ try {
2118
+ const marked = el.closest?.("[dir]");
2119
+ if (marked) {
2120
+ return marked.getAttribute("dir")?.toLowerCase() === "rtl" ? "rtl" : "ltr";
2121
+ }
2122
+ } catch {
2123
+ }
2124
+ return "ltr";
2125
+ };
2126
+ var resolveMode = (mode, el) => {
2127
+ if (!isLogicalMode(mode)) return mode;
2128
+ const rtl = readDirection(el) === "rtl";
2129
+ if (mode === "start") return rtl ? "right" : "left";
2130
+ return rtl ? "left" : "right";
2131
+ };
2132
+
2087
2133
  // src/core/primitives/touch-scroll-guard.ts
2088
2134
  function installTouchScrollGuard(surface, isDragging) {
2089
2135
  const onTouchMove = (e) => {
@@ -2446,7 +2492,7 @@ function resolveEngineOptions(opts, extras) {
2446
2492
  }
2447
2493
  }
2448
2494
  return {
2449
- mode: opts.mode ?? "bottom",
2495
+ mode: resolveMode(opts.mode ?? "bottom", opts.element),
2450
2496
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2451
2497
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2452
2498
  dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
@@ -2550,6 +2596,7 @@ var BottomSheetCore = class {
2550
2596
  __publicField(this, "disableDragFlag");
2551
2597
  __publicField(this, "closeOnRouteChange");
2552
2598
  __publicField(this, "maxHeight");
2599
+ __publicField(this, "maxHeightDeps");
2553
2600
  __publicField(this, "snapPointsRaw");
2554
2601
  __publicField(this, "snaps");
2555
2602
  __publicField(this, "activeId");
@@ -2557,6 +2604,7 @@ var BottomSheetCore = class {
2557
2604
  __publicField(this, "gesture");
2558
2605
  __publicField(this, "contentGesture");
2559
2606
  __publicField(this, "detachSheetGesture", null);
2607
+ __publicField(this, "detachSliderKeyboard", null);
2560
2608
  __publicField(this, "rootEl", null);
2561
2609
  __publicField(this, "destroyed", false);
2562
2610
  __publicField(this, "restClosed", false);
@@ -2608,6 +2656,7 @@ var BottomSheetCore = class {
2608
2656
  this.screenComponent = opts.scrim ?? opts.screenComponent;
2609
2657
  this.scrimParent = this.screenComponent?.parentElement ?? null;
2610
2658
  this.mode = resolved.mode;
2659
+ this.element.dataset.mode = this.mode;
2611
2660
  this.transformTemplate = buildTransformTemplate(this.mode);
2612
2661
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2613
2662
  this.flickVelocity = resolved.flickVelocity;
@@ -2674,7 +2723,7 @@ var BottomSheetCore = class {
2674
2723
  auditVhUsage(this.snapPointsRaw);
2675
2724
  this.auditDuplicateSnapIds(this.snapPointsRaw);
2676
2725
  this.rootEl = this.element.closest(".bs-root");
2677
- this.maxHeight = createMaxHeightController({
2726
+ this.maxHeightDeps = {
2678
2727
  element: this.element,
2679
2728
  mode: this.mode,
2680
2729
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
@@ -2682,7 +2731,8 @@ var BottomSheetCore = class {
2682
2731
  this.snaps.setMaxAxisSize(size);
2683
2732
  },
2684
2733
  recompute: () => this.recompute()
2685
- });
2734
+ };
2735
+ this.maxHeight = createMaxHeightController(this.maxHeightDeps);
2686
2736
  this.fitDeps = {
2687
2737
  element: this.element,
2688
2738
  scrollContainer: this.scrollContainer,
@@ -3016,6 +3066,37 @@ var BottomSheetCore = class {
3016
3066
  getDragFrom() {
3017
3067
  return this.dragFromMode;
3018
3068
  }
3069
+ setMode(mode) {
3070
+ if (this.destroyed) return;
3071
+ const next = resolveMode(mode, this.element);
3072
+ if (next === this.mode) return;
3073
+ const wasVertical = this.mode === "bottom" || this.mode === "top";
3074
+ const nowVertical = next === "bottom" || next === "top";
3075
+ this.gesture?.forceClearDragState();
3076
+ this.detachSheetGesture?.();
3077
+ this.animation.cancel();
3078
+ this.element.style.removeProperty(layoutAxis(this.mode));
3079
+ this.mode = next;
3080
+ this.element.dataset.mode = next;
3081
+ this.transformTemplate = buildTransformTemplate(next);
3082
+ this.maxHeightDeps.mode = next;
3083
+ this.fitDeps.mode = next;
3084
+ this.snaps.setMode(next);
3085
+ this.scrim.setSheetMode(next);
3086
+ if (wasVertical !== nowVertical) {
3087
+ this.aria = new AriaSliderWriter(this.handle, next);
3088
+ }
3089
+ this.detachSliderKeyboard?.();
3090
+ this.mountSliderKeyboard();
3091
+ this.mountSheetGesture();
3092
+ this.recompute();
3093
+ const active = this.snaps.findById(this.activeId);
3094
+ if (active) this.applySize(active.size);
3095
+ this.updateAriaSlider();
3096
+ }
3097
+ getMode() {
3098
+ return this.mode;
3099
+ }
3019
3100
  isTop() {
3020
3101
  return this.isTopSheet;
3021
3102
  }
@@ -3364,7 +3445,7 @@ var BottomSheetCore = class {
3364
3445
  const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3365
3446
  return point?.dragFromContent ?? this.dragFromContentDefault;
3366
3447
  }
3367
- decideContentDrag(surface, e, delta) {
3448
+ decideContentDrag(surface, e, delta, crossDelta) {
3368
3449
  if (this.destroyed) return false;
3369
3450
  if (e.pointerType === "mouse") return false;
3370
3451
  if (this.gesture?.isDragging) return false;
@@ -3372,6 +3453,8 @@ var BottomSheetCore = class {
3372
3453
  if (!isDragAllowedFrom(e.target, "sheet")) return false;
3373
3454
  const decision = decideContentGesture({
3374
3455
  delta,
3456
+ crossDelta,
3457
+ sharesScrollAxis: this.mode === "bottom" || this.mode === "top",
3375
3458
  scrollTop: surface.scrollTop,
3376
3459
  atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3377
3460
  });
@@ -3384,7 +3467,7 @@ var BottomSheetCore = class {
3384
3467
  const controller = new GestureController(
3385
3468
  this.buildGestureDeps(surface, {
3386
3469
  manageTouchAction: false,
3387
- deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
3470
+ deferStart: (e, delta, crossDelta) => this.decideContentDrag(surface, e, delta, crossDelta)
3388
3471
  })
3389
3472
  );
3390
3473
  this.contentGesture = controller;
@@ -3510,7 +3593,11 @@ var BottomSheetCore = class {
3510
3593
  );
3511
3594
  }
3512
3595
  }
3513
- this.teardowns.add(installSliderKeyboard({
3596
+ this.mountSliderKeyboard();
3597
+ this.scrim.attach();
3598
+ }
3599
+ mountSliderKeyboard() {
3600
+ const detach = installSliderKeyboard({
3514
3601
  handle: this.handle,
3515
3602
  mode: this.mode,
3516
3603
  isDestroyed: () => this.destroyed,
@@ -3519,8 +3606,12 @@ var BottomSheetCore = class {
3519
3606
  snapTo: (id) => {
3520
3607
  void this.snapTo(id);
3521
3608
  }
3522
- }));
3523
- this.scrim.attach();
3609
+ });
3610
+ this.detachSliderKeyboard = detach;
3611
+ this.teardowns.add(() => {
3612
+ this.detachSliderKeyboard?.();
3613
+ this.detachSliderKeyboard = null;
3614
+ });
3524
3615
  }
3525
3616
  settleAfterDrag(delta, velocity, kind = "touch") {
3526
3617
  const signal = this.newCycle();
@@ -1,4 +1,4 @@
1
- import { d as SheetEventMap } from '../BottomSheetCore-Cp7dWy91.cjs';
1
+ import { S as SheetEventMap } from '../BottomSheetCore-VPJZcKcg.cjs';
2
2
  import '../transform-jVfAikE9.cjs';
3
3
 
4
4
  type FormikStateLike = {
@@ -1,4 +1,4 @@
1
- import { d as SheetEventMap } from '../BottomSheetCore-DJYwWOqt.js';
1
+ import { S as SheetEventMap } from '../BottomSheetCore-Cgn8b_6A.js';
2
2
  import '../transform-jVfAikE9.js';
3
3
 
4
4
  type FormikStateLike = {
@@ -1,4 +1,4 @@
1
- import { d as SheetEventMap } from '../BottomSheetCore-Cp7dWy91.cjs';
1
+ import { S as SheetEventMap } from '../BottomSheetCore-VPJZcKcg.cjs';
2
2
  import '../transform-jVfAikE9.cjs';
3
3
 
4
4
  type RhfFormStateLike = {
@@ -1,4 +1,4 @@
1
- import { d as SheetEventMap } from '../BottomSheetCore-DJYwWOqt.js';
1
+ import { S as SheetEventMap } from '../BottomSheetCore-Cgn8b_6A.js';
2
2
  import '../transform-jVfAikE9.js';
3
3
 
4
4
  type RhfFormStateLike = {
package/dist/preact.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { BottomSheet, BottomSheetFromConfig, BottomSheetFromConfigProps, BottomSheetHandle, BottomSheetProps, HeaderProp, Overlay, OverlayHandle, OverlayProps, SheetConfig, UseBottomSheetRefs, UseBottomSheetReturn, UseOverlayReturn, useBottomSheet, useOverlay } from './react.cjs';
2
- export { E as EngineState, c as SheetMode, e as SnapPoint, b as SnapPointDef } from './BottomSheetCore-Cp7dWy91.cjs';
2
+ export { E as EngineState, b as SheetMode, d as SnapPoint, a as SnapPointDef } from './BottomSheetCore-VPJZcKcg.cjs';
3
3
  export { OverlayEdge, OverlayOptions, OverlayState } from './overlay.cjs';
4
4
  import 'react';
5
- import './BottomSheetEngine-Lm7HIVHv.cjs';
5
+ import './BottomSheetEngine-B8C2CwF9.cjs';
6
6
  import './teleport-7uYNiEAT.cjs';
7
7
  import './transform-jVfAikE9.cjs';
package/dist/preact.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { BottomSheet, BottomSheetFromConfig, BottomSheetFromConfigProps, BottomSheetHandle, BottomSheetProps, HeaderProp, Overlay, OverlayHandle, OverlayProps, SheetConfig, UseBottomSheetRefs, UseBottomSheetReturn, UseOverlayReturn, useBottomSheet, useOverlay } from './react.js';
2
- export { E as EngineState, c as SheetMode, e as SnapPoint, b as SnapPointDef } from './BottomSheetCore-DJYwWOqt.js';
2
+ export { E as EngineState, b as SheetMode, d as SnapPoint, a as SnapPointDef } from './BottomSheetCore-Cgn8b_6A.js';
3
3
  export { OverlayEdge, OverlayOptions, OverlayState } from './overlay.js';
4
4
  import 'react';
5
- import './BottomSheetEngine-O5PbeKfe.js';
5
+ import './BottomSheetEngine-DwYR_ygJ.js';
6
6
  import './teleport-7uYNiEAT.js';
7
7
  import './transform-jVfAikE9.js';
@@ -302,6 +302,11 @@ class SnapResolver {
302
302
  this.raw = raw;
303
303
  this.recompute();
304
304
  }
305
+ setMode(mode) {
306
+ if (mode === this.mode) return;
307
+ this.mode = mode;
308
+ this.recompute();
309
+ }
305
310
  setAllowedIds(ids) {
306
311
  this.allowedIds = ids;
307
312
  this.rangeCache = null;
@@ -904,6 +909,11 @@ class ScrimController {
904
909
  interactive
905
910
  });
906
911
  }
912
+ setSheetMode(mode) {
913
+ if (this.isDestroyed() || mode === this.mode) return;
914
+ this.mode = mode;
915
+ this.invalidateOpacityCache();
916
+ }
907
917
  setScrimMode(mode, applySize) {
908
918
  if (this.isDestroyed()) return;
909
919
  if (mode === this.scrimMode) return;
@@ -1838,6 +1848,7 @@ const installGestures = (handle, mode, callbacks, options = {}) => {
1838
1848
  let activePointerId = null;
1839
1849
  let activePointerType = "touch";
1840
1850
  let startCoord = 0;
1851
+ let startCross = 0;
1841
1852
  let lastCoord = 0;
1842
1853
  let pendingStart = false;
1843
1854
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
@@ -1846,6 +1857,7 @@ const installGestures = (handle, mode, callbacks, options = {}) => {
1846
1857
  const axis = isAxisVertical(mode) ? "Y" : "X";
1847
1858
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1848
1859
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
1860
+ const crossOf = (e) => axis === "Y" ? e.clientX : e.clientY;
1849
1861
  const capture = (pointerId) => {
1850
1862
  try {
1851
1863
  handle.setPointerCapture(pointerId);
@@ -1864,6 +1876,7 @@ const installGestures = (handle, mode, callbacks, options = {}) => {
1864
1876
  activePointerId = e.pointerId;
1865
1877
  activePointerType = e.pointerType || "touch";
1866
1878
  startCoord = coordOf(e);
1879
+ startCross = crossOf(e);
1867
1880
  lastCoord = startCoord;
1868
1881
  samples.reset();
1869
1882
  samples.push(e.timeStamp, startCoord);
@@ -1880,7 +1893,7 @@ const installGestures = (handle, mode, callbacks, options = {}) => {
1880
1893
  const rawDelta = coord - startCoord;
1881
1894
  const delta = rawDelta * sign;
1882
1895
  if (pendingStart) {
1883
- const verdict = options.deferStart(e, delta);
1896
+ const verdict = options.deferStart(e, delta, crossOf(e) - startCross);
1884
1897
  if (verdict === false) {
1885
1898
  releaseTracking();
1886
1899
  return;
@@ -2093,11 +2106,42 @@ function isDragAllowedFrom(target, mode) {
2093
2106
  const CONTENT_DRAG_SLOP = 6;
2094
2107
  function decideContentGesture(input) {
2095
2108
  const slop = input.slop ?? CONTENT_DRAG_SLOP;
2109
+ const cross = input.crossDelta ?? 0;
2110
+ const sharesScrollAxis = input.sharesScrollAxis ?? true;
2111
+ if (!sharesScrollAxis) {
2112
+ if (Math.abs(input.delta) < slop && Math.abs(cross) < slop) return "pending";
2113
+ if (Math.abs(input.delta) <= Math.abs(cross)) return "scroll";
2114
+ return "drag";
2115
+ }
2096
2116
  if (Math.abs(input.delta) < slop) return "pending";
2097
2117
  if (input.scrollTop > 0) return "scroll";
2098
2118
  if (input.delta > 0 && input.atMaxSnap) return "scroll";
2099
2119
  return "drag";
2100
2120
  }
2121
+ const isLogicalMode = (mode) => mode === "start" || mode === "end";
2122
+ const readDirection = (el) => {
2123
+ if (!el) return "ltr";
2124
+ if (typeof getComputedStyle === "function") {
2125
+ try {
2126
+ if (getComputedStyle(el).direction === "rtl") return "rtl";
2127
+ } catch {
2128
+ }
2129
+ }
2130
+ try {
2131
+ const marked = el.closest?.("[dir]");
2132
+ if (marked) {
2133
+ return marked.getAttribute("dir")?.toLowerCase() === "rtl" ? "rtl" : "ltr";
2134
+ }
2135
+ } catch {
2136
+ }
2137
+ return "ltr";
2138
+ };
2139
+ const resolveMode = (mode, el) => {
2140
+ if (!isLogicalMode(mode)) return mode;
2141
+ const rtl = readDirection(el) === "rtl";
2142
+ if (mode === "start") return rtl ? "right" : "left";
2143
+ return rtl ? "left" : "right";
2144
+ };
2101
2145
  function installTouchScrollGuard(surface, isDragging) {
2102
2146
  const onTouchMove = (e) => {
2103
2147
  if (!isDragging()) return;
@@ -2498,7 +2542,7 @@ function resolveEngineOptions(opts, extras) {
2498
2542
  }
2499
2543
  }
2500
2544
  return {
2501
- mode: opts.mode ?? "bottom",
2545
+ mode: resolveMode(opts.mode ?? "bottom", opts.element),
2502
2546
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2503
2547
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2504
2548
  dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
@@ -2598,6 +2642,7 @@ class BottomSheetCore {
2598
2642
  __publicField(this, "disableDragFlag");
2599
2643
  __publicField(this, "closeOnRouteChange");
2600
2644
  __publicField(this, "maxHeight");
2645
+ __publicField(this, "maxHeightDeps");
2601
2646
  __publicField(this, "snapPointsRaw");
2602
2647
  __publicField(this, "snaps");
2603
2648
  __publicField(this, "activeId");
@@ -2605,6 +2650,7 @@ class BottomSheetCore {
2605
2650
  __publicField(this, "gesture");
2606
2651
  __publicField(this, "contentGesture");
2607
2652
  __publicField(this, "detachSheetGesture", null);
2653
+ __publicField(this, "detachSliderKeyboard", null);
2608
2654
  __publicField(this, "rootEl", null);
2609
2655
  __publicField(this, "destroyed", false);
2610
2656
  __publicField(this, "restClosed", false);
@@ -2657,6 +2703,7 @@ class BottomSheetCore {
2657
2703
  this.screenComponent = opts.scrim ?? opts.screenComponent;
2658
2704
  this.scrimParent = this.screenComponent?.parentElement ?? null;
2659
2705
  this.mode = resolved.mode;
2706
+ this.element.dataset.mode = this.mode;
2660
2707
  this.transformTemplate = buildTransformTemplate(this.mode);
2661
2708
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2662
2709
  this.flickVelocity = resolved.flickVelocity;
@@ -2714,7 +2761,7 @@ class BottomSheetCore {
2714
2761
  auditVhUsage(this.snapPointsRaw);
2715
2762
  this.auditDuplicateSnapIds(this.snapPointsRaw);
2716
2763
  this.rootEl = this.element.closest(".bs-root");
2717
- this.maxHeight = createMaxHeightController({
2764
+ this.maxHeightDeps = {
2718
2765
  element: this.element,
2719
2766
  mode: this.mode,
2720
2767
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
@@ -2722,7 +2769,8 @@ class BottomSheetCore {
2722
2769
  this.snaps.setMaxAxisSize(size);
2723
2770
  },
2724
2771
  recompute: () => this.recompute()
2725
- });
2772
+ };
2773
+ this.maxHeight = createMaxHeightController(this.maxHeightDeps);
2726
2774
  this.fitDeps = {
2727
2775
  element: this.element,
2728
2776
  scrollContainer: this.scrollContainer,
@@ -3052,6 +3100,37 @@ class BottomSheetCore {
3052
3100
  getDragFrom() {
3053
3101
  return this.dragFromMode;
3054
3102
  }
3103
+ setMode(mode) {
3104
+ if (this.destroyed) return;
3105
+ const next = resolveMode(mode, this.element);
3106
+ if (next === this.mode) return;
3107
+ const wasVertical = this.mode === "bottom" || this.mode === "top";
3108
+ const nowVertical = next === "bottom" || next === "top";
3109
+ this.gesture?.forceClearDragState();
3110
+ this.detachSheetGesture?.();
3111
+ this.animation.cancel();
3112
+ this.element.style.removeProperty(layoutAxis(this.mode));
3113
+ this.mode = next;
3114
+ this.element.dataset.mode = next;
3115
+ this.transformTemplate = buildTransformTemplate(next);
3116
+ this.maxHeightDeps.mode = next;
3117
+ this.fitDeps.mode = next;
3118
+ this.snaps.setMode(next);
3119
+ this.scrim.setSheetMode(next);
3120
+ if (wasVertical !== nowVertical) {
3121
+ this.aria = new AriaSliderWriter(this.handle, next);
3122
+ }
3123
+ this.detachSliderKeyboard?.();
3124
+ this.mountSliderKeyboard();
3125
+ this.mountSheetGesture();
3126
+ this.recompute();
3127
+ const active = this.snaps.findById(this.activeId);
3128
+ if (active) this.applySize(active.size);
3129
+ this.updateAriaSlider();
3130
+ }
3131
+ getMode() {
3132
+ return this.mode;
3133
+ }
3055
3134
  isTop() {
3056
3135
  return this.isTopSheet;
3057
3136
  }
@@ -3390,7 +3469,7 @@ class BottomSheetCore {
3390
3469
  const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3391
3470
  return point?.dragFromContent ?? this.dragFromContentDefault;
3392
3471
  }
3393
- decideContentDrag(surface, e, delta) {
3472
+ decideContentDrag(surface, e, delta, crossDelta) {
3394
3473
  if (this.destroyed) return false;
3395
3474
  if (e.pointerType === "mouse") return false;
3396
3475
  if (this.gesture?.isDragging) return false;
@@ -3398,6 +3477,8 @@ class BottomSheetCore {
3398
3477
  if (!isDragAllowedFrom(e.target, "sheet")) return false;
3399
3478
  const decision = decideContentGesture({
3400
3479
  delta,
3480
+ crossDelta,
3481
+ sharesScrollAxis: this.mode === "bottom" || this.mode === "top",
3401
3482
  scrollTop: surface.scrollTop,
3402
3483
  atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3403
3484
  });
@@ -3409,7 +3490,7 @@ class BottomSheetCore {
3409
3490
  if (this.contentGesture) return;
3410
3491
  const controller = new GestureController(this.buildGestureDeps(surface, {
3411
3492
  manageTouchAction: false,
3412
- deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
3493
+ deferStart: (e, delta, crossDelta) => this.decideContentDrag(surface, e, delta, crossDelta)
3413
3494
  }));
3414
3495
  this.contentGesture = controller;
3415
3496
  const detachGestures = controller.install();
@@ -3527,7 +3608,11 @@ class BottomSheetCore {
3527
3608
  this.teardowns.add(() => document.removeEventListener("keydown", onKey));
3528
3609
  }
3529
3610
  }
3530
- this.teardowns.add(installSliderKeyboard({
3611
+ this.mountSliderKeyboard();
3612
+ this.scrim.attach();
3613
+ }
3614
+ mountSliderKeyboard() {
3615
+ const detach = installSliderKeyboard({
3531
3616
  handle: this.handle,
3532
3617
  mode: this.mode,
3533
3618
  isDestroyed: () => this.destroyed,
@@ -3536,8 +3621,12 @@ class BottomSheetCore {
3536
3621
  snapTo: (id) => {
3537
3622
  void this.snapTo(id);
3538
3623
  }
3539
- }));
3540
- this.scrim.attach();
3624
+ });
3625
+ this.detachSliderKeyboard = detach;
3626
+ this.teardowns.add(() => {
3627
+ this.detachSliderKeyboard?.();
3628
+ this.detachSliderKeyboard = null;
3629
+ });
3541
3630
  }
3542
3631
  settleAfterDrag(delta, velocity, kind = "touch") {
3543
3632
  const signal = this.newCycle();