@surdeddd/bottom-sheet 0.14.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +100 -9
  51. package/dist/vue.js +100 -9
  52. package/dist/webgl.cjs +104 -14
  53. package/dist/webgl.d.cts +1 -1
  54. package/dist/webgl.d.ts +1 -1
  55. package/dist/webgl.js +104 -14
  56. package/package.json +39 -39
package/dist/vue.cjs CHANGED
@@ -317,6 +317,11 @@ var SnapResolver = class {
317
317
  this.raw = raw;
318
318
  this.recompute();
319
319
  }
320
+ setMode(mode) {
321
+ if (mode === this.mode) return;
322
+ this.mode = mode;
323
+ this.recompute();
324
+ }
320
325
  setAllowedIds(ids) {
321
326
  this.allowedIds = ids;
322
327
  this.rangeCache = null;
@@ -900,6 +905,11 @@ var ScrimController = class {
900
905
  if (this.isDestroyed()) return;
901
906
  this.applyScrimStyles({ interactive });
902
907
  }
908
+ setSheetMode(mode) {
909
+ if (this.isDestroyed() || mode === this.mode) return;
910
+ this.mode = mode;
911
+ this.invalidateOpacityCache();
912
+ }
903
913
  setScrimMode(mode, applySize) {
904
914
  if (this.isDestroyed()) return;
905
915
  if (mode === this.scrimMode) return;
@@ -1822,6 +1832,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1822
1832
  let activePointerId = null;
1823
1833
  let activePointerType = "touch";
1824
1834
  let startCoord = 0;
1835
+ let startCross = 0;
1825
1836
  let lastCoord = 0;
1826
1837
  let pendingStart = false;
1827
1838
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
@@ -1830,6 +1841,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1830
1841
  const axis = isAxisVertical(mode) ? "Y" : "X";
1831
1842
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1832
1843
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
1844
+ const crossOf = (e) => axis === "Y" ? e.clientX : e.clientY;
1833
1845
  const capture = (pointerId) => {
1834
1846
  try {
1835
1847
  handle.setPointerCapture(pointerId);
@@ -1848,6 +1860,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1848
1860
  activePointerId = e.pointerId;
1849
1861
  activePointerType = e.pointerType || "touch";
1850
1862
  startCoord = coordOf(e);
1863
+ startCross = crossOf(e);
1851
1864
  lastCoord = startCoord;
1852
1865
  samples.reset();
1853
1866
  samples.push(e.timeStamp, startCoord);
@@ -1864,7 +1877,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1864
1877
  const rawDelta = coord - startCoord;
1865
1878
  const delta = rawDelta * sign;
1866
1879
  if (pendingStart) {
1867
- const verdict = options.deferStart(e, delta);
1880
+ const verdict = options.deferStart(e, delta, crossOf(e) - startCross);
1868
1881
  if (verdict === false) {
1869
1882
  releaseTracking();
1870
1883
  return;
@@ -2082,12 +2095,45 @@ function isDragAllowedFrom(target, mode) {
2082
2095
  var CONTENT_DRAG_SLOP = 6;
2083
2096
  function decideContentGesture(input) {
2084
2097
  const slop = input.slop ?? CONTENT_DRAG_SLOP;
2098
+ const cross = input.crossDelta ?? 0;
2099
+ const sharesScrollAxis = input.sharesScrollAxis ?? true;
2100
+ if (!sharesScrollAxis) {
2101
+ if (Math.abs(input.delta) < slop && Math.abs(cross) < slop) return "pending";
2102
+ if (Math.abs(input.delta) <= Math.abs(cross)) return "scroll";
2103
+ return "drag";
2104
+ }
2085
2105
  if (Math.abs(input.delta) < slop) return "pending";
2086
2106
  if (input.scrollTop > 0) return "scroll";
2087
2107
  if (input.delta > 0 && input.atMaxSnap) return "scroll";
2088
2108
  return "drag";
2089
2109
  }
2090
2110
 
2111
+ // src/core/primitives/logical-mode.ts
2112
+ var isLogicalMode = (mode) => mode === "start" || mode === "end";
2113
+ var readDirection = (el) => {
2114
+ if (!el) return "ltr";
2115
+ if (typeof getComputedStyle === "function") {
2116
+ try {
2117
+ if (getComputedStyle(el).direction === "rtl") return "rtl";
2118
+ } catch {
2119
+ }
2120
+ }
2121
+ try {
2122
+ const marked = el.closest?.("[dir]");
2123
+ if (marked) {
2124
+ return marked.getAttribute("dir")?.toLowerCase() === "rtl" ? "rtl" : "ltr";
2125
+ }
2126
+ } catch {
2127
+ }
2128
+ return "ltr";
2129
+ };
2130
+ var resolveMode = (mode, el) => {
2131
+ if (!isLogicalMode(mode)) return mode;
2132
+ const rtl = readDirection(el) === "rtl";
2133
+ if (mode === "start") return rtl ? "right" : "left";
2134
+ return rtl ? "left" : "right";
2135
+ };
2136
+
2091
2137
  // src/core/primitives/touch-scroll-guard.ts
2092
2138
  function installTouchScrollGuard(surface, isDragging) {
2093
2139
  const onTouchMove = (e) => {
@@ -2450,7 +2496,7 @@ function resolveEngineOptions(opts, extras) {
2450
2496
  }
2451
2497
  }
2452
2498
  return {
2453
- mode: opts.mode ?? "bottom",
2499
+ mode: resolveMode(opts.mode ?? "bottom", opts.element),
2454
2500
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2455
2501
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2456
2502
  dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
@@ -2554,6 +2600,7 @@ var BottomSheetCore = class {
2554
2600
  __publicField(this, "disableDragFlag");
2555
2601
  __publicField(this, "closeOnRouteChange");
2556
2602
  __publicField(this, "maxHeight");
2603
+ __publicField(this, "maxHeightDeps");
2557
2604
  __publicField(this, "snapPointsRaw");
2558
2605
  __publicField(this, "snaps");
2559
2606
  __publicField(this, "activeId");
@@ -2561,6 +2608,7 @@ var BottomSheetCore = class {
2561
2608
  __publicField(this, "gesture");
2562
2609
  __publicField(this, "contentGesture");
2563
2610
  __publicField(this, "detachSheetGesture", null);
2611
+ __publicField(this, "detachSliderKeyboard", null);
2564
2612
  __publicField(this, "rootEl", null);
2565
2613
  __publicField(this, "destroyed", false);
2566
2614
  __publicField(this, "restClosed", false);
@@ -2612,6 +2660,7 @@ var BottomSheetCore = class {
2612
2660
  this.screenComponent = opts.scrim ?? opts.screenComponent;
2613
2661
  this.scrimParent = this.screenComponent?.parentElement ?? null;
2614
2662
  this.mode = resolved.mode;
2663
+ this.element.dataset.mode = this.mode;
2615
2664
  this.transformTemplate = buildTransformTemplate(this.mode);
2616
2665
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2617
2666
  this.flickVelocity = resolved.flickVelocity;
@@ -2678,7 +2727,7 @@ var BottomSheetCore = class {
2678
2727
  auditVhUsage(this.snapPointsRaw);
2679
2728
  this.auditDuplicateSnapIds(this.snapPointsRaw);
2680
2729
  this.rootEl = this.element.closest(".bs-root");
2681
- this.maxHeight = createMaxHeightController({
2730
+ this.maxHeightDeps = {
2682
2731
  element: this.element,
2683
2732
  mode: this.mode,
2684
2733
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
@@ -2686,7 +2735,8 @@ var BottomSheetCore = class {
2686
2735
  this.snaps.setMaxAxisSize(size);
2687
2736
  },
2688
2737
  recompute: () => this.recompute()
2689
- });
2738
+ };
2739
+ this.maxHeight = createMaxHeightController(this.maxHeightDeps);
2690
2740
  this.fitDeps = {
2691
2741
  element: this.element,
2692
2742
  scrollContainer: this.scrollContainer,
@@ -3020,6 +3070,37 @@ var BottomSheetCore = class {
3020
3070
  getDragFrom() {
3021
3071
  return this.dragFromMode;
3022
3072
  }
3073
+ setMode(mode) {
3074
+ if (this.destroyed) return;
3075
+ const next = resolveMode(mode, this.element);
3076
+ if (next === this.mode) return;
3077
+ const wasVertical = this.mode === "bottom" || this.mode === "top";
3078
+ const nowVertical = next === "bottom" || next === "top";
3079
+ this.gesture?.forceClearDragState();
3080
+ this.detachSheetGesture?.();
3081
+ this.animation.cancel();
3082
+ this.element.style.removeProperty(layoutAxis(this.mode));
3083
+ this.mode = next;
3084
+ this.element.dataset.mode = next;
3085
+ this.transformTemplate = buildTransformTemplate(next);
3086
+ this.maxHeightDeps.mode = next;
3087
+ this.fitDeps.mode = next;
3088
+ this.snaps.setMode(next);
3089
+ this.scrim.setSheetMode(next);
3090
+ if (wasVertical !== nowVertical) {
3091
+ this.aria = new AriaSliderWriter(this.handle, next);
3092
+ }
3093
+ this.detachSliderKeyboard?.();
3094
+ this.mountSliderKeyboard();
3095
+ this.mountSheetGesture();
3096
+ this.recompute();
3097
+ const active = this.snaps.findById(this.activeId);
3098
+ if (active) this.applySize(active.size);
3099
+ this.updateAriaSlider();
3100
+ }
3101
+ getMode() {
3102
+ return this.mode;
3103
+ }
3023
3104
  isTop() {
3024
3105
  return this.isTopSheet;
3025
3106
  }
@@ -3368,7 +3449,7 @@ var BottomSheetCore = class {
3368
3449
  const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3369
3450
  return point?.dragFromContent ?? this.dragFromContentDefault;
3370
3451
  }
3371
- decideContentDrag(surface, e, delta) {
3452
+ decideContentDrag(surface, e, delta, crossDelta) {
3372
3453
  if (this.destroyed) return false;
3373
3454
  if (e.pointerType === "mouse") return false;
3374
3455
  if (this.gesture?.isDragging) return false;
@@ -3376,6 +3457,8 @@ var BottomSheetCore = class {
3376
3457
  if (!isDragAllowedFrom(e.target, "sheet")) return false;
3377
3458
  const decision = decideContentGesture({
3378
3459
  delta,
3460
+ crossDelta,
3461
+ sharesScrollAxis: this.mode === "bottom" || this.mode === "top",
3379
3462
  scrollTop: surface.scrollTop,
3380
3463
  atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3381
3464
  });
@@ -3388,7 +3471,7 @@ var BottomSheetCore = class {
3388
3471
  const controller = new GestureController(
3389
3472
  this.buildGestureDeps(surface, {
3390
3473
  manageTouchAction: false,
3391
- deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
3474
+ deferStart: (e, delta, crossDelta) => this.decideContentDrag(surface, e, delta, crossDelta)
3392
3475
  })
3393
3476
  );
3394
3477
  this.contentGesture = controller;
@@ -3514,7 +3597,11 @@ var BottomSheetCore = class {
3514
3597
  );
3515
3598
  }
3516
3599
  }
3517
- this.teardowns.add(installSliderKeyboard({
3600
+ this.mountSliderKeyboard();
3601
+ this.scrim.attach();
3602
+ }
3603
+ mountSliderKeyboard() {
3604
+ const detach = installSliderKeyboard({
3518
3605
  handle: this.handle,
3519
3606
  mode: this.mode,
3520
3607
  isDestroyed: () => this.destroyed,
@@ -3523,8 +3610,12 @@ var BottomSheetCore = class {
3523
3610
  snapTo: (id) => {
3524
3611
  void this.snapTo(id);
3525
3612
  }
3526
- }));
3527
- this.scrim.attach();
3613
+ });
3614
+ this.detachSliderKeyboard = detach;
3615
+ this.teardowns.add(() => {
3616
+ this.detachSliderKeyboard?.();
3617
+ this.detachSliderKeyboard = null;
3618
+ });
3528
3619
  }
3529
3620
  settleAfterDrag(delta, velocity, kind = "touch") {
3530
3621
  const signal = this.newCycle();
package/dist/vue.js CHANGED
@@ -315,6 +315,11 @@ var SnapResolver = class {
315
315
  this.raw = raw;
316
316
  this.recompute();
317
317
  }
318
+ setMode(mode) {
319
+ if (mode === this.mode) return;
320
+ this.mode = mode;
321
+ this.recompute();
322
+ }
318
323
  setAllowedIds(ids) {
319
324
  this.allowedIds = ids;
320
325
  this.rangeCache = null;
@@ -898,6 +903,11 @@ var ScrimController = class {
898
903
  if (this.isDestroyed()) return;
899
904
  this.applyScrimStyles({ interactive });
900
905
  }
906
+ setSheetMode(mode) {
907
+ if (this.isDestroyed() || mode === this.mode) return;
908
+ this.mode = mode;
909
+ this.invalidateOpacityCache();
910
+ }
901
911
  setScrimMode(mode, applySize) {
902
912
  if (this.isDestroyed()) return;
903
913
  if (mode === this.scrimMode) return;
@@ -1820,6 +1830,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1820
1830
  let activePointerId = null;
1821
1831
  let activePointerType = "touch";
1822
1832
  let startCoord = 0;
1833
+ let startCross = 0;
1823
1834
  let lastCoord = 0;
1824
1835
  let pendingStart = false;
1825
1836
  const VELOCITY_WINDOW_MS = (kind) => kind === "mouse" ? 160 : 120;
@@ -1828,6 +1839,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1828
1839
  const axis = isAxisVertical(mode) ? "Y" : "X";
1829
1840
  const sign = mode === "bottom" || mode === "right" ? -1 : 1;
1830
1841
  const coordOf = (e) => axis === "Y" ? e.clientY : e.clientX;
1842
+ const crossOf = (e) => axis === "Y" ? e.clientX : e.clientY;
1831
1843
  const capture = (pointerId) => {
1832
1844
  try {
1833
1845
  handle.setPointerCapture(pointerId);
@@ -1846,6 +1858,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1846
1858
  activePointerId = e.pointerId;
1847
1859
  activePointerType = e.pointerType || "touch";
1848
1860
  startCoord = coordOf(e);
1861
+ startCross = crossOf(e);
1849
1862
  lastCoord = startCoord;
1850
1863
  samples.reset();
1851
1864
  samples.push(e.timeStamp, startCoord);
@@ -1862,7 +1875,7 @@ var installGestures = (handle, mode, callbacks, options = {}) => {
1862
1875
  const rawDelta = coord - startCoord;
1863
1876
  const delta = rawDelta * sign;
1864
1877
  if (pendingStart) {
1865
- const verdict = options.deferStart(e, delta);
1878
+ const verdict = options.deferStart(e, delta, crossOf(e) - startCross);
1866
1879
  if (verdict === false) {
1867
1880
  releaseTracking();
1868
1881
  return;
@@ -2080,12 +2093,45 @@ function isDragAllowedFrom(target, mode) {
2080
2093
  var CONTENT_DRAG_SLOP = 6;
2081
2094
  function decideContentGesture(input) {
2082
2095
  const slop = input.slop ?? CONTENT_DRAG_SLOP;
2096
+ const cross = input.crossDelta ?? 0;
2097
+ const sharesScrollAxis = input.sharesScrollAxis ?? true;
2098
+ if (!sharesScrollAxis) {
2099
+ if (Math.abs(input.delta) < slop && Math.abs(cross) < slop) return "pending";
2100
+ if (Math.abs(input.delta) <= Math.abs(cross)) return "scroll";
2101
+ return "drag";
2102
+ }
2083
2103
  if (Math.abs(input.delta) < slop) return "pending";
2084
2104
  if (input.scrollTop > 0) return "scroll";
2085
2105
  if (input.delta > 0 && input.atMaxSnap) return "scroll";
2086
2106
  return "drag";
2087
2107
  }
2088
2108
 
2109
+ // src/core/primitives/logical-mode.ts
2110
+ var isLogicalMode = (mode) => mode === "start" || mode === "end";
2111
+ var readDirection = (el) => {
2112
+ if (!el) return "ltr";
2113
+ if (typeof getComputedStyle === "function") {
2114
+ try {
2115
+ if (getComputedStyle(el).direction === "rtl") return "rtl";
2116
+ } catch {
2117
+ }
2118
+ }
2119
+ try {
2120
+ const marked = el.closest?.("[dir]");
2121
+ if (marked) {
2122
+ return marked.getAttribute("dir")?.toLowerCase() === "rtl" ? "rtl" : "ltr";
2123
+ }
2124
+ } catch {
2125
+ }
2126
+ return "ltr";
2127
+ };
2128
+ var resolveMode = (mode, el) => {
2129
+ if (!isLogicalMode(mode)) return mode;
2130
+ const rtl = readDirection(el) === "rtl";
2131
+ if (mode === "start") return rtl ? "right" : "left";
2132
+ return rtl ? "left" : "right";
2133
+ };
2134
+
2089
2135
  // src/core/primitives/touch-scroll-guard.ts
2090
2136
  function installTouchScrollGuard(surface, isDragging) {
2091
2137
  const onTouchMove = (e) => {
@@ -2448,7 +2494,7 @@ function resolveEngineOptions(opts, extras) {
2448
2494
  }
2449
2495
  }
2450
2496
  return {
2451
- mode: opts.mode ?? "bottom",
2497
+ mode: resolveMode(opts.mode ?? "bottom", opts.element),
2452
2498
  flickVelocity: opts.flickVelocity ?? DEFAULT_FLICK_VELOCITY,
2453
2499
  dragThreshold: opts.dragThreshold ?? DEFAULT_DRAG_THRESHOLD,
2454
2500
  dragFrom: opts.dragFrom ?? (opts.handle ? "handle" : "sheet"),
@@ -2552,6 +2598,7 @@ var BottomSheetCore = class {
2552
2598
  __publicField(this, "disableDragFlag");
2553
2599
  __publicField(this, "closeOnRouteChange");
2554
2600
  __publicField(this, "maxHeight");
2601
+ __publicField(this, "maxHeightDeps");
2555
2602
  __publicField(this, "snapPointsRaw");
2556
2603
  __publicField(this, "snaps");
2557
2604
  __publicField(this, "activeId");
@@ -2559,6 +2606,7 @@ var BottomSheetCore = class {
2559
2606
  __publicField(this, "gesture");
2560
2607
  __publicField(this, "contentGesture");
2561
2608
  __publicField(this, "detachSheetGesture", null);
2609
+ __publicField(this, "detachSliderKeyboard", null);
2562
2610
  __publicField(this, "rootEl", null);
2563
2611
  __publicField(this, "destroyed", false);
2564
2612
  __publicField(this, "restClosed", false);
@@ -2610,6 +2658,7 @@ var BottomSheetCore = class {
2610
2658
  this.screenComponent = opts.scrim ?? opts.screenComponent;
2611
2659
  this.scrimParent = this.screenComponent?.parentElement ?? null;
2612
2660
  this.mode = resolved.mode;
2661
+ this.element.dataset.mode = this.mode;
2613
2662
  this.transformTemplate = buildTransformTemplate(this.mode);
2614
2663
  this.aria = new AriaSliderWriter(this.handle, this.mode);
2615
2664
  this.flickVelocity = resolved.flickVelocity;
@@ -2676,7 +2725,7 @@ var BottomSheetCore = class {
2676
2725
  auditVhUsage(this.snapPointsRaw);
2677
2726
  this.auditDuplicateSnapIds(this.snapPointsRaw);
2678
2727
  this.rootEl = this.element.closest(".bs-root");
2679
- this.maxHeight = createMaxHeightController({
2728
+ this.maxHeightDeps = {
2680
2729
  element: this.element,
2681
2730
  mode: this.mode,
2682
2731
  getMaxAxisSize: () => this.snaps.getMaxAxisSize(),
@@ -2684,7 +2733,8 @@ var BottomSheetCore = class {
2684
2733
  this.snaps.setMaxAxisSize(size);
2685
2734
  },
2686
2735
  recompute: () => this.recompute()
2687
- });
2736
+ };
2737
+ this.maxHeight = createMaxHeightController(this.maxHeightDeps);
2688
2738
  this.fitDeps = {
2689
2739
  element: this.element,
2690
2740
  scrollContainer: this.scrollContainer,
@@ -3018,6 +3068,37 @@ var BottomSheetCore = class {
3018
3068
  getDragFrom() {
3019
3069
  return this.dragFromMode;
3020
3070
  }
3071
+ setMode(mode) {
3072
+ if (this.destroyed) return;
3073
+ const next = resolveMode(mode, this.element);
3074
+ if (next === this.mode) return;
3075
+ const wasVertical = this.mode === "bottom" || this.mode === "top";
3076
+ const nowVertical = next === "bottom" || next === "top";
3077
+ this.gesture?.forceClearDragState();
3078
+ this.detachSheetGesture?.();
3079
+ this.animation.cancel();
3080
+ this.element.style.removeProperty(layoutAxis(this.mode));
3081
+ this.mode = next;
3082
+ this.element.dataset.mode = next;
3083
+ this.transformTemplate = buildTransformTemplate(next);
3084
+ this.maxHeightDeps.mode = next;
3085
+ this.fitDeps.mode = next;
3086
+ this.snaps.setMode(next);
3087
+ this.scrim.setSheetMode(next);
3088
+ if (wasVertical !== nowVertical) {
3089
+ this.aria = new AriaSliderWriter(this.handle, next);
3090
+ }
3091
+ this.detachSliderKeyboard?.();
3092
+ this.mountSliderKeyboard();
3093
+ this.mountSheetGesture();
3094
+ this.recompute();
3095
+ const active = this.snaps.findById(this.activeId);
3096
+ if (active) this.applySize(active.size);
3097
+ this.updateAriaSlider();
3098
+ }
3099
+ getMode() {
3100
+ return this.mode;
3101
+ }
3021
3102
  isTop() {
3022
3103
  return this.isTopSheet;
3023
3104
  }
@@ -3366,7 +3447,7 @@ var BottomSheetCore = class {
3366
3447
  const point = this.snapPointsRaw.find((p) => p.id === this.activeId);
3367
3448
  return point?.dragFromContent ?? this.dragFromContentDefault;
3368
3449
  }
3369
- decideContentDrag(surface, e, delta) {
3450
+ decideContentDrag(surface, e, delta, crossDelta) {
3370
3451
  if (this.destroyed) return false;
3371
3452
  if (e.pointerType === "mouse") return false;
3372
3453
  if (this.gesture?.isDragging) return false;
@@ -3374,6 +3455,8 @@ var BottomSheetCore = class {
3374
3455
  if (!isDragAllowedFrom(e.target, "sheet")) return false;
3375
3456
  const decision = decideContentGesture({
3376
3457
  delta,
3458
+ crossDelta,
3459
+ sharesScrollAxis: this.mode === "bottom" || this.mode === "top",
3377
3460
  scrollTop: surface.scrollTop,
3378
3461
  atMaxSnap: this.size >= this.getAllowedRange().max - 0.5
3379
3462
  });
@@ -3386,7 +3469,7 @@ var BottomSheetCore = class {
3386
3469
  const controller = new GestureController(
3387
3470
  this.buildGestureDeps(surface, {
3388
3471
  manageTouchAction: false,
3389
- deferStart: (e, delta) => this.decideContentDrag(surface, e, delta)
3472
+ deferStart: (e, delta, crossDelta) => this.decideContentDrag(surface, e, delta, crossDelta)
3390
3473
  })
3391
3474
  );
3392
3475
  this.contentGesture = controller;
@@ -3512,7 +3595,11 @@ var BottomSheetCore = class {
3512
3595
  );
3513
3596
  }
3514
3597
  }
3515
- this.teardowns.add(installSliderKeyboard({
3598
+ this.mountSliderKeyboard();
3599
+ this.scrim.attach();
3600
+ }
3601
+ mountSliderKeyboard() {
3602
+ const detach = installSliderKeyboard({
3516
3603
  handle: this.handle,
3517
3604
  mode: this.mode,
3518
3605
  isDestroyed: () => this.destroyed,
@@ -3521,8 +3608,12 @@ var BottomSheetCore = class {
3521
3608
  snapTo: (id) => {
3522
3609
  void this.snapTo(id);
3523
3610
  }
3524
- }));
3525
- this.scrim.attach();
3611
+ });
3612
+ this.detachSliderKeyboard = detach;
3613
+ this.teardowns.add(() => {
3614
+ this.detachSliderKeyboard?.();
3615
+ this.detachSliderKeyboard = null;
3616
+ });
3526
3617
  }
3527
3618
  settleAfterDrag(delta, velocity, kind = "touch") {
3528
3619
  const signal = this.newCycle();
package/dist/webgl.cjs CHANGED
@@ -273,6 +273,59 @@ var wrapLines = (ctx, text, maxWidth) => {
273
273
  lines.push(line);
274
274
  return lines;
275
275
  };
276
+ var isPaintedColor = (value) => !!value && value !== "transparent" && !/rgba\(\s*0,\s*0,\s*0,\s*0\s*\)/.test(value);
277
+ var roundedPath = (ctx, x, y, w, h, r) => {
278
+ const rad = Math.min(r, w / 2, h / 2);
279
+ ctx.beginPath();
280
+ if (rad <= 0) {
281
+ ctx.rect(x, y, w, h);
282
+ return;
283
+ }
284
+ ctx.moveTo(x + rad, y);
285
+ ctx.arcTo(x + w, y, x + w, y + h, rad);
286
+ ctx.arcTo(x + w, y + h, x, y + h, rad);
287
+ ctx.arcTo(x, y + h, x, y, rad);
288
+ ctx.arcTo(x, y, x + w, y, rad);
289
+ ctx.closePath();
290
+ };
291
+ var drawBox = (ctx, cs, rect, rootRect) => {
292
+ const bg = cs.backgroundColor;
293
+ const borderWidth = parseFloat(cs.borderTopWidth) || 0;
294
+ const hasBorder = borderWidth > 0 && isPaintedColor(cs.borderTopColor);
295
+ if (!isPaintedColor(bg) && !hasBorder) return false;
296
+ const x = rect.left - rootRect.left;
297
+ const y = rect.top - rootRect.top;
298
+ const radius = parseFloat(cs.borderTopLeftRadius) || 0;
299
+ if (isPaintedColor(bg)) {
300
+ roundedPath(ctx, x, y, rect.width, rect.height, radius);
301
+ ctx.fillStyle = bg;
302
+ ctx.fill();
303
+ }
304
+ if (hasBorder) {
305
+ roundedPath(ctx, x, y, rect.width, rect.height, radius);
306
+ ctx.strokeStyle = cs.borderTopColor;
307
+ ctx.lineWidth = borderWidth;
308
+ ctx.stroke();
309
+ }
310
+ return true;
311
+ };
312
+ var drawImage = (ctx, img, rootRect) => {
313
+ if (!img.complete || img.naturalWidth === 0) return false;
314
+ const rect = img.getBoundingClientRect();
315
+ if (rect.width < 1 || rect.height < 1) return false;
316
+ try {
317
+ ctx.drawImage(
318
+ img,
319
+ rect.left - rootRect.left,
320
+ rect.top - rootRect.top,
321
+ rect.width,
322
+ rect.height
323
+ );
324
+ return true;
325
+ } catch {
326
+ return false;
327
+ }
328
+ };
276
329
  var captureContent = (gl, root, dpr) => {
277
330
  const rootRect = root.getBoundingClientRect();
278
331
  const w = Math.max(1, Math.round(rootRect.width * dpr));
@@ -289,12 +342,24 @@ var captureContent = (gl, root, dpr) => {
289
342
  let painted = 0;
290
343
  while (walker.nextNode()) {
291
344
  const el = walker.currentNode;
345
+ if (el.tagName === "IMG") {
346
+ if (drawImage(ctx, el, rootRect)) {
347
+ painted++;
348
+ hiddenNodes.push(el);
349
+ }
350
+ continue;
351
+ }
292
352
  if (!isRenderable(el)) continue;
293
- const text = directText(el);
294
- if (!text) continue;
295
353
  const rect = el.getBoundingClientRect();
296
354
  if (rect.width < 1 || rect.height < 1) continue;
297
355
  const cs = getComputedStyle(el);
356
+ const boxed = drawBox(ctx, cs, rect, rootRect);
357
+ if (boxed) {
358
+ painted++;
359
+ hiddenNodes.push(el);
360
+ }
361
+ const text = directText(el);
362
+ if (!text) continue;
298
363
  ctx.font = `${cs.fontStyle} ${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`;
299
364
  ctx.fillStyle = cs.color;
300
365
  ctx.textBaseline = "top";
@@ -321,7 +386,7 @@ var captureContent = (gl, root, dpr) => {
321
386
  });
322
387
  if (lines.length) {
323
388
  painted++;
324
- hiddenNodes.push(el);
389
+ if (!boxed) hiddenNodes.push(el);
325
390
  }
326
391
  }
327
392
  if (!painted) return null;
@@ -329,14 +394,19 @@ var captureContent = (gl, root, dpr) => {
329
394
  if (!texture) return null;
330
395
  gl.bindTexture(gl.TEXTURE_2D, texture);
331
396
  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
332
- gl.texImage2D(
333
- gl.TEXTURE_2D,
334
- 0,
335
- gl.RGBA,
336
- gl.RGBA,
337
- gl.UNSIGNED_BYTE,
338
- surface
339
- );
397
+ try {
398
+ gl.texImage2D(
399
+ gl.TEXTURE_2D,
400
+ 0,
401
+ gl.RGBA,
402
+ gl.RGBA,
403
+ gl.UNSIGNED_BYTE,
404
+ surface
405
+ );
406
+ } catch {
407
+ gl.deleteTexture(texture);
408
+ return null;
409
+ }
340
410
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
341
411
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
342
412
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
@@ -344,10 +414,30 @@ var captureContent = (gl, root, dpr) => {
344
414
  return { texture, width: w, height: h, hiddenNodes };
345
415
  };
346
416
  var hideCapturedText = (nodes) => {
347
- const restore = nodes.map((el) => ({ el, prev: el.style.color }));
348
- for (const { el } of restore) el.style.color = "transparent";
417
+ const restore = nodes.map((el) => ({
418
+ el,
419
+ color: el.style.color,
420
+ background: el.style.background,
421
+ borderColor: el.style.borderColor,
422
+ opacity: el.style.opacity,
423
+ isImage: el.tagName === "IMG"
424
+ }));
425
+ for (const entry of restore) {
426
+ if (entry.isImage) {
427
+ entry.el.style.opacity = "0";
428
+ continue;
429
+ }
430
+ entry.el.style.color = "transparent";
431
+ entry.el.style.background = "transparent";
432
+ entry.el.style.borderColor = "transparent";
433
+ }
349
434
  return () => {
350
- for (const { el, prev } of restore) el.style.color = prev;
435
+ for (const entry of restore) {
436
+ entry.el.style.color = entry.color;
437
+ entry.el.style.background = entry.background;
438
+ entry.el.style.borderColor = entry.borderColor;
439
+ entry.el.style.opacity = entry.opacity;
440
+ }
351
441
  };
352
442
  };
353
443
 
package/dist/webgl.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { f as EngineFeature } from './BottomSheetCore-Cp7dWy91.cjs';
1
+ import { f as EngineFeature } from './BottomSheetCore-VPJZcKcg.cjs';
2
2
  import './transform-jVfAikE9.cjs';
3
3
 
4
4
  type WebGLRendererOptions = {
package/dist/webgl.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { f as EngineFeature } from './BottomSheetCore-DJYwWOqt.js';
1
+ import { f as EngineFeature } from './BottomSheetCore-Cgn8b_6A.js';
2
2
  import './transform-jVfAikE9.js';
3
3
 
4
4
  type WebGLRendererOptions = {