@tremolo-ui/react 0.3.0 → 0.4.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.
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@ import clsx from "clsx";
2
2
  import React, { createContext, createRef, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useInsertionEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
  import { clamp, decimalPart, isBlackKey, isWhiteKey, normalizeValue, noteKey, noteKeys, radian, rawValue, stepValue, styleHelper, toFixed, xor } from "@tremolo-ui/functions";
5
+ import { NOT_SUPPORTED, PERMISSION_DENIED, createDrag, createMIDIAccess, createMIDIInput, createMIDIMessage, createWheel } from "@tremolo-ui/dom";
5
6
  import { createStore, useStore } from "zustand";
6
- import { NOT_SUPPORTED, PERMISSION_DENIED, createMIDIAccess, createMIDIInput, createMIDIMessage } from "@tremolo-ui/dom";
7
7
  //#region src/components/AnimationCanvas/canvas.ts
8
8
  const drawingState = [
9
9
  "strokeStyle",
@@ -155,110 +155,55 @@ function useCallbackRef(callback, deps = []) {
155
155
  return useCallback((...args) => callbackRef.current?.(...args), deps);
156
156
  }
157
157
  //#endregion
158
- //#region src/hooks/useEventListener.ts
159
- function useEventListener(target, event, handler, options) {
160
- const listener = useCallbackRef(handler);
158
+ //#region src/hooks/useDrag.ts
159
+ /**
160
+ * Track a pointer drag on an element.
161
+ *
162
+ * @returns a ref callback to attach to the element being dragged
163
+ */
164
+ function useDrag({ threshold = 1, cursor, onDrag, onDragStart, onDragEnd }) {
165
+ const dragHandler = useCallbackRef(onDrag);
166
+ const dragStartHandler = useCallbackRef(onDragStart);
167
+ const dragEndHandler = useCallbackRef(onDragEnd);
168
+ const [node, setNode] = useState(null);
161
169
  useEffect(() => {
162
- const node = typeof target === "function" ? target() : target ?? document;
163
170
  if (!node) return;
164
- node.addEventListener(event, listener, options);
165
- return () => {
166
- node.removeEventListener(event, listener, options);
167
- };
171
+ const instance = createDrag(node, {
172
+ threshold,
173
+ cursor,
174
+ onDragStart: () => dragStartHandler(),
175
+ onDrag: ({ x, y, deltaX, deltaY }) => dragHandler(x, y, deltaX, deltaY),
176
+ onDragEnd: () => dragEndHandler()
177
+ });
178
+ return () => instance.destroy();
168
179
  }, [
169
- event,
170
- target,
171
- options,
172
- listener
180
+ node,
181
+ threshold,
182
+ cursor,
183
+ dragHandler,
184
+ dragStartHandler,
185
+ dragEndHandler
173
186
  ]);
174
- return () => {
175
- (typeof target === "function" ? target() : target ?? document)?.removeEventListener(event, listener, options);
176
- };
187
+ return setNode;
177
188
  }
178
189
  //#endregion
179
- //#region src/hooks/useRefCallbackEvent.ts
180
- function useRefCallbackEvent(event, handler, options, deps = []) {
181
- return useMemo(() => {
182
- let cleanup;
183
- return (node) => {
184
- if (!node) {
185
- cleanup?.();
186
- return;
187
- }
188
- node.addEventListener(event, handler, options);
189
- cleanup = () => {
190
- node.removeEventListener(event, handler, options);
191
- };
192
- };
193
- }, deps);
194
- }
195
- //#endregion
196
- //#region src/hooks/useDrag.ts
190
+ //#region src/hooks/useWheel.ts
197
191
  /**
198
- * @returns [refCallback, pointerDownHandler]
192
+ * Listen to wheel events on an element.
193
+ *
194
+ * The listener is not passive, so the handler may call `preventDefault()`.
195
+ *
196
+ * @returns a ref callback to attach to the element
199
197
  */
200
- function useDrag({ threshold: _threshold = 1, onDrag, onDragStart, onDragEnd }) {
201
- const dragOffsetX = useRef(void 0);
202
- const dragOffsetY = useRef(void 0);
203
- const dragStartX = useRef(0);
204
- const dragStartY = useRef(0);
205
- const threshold = Math.max(_threshold, 1);
206
- const handleDrag = useCallback((event, first = false) => {
207
- const isTouch = event instanceof TouchEvent;
208
- if (isTouch && event.cancelable) event.preventDefault();
209
- const screenX = isTouch ? event.touches[0].screenX : event.screenX;
210
- const screenY = isTouch ? event.touches[0].screenY : event.screenY;
211
- let deltaX = 0;
212
- let deltaY = 0;
213
- if (first) {
214
- dragStartX.current = screenX;
215
- dragStartY.current = screenY;
216
- }
217
- if (dragOffsetX.current) {
218
- deltaX = screenX - dragOffsetX.current;
219
- dragOffsetX.current = screenX;
220
- }
221
- if (dragOffsetY.current) {
222
- deltaY = screenY - dragOffsetY.current;
223
- dragOffsetY.current = screenY;
224
- }
225
- if (Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold) return;
226
- onDrag?.(screenX - dragStartX.current, screenY - dragStartY.current, deltaX, deltaY);
227
- }, [threshold, onDrag]);
228
- const pointerDownHandler = useCallback((event) => {
229
- dragOffsetX.current = event.screenX;
230
- dragOffsetY.current = event.screenY;
231
- handleDrag(event, true);
232
- onDragStart?.();
233
- }, [handleDrag, onDragStart]);
234
- const refHandler = useRefCallbackEvent("touchmove", handleDrag, { passive: false }, [onDrag]);
235
- useEventListener(globalThis.window, "mousemove", handleDrag);
236
- useEventListener(globalThis.window, "pointerup", () => {
237
- dragOffsetX.current = void 0;
238
- dragOffsetY.current = void 0;
239
- onDragEnd?.();
240
- });
241
- return [refHandler, pointerDownHandler];
242
- }
243
- //#endregion
244
- //#region src/components/DragObserver/index.tsx
245
- function DragObserver(props) {
246
- const { as: Component = "div", threshold = 1, onDrag, onDragStart, onDragEnd, children, onPointerDown, ...attributes } = props;
247
- const [refCallback, pointerDownHandler] = useDrag({
248
- threshold,
249
- onDrag,
250
- onDragStart,
251
- onDragEnd
252
- });
253
- return /* @__PURE__ */ jsx(Component, {
254
- ref: refCallback,
255
- onPointerDown: (e) => {
256
- pointerDownHandler(e);
257
- onPointerDown?.(e);
258
- },
259
- ...attributes,
260
- children
261
- });
198
+ function useWheel(onWheel) {
199
+ const wheelHandler = useCallbackRef(onWheel);
200
+ const [node, setNode] = useState(null);
201
+ useEffect(() => {
202
+ if (!node) return;
203
+ const instance = createWheel(node, (event) => wheelHandler(event));
204
+ return () => instance.destroy();
205
+ }, [node, wheelHandler]);
206
+ return setNode;
262
207
  }
263
208
  //#endregion
264
209
  //#region src/components/_util/index.ts
@@ -268,22 +213,6 @@ function addUserSelectNone() {
268
213
  function removeUserSelectNone() {
269
214
  window.document.body.classList.remove("tremolo-user-select-none");
270
215
  }
271
- const cursorStyles = {
272
- grabbing: "tremolo-cursor-grabbing",
273
- grab: "tremolo-cursor-grab",
274
- pointer: "tremolo-cursor-pointer",
275
- move: "tremolo-cursor-move",
276
- none: "tremolo-cursor-none"
277
- };
278
- function setCursorStyle(type) {
279
- resetCursorStyle();
280
- window.document.body.classList.add(cursorStyles[type]);
281
- }
282
- function resetCursorStyle() {
283
- Object.values(cursorStyles).forEach((s) => {
284
- window.document.body.classList.remove(s);
285
- });
286
- }
287
216
  function calcDrawingState({ value, min, max, skew, startValue, angleRange }) {
288
217
  const p = normalizeValue(value, min, max, skew);
289
218
  const s = normalizeValue(startValue, min, max, skew);
@@ -493,32 +422,26 @@ const Knob = {
493
422
  readonly,
494
423
  updateValueByEvent
495
424
  ]);
496
- const [touchMoveRefCallback, pointerDownHandler] = useDrag({
425
+ const dragRefCallback = useDrag({
426
+ cursor: readonly ? void 0 : externalStyles.cursor,
497
427
  onDrag,
498
428
  onDragStart: () => {
499
429
  setDragging(true);
500
430
  valueRef.current = normalizeValue(value, min, max, skew);
501
431
  if (externalStyles.userSelectNone) addUserSelectNone();
502
- if (externalStyles.cursor) setCursorStyle(externalStyles.cursor);
503
432
  },
504
433
  onDragEnd: () => {
505
434
  setDragging(false);
506
435
  if (externalStyles.userSelectNone) removeUserSelectNone();
507
- if (externalStyles.cursor) resetCursorStyle();
508
436
  }
509
437
  });
510
- const wheelRefCallback = useRefCallbackEvent("wheel", (event) => {
438
+ const wheelRefCallback = useWheel((event) => {
511
439
  if (!wheel || readonly) return;
512
440
  event.preventDefault();
513
441
  if (!onChange || event.deltaY == 0) return;
514
442
  const x = Math.sign(event.deltaY) * -wheel[1];
515
443
  onChange(updateValueByEvent(wheel[0], x));
516
- }, { passive: false }, [
517
- wheel,
518
- onChange,
519
- readonly,
520
- updateValueByEvent
521
- ]);
444
+ });
522
445
  useImperativeHandle(forwardedRef, () => {
523
446
  return {
524
447
  focus() {
@@ -541,7 +464,7 @@ const Knob = {
541
464
  ref: (elm) => {
542
465
  elmRef.current = elm;
543
466
  wheelRefCallback(elm);
544
- touchMoveRefCallback(elm);
467
+ dragRefCallback(elm);
545
468
  },
546
469
  className: clsx("tremolo-knob", className),
547
470
  tabIndex: 0,
@@ -557,10 +480,7 @@ const Knob = {
557
480
  height: size,
558
481
  ...style
559
482
  },
560
- onPointerDown: (event) => {
561
- pointerDownHandler(event);
562
- onPointerDown?.(event);
563
- },
483
+ onPointerDown,
564
484
  onDoubleClick: (event) => {
565
485
  if (enableDoubleClickDefault && onChange) onChange(defaultValue);
566
486
  onDoubleClick?.(event);
@@ -697,6 +617,27 @@ function useNumberInputContext(selector) {
697
617
  return useStore(store, selector);
698
618
  }
699
619
  //#endregion
620
+ //#region src/hooks/useEventListener.ts
621
+ function useEventListener(target, event, handler, options) {
622
+ const listener = useCallbackRef(handler);
623
+ useEffect(() => {
624
+ const node = typeof target === "function" ? target() : target ?? document;
625
+ if (!node) return;
626
+ node.addEventListener(event, listener, options);
627
+ return () => {
628
+ node.removeEventListener(event, listener, options);
629
+ };
630
+ }, [
631
+ event,
632
+ target,
633
+ options,
634
+ listener
635
+ ]);
636
+ return () => {
637
+ (typeof target === "function" ? target() : target ?? document)?.removeEventListener(event, listener, options);
638
+ };
639
+ }
640
+ //#endregion
700
641
  //#region src/hooks/useInterval.ts
701
642
  function useInterval(callback, delay) {
702
643
  const savedCallback = useRef(callback);
@@ -842,19 +783,14 @@ const InternalInput = forwardRef(({ disabled, readonly, selectWithFocus, blurOnE
842
783
  onChange,
843
784
  updateValueByEvent
844
785
  ]);
845
- const wheelRefCallback = useRefCallbackEvent("wheel", (event) => {
786
+ const wheelRefCallback = useWheel((event) => {
846
787
  if (!wheel || readonly) return;
847
788
  event.preventDefault();
848
789
  if (!onChange || event.deltaY == 0) return;
849
790
  const x = Math.sign(event.deltaY) * -wheel[1];
850
791
  const parsed = parseValue(String(updateValueByEvent(wheel[0], x)));
851
792
  onChange?.(parsed.rawValue, parsed.formatValue);
852
- }, { passive: false }, [
853
- wheel,
854
- readonly,
855
- onChange,
856
- updateValueByEvent
857
- ]);
793
+ });
858
794
  useImperativeHandle(ref, () => {
859
795
  return {
860
796
  focus() {
@@ -972,6 +908,23 @@ const NumberInput = {
972
908
  DecrementStepper
973
909
  };
974
910
  //#endregion
911
+ //#region src/hooks/useRefCallbackEvent.ts
912
+ function useRefCallbackEvent(event, handler, options, deps = []) {
913
+ return useMemo(() => {
914
+ let cleanup;
915
+ return (node) => {
916
+ if (!node) {
917
+ cleanup?.();
918
+ return;
919
+ }
920
+ node.addEventListener(event, handler, options);
921
+ cleanup = () => {
922
+ node.removeEventListener(event, handler, options);
923
+ };
924
+ };
925
+ }, deps);
926
+ }
927
+ //#endregion
975
928
  //#region src/hooks/usePianoDrag.ts
976
929
  /**
977
930
  * Internal
@@ -1428,42 +1381,57 @@ function Container({ className, children, ...props }) {
1428
1381
  }
1429
1382
  //#endregion
1430
1383
  //#region src/hooks/useDragWithElement.ts
1431
- function useDragWithElement({ baseElementRef, onDrag, onDragStart, onDragEnd }) {
1384
+ /**
1385
+ * Track a pointer drag, reporting the position normalized against
1386
+ * the bounding rect of `baseElementRef`.
1387
+ *
1388
+ * @returns a ref callback for the element that starts the drag, and whether a drag is in progress
1389
+ */
1390
+ function useDragWithElement({ baseElementRef, updateOnPointerDown = false, cursor, onDrag, onDragStart, onDragEnd }) {
1432
1391
  const [dragging, setDragging] = useState(false);
1433
1392
  const normalizedX = useRef(0);
1434
1393
  const normalizedY = useRef(0);
1435
- const handleDrag = useCallback((event) => {
1436
- if (!baseElementRef.current || !dragging) return;
1437
- const isTouch = event instanceof TouchEvent;
1438
- if (isTouch && event.cancelable) event.preventDefault();
1439
- const { left, top, right, bottom } = baseElementRef.current.getBoundingClientRect();
1440
- const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
1441
- const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
1442
- const nx = normalizeValue(mouseX, left, right);
1443
- const ny = normalizeValue(mouseY, top, bottom);
1444
- normalizedX.current = nx;
1445
- normalizedY.current = ny;
1446
- onDrag(nx, ny);
1394
+ const dragHandler = useCallbackRef(onDrag);
1395
+ const dragStartHandler = useCallbackRef(onDragStart);
1396
+ const dragEndHandler = useCallbackRef(onDragEnd);
1397
+ const update = useCallback((clientX, clientY) => {
1398
+ const base = baseElementRef.current;
1399
+ if (!base) return false;
1400
+ const { left, top, right, bottom } = base.getBoundingClientRect();
1401
+ normalizedX.current = normalizeValue(clientX, left, right);
1402
+ normalizedY.current = normalizeValue(clientY, top, bottom);
1403
+ return true;
1404
+ }, [baseElementRef]);
1405
+ const [node, setNode] = useState(null);
1406
+ useEffect(() => {
1407
+ if (!node) return;
1408
+ const instance = createDrag(node, {
1409
+ cursor,
1410
+ onDragStart: ({ clientX, clientY }) => {
1411
+ setDragging(true);
1412
+ if (update(clientX, clientY) && updateOnPointerDown) dragHandler(normalizedX.current, normalizedY.current);
1413
+ dragStartHandler(normalizedX.current, normalizedY.current);
1414
+ },
1415
+ onDrag: ({ clientX, clientY }) => {
1416
+ if (update(clientX, clientY)) dragHandler(normalizedX.current, normalizedY.current);
1417
+ },
1418
+ onDragEnd: () => {
1419
+ setDragging(false);
1420
+ dragEndHandler(normalizedX.current, normalizedY.current);
1421
+ }
1422
+ });
1423
+ return () => instance.destroy();
1447
1424
  }, [
1448
- onDrag,
1449
- baseElementRef,
1450
- dragging
1425
+ node,
1426
+ update,
1427
+ updateOnPointerDown,
1428
+ cursor,
1429
+ dragHandler,
1430
+ dragStartHandler,
1431
+ dragEndHandler
1451
1432
  ]);
1452
- const refHandler = useRefCallbackEvent("touchmove", handleDrag, { passive: false }, [onDrag]);
1453
- const pointerDownHandler = useCallback((event) => {
1454
- setDragging(true);
1455
- handleDrag(event);
1456
- onDragStart?.(normalizedX.current, normalizedY.current);
1457
- }, [handleDrag, onDragStart]);
1458
- useEventListener(globalThis.window, "pointermove", handleDrag);
1459
- useEventListener(globalThis.window, "pointerup", () => {
1460
- if (!dragging) return;
1461
- setDragging(false);
1462
- onDragEnd?.(normalizedX.current, normalizedY.current);
1463
- });
1464
1433
  return {
1465
- refHandler,
1466
- pointerDownHandler,
1434
+ refCallback: setNode,
1467
1435
  dragging
1468
1436
  };
1469
1437
  }
@@ -1481,8 +1449,9 @@ function Point({ value, min, max, size, width = 16, height = 16, color, disabled
1481
1449
  const externalStyles = usePointsEditorContext((s) => s.externalStyles);
1482
1450
  const __disabled = usePointsEditorContext((s) => s.disabled);
1483
1451
  const __readonly = usePointsEditorContext((s) => s.readonly);
1484
- const { refHandler: touchMoveRefCallback, pointerDownHandler, dragging } = useDragWithElement({
1452
+ const { refCallback: dragRefCallback, dragging } = useDragWithElement({
1485
1453
  baseElementRef: containerElementRef,
1454
+ cursor: readonly ? void 0 : externalStyles.cursor,
1486
1455
  onDrag: (x, y) => {
1487
1456
  if (readonly) return;
1488
1457
  onChange?.(clampPoint({
@@ -1493,7 +1462,6 @@ function Point({ value, min, max, size, width = 16, height = 16, color, disabled
1493
1462
  onDragStart: (x, y) => {
1494
1463
  if (readonly) return;
1495
1464
  if (externalStyles.userSelectNone) addUserSelectNone();
1496
- if (externalStyles.cursor) setCursorStyle(externalStyles.cursor);
1497
1465
  onDragStart?.(clampPoint({
1498
1466
  x,
1499
1467
  y
@@ -1502,7 +1470,6 @@ function Point({ value, min, max, size, width = 16, height = 16, color, disabled
1502
1470
  onDragEnd: (x, y) => {
1503
1471
  if (readonly) return;
1504
1472
  if (externalStyles.userSelectNone) removeUserSelectNone();
1505
- if (externalStyles.cursor) resetCursorStyle();
1506
1473
  onDragEnd?.(clampPoint({
1507
1474
  x,
1508
1475
  y
@@ -1511,9 +1478,7 @@ function Point({ value, min, max, size, width = 16, height = 16, color, disabled
1511
1478
  });
1512
1479
  const colors = { "--color": color };
1513
1480
  return /* @__PURE__ */ jsx("div", {
1514
- ref: (div) => {
1515
- touchMoveRefCallback(div);
1516
- },
1481
+ ref: dragRefCallback,
1517
1482
  className: clsx("tremolo-points-editor-point", className),
1518
1483
  tabIndex: 0,
1519
1484
  "aria-disabled": disabled != void 0 ? disabled : __disabled,
@@ -1527,10 +1492,7 @@ function Point({ value, min, max, size, width = 16, height = 16, color, disabled
1527
1492
  top: `${value.y * 100}%`,
1528
1493
  ...style
1529
1494
  },
1530
- onPointerDown: (event) => {
1531
- pointerDownHandler(event);
1532
- onPointerDown?.(event);
1533
- },
1495
+ onPointerDown,
1534
1496
  ...props
1535
1497
  });
1536
1498
  }
@@ -1831,24 +1793,24 @@ const Slider = {
1831
1793
  reverse,
1832
1794
  updateValueByEvent
1833
1795
  ]);
1834
- const { refHandler: touchMoveRefCallback, pointerDownHandler } = useDragWithElement({
1796
+ const { refCallback: dragRefCallback } = useDragWithElement({
1835
1797
  baseElementRef: trackElementRef,
1798
+ cursor: readonly ? void 0 : externalStyles.cursor,
1799
+ updateOnPointerDown: true,
1836
1800
  onDrag,
1837
1801
  onDragStart: (nx, ny) => {
1838
1802
  if (readonly) return;
1839
1803
  if (externalStyles.userSelectNone) addUserSelectNone();
1840
- if (externalStyles.cursor) setCursorStyle(externalStyles.cursor);
1841
1804
  thumbRef.current?.focus();
1842
1805
  onDragStart?.(clamp(stepValue(rawValue(vertical ? ny : nx, min, max, skew), step), min, max));
1843
1806
  },
1844
1807
  onDragEnd: (nx, ny) => {
1845
1808
  if (readonly) return;
1846
1809
  if (externalStyles.userSelectNone) removeUserSelectNone();
1847
- if (externalStyles.cursor) resetCursorStyle();
1848
1810
  onDragEnd?.(clamp(stepValue(rawValue(vertical ? ny : nx, min, max, skew), step), min, max));
1849
1811
  }
1850
1812
  });
1851
- const wheelRefCallback = useRefCallbackEvent("wheel", (event) => {
1813
+ const wheelRefCallback = useWheel((event) => {
1852
1814
  if (!wheel || !onChange || readonly) return;
1853
1815
  event.preventDefault();
1854
1816
  let x;
@@ -1859,13 +1821,7 @@ const Slider = {
1859
1821
  }
1860
1822
  if (vertical && reverse) x *= -1;
1861
1823
  onChange(updateValueByEvent(wheel[0], x));
1862
- }, { passive: false }, [
1863
- wheel,
1864
- vertical,
1865
- readonly,
1866
- onChange,
1867
- updateValueByEvent
1868
- ]);
1824
+ });
1869
1825
  useImperativeHandle(forwardedRef, () => {
1870
1826
  return {
1871
1827
  focus() {
@@ -1889,7 +1845,7 @@ const Slider = {
1889
1845
  className: clsx("tremolo-slider", className),
1890
1846
  ref: (div) => {
1891
1847
  wheelRefCallback(div);
1892
- touchMoveRefCallback(div);
1848
+ dragRefCallback(div);
1893
1849
  },
1894
1850
  tabIndex: -1,
1895
1851
  role: "slider",
@@ -1903,10 +1859,7 @@ const Slider = {
1903
1859
  margin: `calc(${styleHelper(thumbProps?.size ?? 22)} / 2)`,
1904
1860
  ...style
1905
1861
  },
1906
- onPointerDown: (event) => {
1907
- pointerDownHandler(event);
1908
- onPointerDown?.(event);
1909
- },
1862
+ onPointerDown,
1910
1863
  onKeyDown: (event) => {
1911
1864
  handleKeyDown(event);
1912
1865
  onKeyDown?.(event);
@@ -1981,29 +1934,6 @@ function composeRefs(...refs) {
1981
1934
  };
1982
1935
  }
1983
1936
  //#endregion
1984
- //#region src/components/WheelObserver/index.tsx
1985
- /**
1986
- * @example
1987
- * <WheelObserver
1988
- * onWheel={(event) => {
1989
- * event.preventDefault()
1990
- * console.log(event.deltaY)
1991
- * }
1992
- * >
1993
- * <div>Wheel here</div>
1994
- * </WheelObserver>
1995
- */
1996
- function WheelObserver(props) {
1997
- const { as: Component = "div", children, onWheel, ref, ...attributes } = props;
1998
- return /* @__PURE__ */ jsx(Component, {
1999
- ref: composeRefs(ref, useRefCallbackEvent("wheel", (event) => {
2000
- if (onWheel) onWheel(event);
2001
- }, { passive: false }, [onWheel])),
2002
- ...attributes,
2003
- children
2004
- });
2005
- }
2006
- //#endregion
2007
1937
  //#region src/components/XYPad/Area.tsx
2008
1938
  function Area({ width = 120, height = 120, color, children, className, style, __thumb, ...props }) {
2009
1939
  return /* @__PURE__ */ jsxs("div", {
@@ -2155,13 +2085,14 @@ const XYPad = {
2155
2085
  y,
2156
2086
  updateValueByEvent
2157
2087
  ]);
2158
- const { refHandler: touchMoveRefCallback, pointerDownHandler } = useDragWithElement({
2088
+ const { refCallback: dragRefCallback } = useDragWithElement({
2159
2089
  baseElementRef: areaElementRef,
2090
+ cursor: readonly ? void 0 : externalStyles.cursor,
2091
+ updateOnPointerDown: true,
2160
2092
  onDrag,
2161
2093
  onDragStart: (nx, ny) => {
2162
2094
  if (readonly) return;
2163
2095
  if (externalStyles.userSelectNone) addUserSelectNone();
2164
- if (externalStyles.cursor) setCursorStyle(externalStyles.cursor);
2165
2096
  thumbRef.current?.focus();
2166
2097
  const valueX = clamp(stepValue(rawValue(nx, x.min, x.max, x.skew), x.step), x.min, x.max);
2167
2098
  const valueY = clamp(stepValue(rawValue(ny, y.min, y.max, y.skew), y.step), y.min, y.max);
@@ -2170,13 +2101,12 @@ const XYPad = {
2170
2101
  onDragEnd: (nx, ny) => {
2171
2102
  if (readonly) return;
2172
2103
  if (externalStyles.userSelectNone) removeUserSelectNone();
2173
- if (externalStyles.cursor) resetCursorStyle();
2174
2104
  const valueX = clamp(stepValue(rawValue(nx, x.min, x.max, x.skew), x.step), x.min, x.max);
2175
2105
  const valueY = clamp(stepValue(rawValue(ny, y.min, y.max, y.skew), y.step), y.min, y.max);
2176
2106
  onDragEnd?.(valueX, valueY);
2177
2107
  }
2178
2108
  });
2179
- const wheelRefCallback = useRefCallbackEvent("wheel", (event) => {
2109
+ const wheelRefCallback = useWheel((event) => {
2180
2110
  if (!onChange || readonly) return;
2181
2111
  const target = event.shiftKey ? x : y;
2182
2112
  if (!target.wheel) return;
@@ -2187,13 +2117,7 @@ const XYPad = {
2187
2117
  const newValue = updateValueByEvent(target.wheel[0], target, delta);
2188
2118
  if (event.shiftKey) onChange(newValue, y.value);
2189
2119
  else onChange(x.value, newValue);
2190
- }, { passive: false }, [
2191
- x,
2192
- y,
2193
- onChange,
2194
- readonly,
2195
- updateValueByEvent
2196
- ]);
2120
+ });
2197
2121
  useImperativeHandle(forwardedRef, () => {
2198
2122
  return {
2199
2123
  focus() {
@@ -2207,7 +2131,7 @@ const XYPad = {
2207
2131
  }, []);
2208
2132
  return /* @__PURE__ */ jsx("div", {
2209
2133
  className: clsx("tremolo-xy-pad", className),
2210
- ref: composeRefs(rootRef, wheelRefCallback, touchMoveRefCallback),
2134
+ ref: composeRefs(rootRef, wheelRefCallback, dragRefCallback),
2211
2135
  tabIndex: -1,
2212
2136
  "aria-disabled": disabled,
2213
2137
  "aria-readonly": readonly,
@@ -2217,10 +2141,7 @@ const XYPad = {
2217
2141
  WebkitTapHighlightColor: "transparent",
2218
2142
  ...style
2219
2143
  },
2220
- onPointerDown: (event) => {
2221
- pointerDownHandler(event);
2222
- onPointerDown?.(event);
2223
- },
2144
+ onPointerDown,
2224
2145
  onKeyDown: (event) => {
2225
2146
  handleKeyDown(event);
2226
2147
  onKeyDown?.(event);
@@ -2321,6 +2242,6 @@ function useMIDIMessage(midiAccess, onMIDIMessage) {
2321
2242
  }, [midiAccess, onMIDIMessage]);
2322
2243
  }
2323
2244
  //#endregion
2324
- export { AnimationCanvas, DragObserver, Knob, NOT_SUPPORTED, NumberInput, PERMISSION_DENIED, Piano, PointsEditor, SHORTCUTS, Slider, WheelObserver, XYPad, clampPoint, getNoteRangeArray, useAnimationFrame, useDrag, useDragWithElement, useEventListener, useInterval, useLongPress, useMIDIAccess, useMIDIInput, useMIDIMessage, useSliderContext };
2245
+ export { AnimationCanvas, Knob, NOT_SUPPORTED, NumberInput, PERMISSION_DENIED, Piano, PointsEditor, SHORTCUTS, Slider, XYPad, clampPoint, getNoteRangeArray, useAnimationFrame, useDrag, useDragWithElement, useEventListener, useInterval, useLongPress, useMIDIAccess, useMIDIInput, useMIDIMessage, useSliderContext, useWheel };
2325
2246
 
2326
2247
  //# sourceMappingURL=index.js.map