@tremolo-ui/react 0.0.12 → 0.1.0-alpha.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 (63) hide show
  1. package/dist/cjs/index.js +320 -233
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/Knob/index.d.ts +12 -0
  4. package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
  5. package/dist/cjs/types/components/Piano/KeyLabel.d.ts +1 -3
  6. package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +1 -1
  7. package/dist/cjs/types/components/Piano/context.d.ts +24 -0
  8. package/dist/cjs/types/components/Piano/context.d.ts.map +1 -0
  9. package/dist/cjs/types/components/Piano/index.d.ts +9 -9
  10. package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
  11. package/dist/cjs/types/components/Piano/key.d.ts +10 -19
  12. package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
  13. package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
  14. package/dist/cjs/types/components/XYPad/index.d.ts.map +1 -1
  15. package/dist/cjs/types/hooks/useDrag.d.ts.map +1 -1
  16. package/dist/cjs/types/hooks/useDragWithElement.d.ts +16 -0
  17. package/dist/cjs/types/hooks/useDragWithElement.d.ts.map +1 -0
  18. package/dist/cjs/types/index.d.ts +1 -0
  19. package/dist/cjs/types/index.d.ts.map +1 -1
  20. package/dist/esm/index.js +319 -234
  21. package/dist/esm/index.js.map +1 -1
  22. package/dist/esm/types/components/Knob/index.d.ts +12 -0
  23. package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
  24. package/dist/esm/types/components/Piano/KeyLabel.d.ts +1 -3
  25. package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +1 -1
  26. package/dist/esm/types/components/Piano/context.d.ts +24 -0
  27. package/dist/esm/types/components/Piano/context.d.ts.map +1 -0
  28. package/dist/esm/types/components/Piano/index.d.ts +9 -9
  29. package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
  30. package/dist/esm/types/components/Piano/key.d.ts +10 -19
  31. package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
  32. package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
  33. package/dist/esm/types/components/XYPad/index.d.ts.map +1 -1
  34. package/dist/esm/types/hooks/useDrag.d.ts.map +1 -1
  35. package/dist/esm/types/hooks/useDragWithElement.d.ts +16 -0
  36. package/dist/esm/types/hooks/useDragWithElement.d.ts.map +1 -0
  37. package/dist/esm/types/index.d.ts +1 -0
  38. package/dist/esm/types/index.d.ts.map +1 -1
  39. package/dist/styles/index.css +2 -0
  40. package/package.json +2 -1
  41. package/src/components/AnimationCanvas/index.tsx +3 -1
  42. package/src/components/Knob/index.tsx +14 -0
  43. package/src/components/Piano/KeyLabel.tsx +9 -5
  44. package/src/components/Piano/context.tsx +108 -0
  45. package/src/components/Piano/index.css +2 -0
  46. package/src/components/Piano/index.tsx +186 -114
  47. package/src/components/Piano/key.tsx +215 -0
  48. package/src/components/Slider/index.tsx +40 -52
  49. package/src/components/XYPad/index.tsx +64 -54
  50. package/src/hooks/useDrag.ts +6 -7
  51. package/src/hooks/useDragWithElement.ts +76 -0
  52. package/src/index.ts +1 -0
  53. package/dist/cjs/types/components/Piano/BlackKey.d.ts +0 -5
  54. package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +0 -1
  55. package/dist/cjs/types/components/Piano/WhiteKey.d.ts +0 -7
  56. package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +0 -1
  57. package/dist/esm/types/components/Piano/BlackKey.d.ts +0 -5
  58. package/dist/esm/types/components/Piano/BlackKey.d.ts.map +0 -1
  59. package/dist/esm/types/components/Piano/WhiteKey.d.ts +0 -7
  60. package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +0 -1
  61. package/src/components/Piano/BlackKey.tsx +0 -132
  62. package/src/components/Piano/WhiteKey.tsx +0 -134
  63. package/src/components/Piano/key.ts +0 -51
package/dist/cjs/index.js CHANGED
@@ -110,7 +110,9 @@ function AnimationCanvas(_a) {
110
110
  memoCanvas.width = w * dpr;
111
111
  memoCanvas.height = h * dpr;
112
112
  memoContext.scale(1 / dpr, 1 / dpr);
113
- memoContext.drawImage(context.canvas, 0, 0);
113
+ if (canvas.width > 0 && canvas.height > 0) {
114
+ memoContext.drawImage(canvas, 0, 0);
115
+ }
114
116
  }
115
117
  setDprConfig(canvas, context, w, h, dpr);
116
118
  widthRef.current = w;
@@ -321,6 +323,13 @@ function isWhiteKey(note) {
321
323
  mod(n, 12) == 9 ||
322
324
  mod(n, 12) == 11);
323
325
  }
326
+ /**
327
+ * @param note noteNumber: 0 ~ 127 or noteName e.g. 'C3'
328
+ * @category MIDI
329
+ */
330
+ function isBlackKey(note) {
331
+ return !isWhiteKey(note);
332
+ }
324
333
 
325
334
  /**
326
335
  * This hook is user-land implementation of the experimental `useEffectEvent` hook.
@@ -401,8 +410,7 @@ function useDrag({ threshold = 1, onDrag, onDragStart, onDragEnd, }) {
401
410
  }
402
411
  if (Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold)
403
412
  return;
404
- if (onDrag)
405
- onDrag(screenX - dragStartX.current, screenY - dragStartY.current, deltaX, deltaY);
413
+ onDrag(screenX - dragStartX.current, screenY - dragStartY.current, deltaX, deltaY);
406
414
  }, [threshold, onDrag]);
407
415
  const refHandler = useRefCallbackEvent('touchmove', handleDrag, { passive: false }, [onDrag]);
408
416
  const pointerDownHandler = React.useCallback((event) => {
@@ -669,7 +677,7 @@ const Knob = React.forwardRef((_a, ref) => {
669
677
  elmRef.current = div;
670
678
  wheelRefCallback(div);
671
679
  touchMoveRefCallback(div);
672
- }, width: size, height: size, tabIndex: 0, "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled, "aria-readonly": readonly, onPointerDown: (event) => {
680
+ }, width: size, height: size, tabIndex: 0, role: "slider", "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled, "aria-readonly": readonly, onPointerDown: (event) => {
673
681
  pointerDownHandler(event);
674
682
  onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
675
683
  }, onDoubleClick: (event) => {
@@ -1059,21 +1067,73 @@ const NumberInput = React.forwardRef((_a, ref) => {
1059
1067
  tabIndex: 0, style: Object.assign({}, colors), "data-stepper": !!children, "data-variant": variant, children: [jsxRuntime.jsx(InternalInput, Object.assign({ ref: ref, readonly: readonly, disabled: disabled, selectWithFocus: selectWithFocus, blurOnEnter: blurOnEnter, clampValueOnBlur: clampValueOnBlur, wheel: wheel, keyboard: keyboard, className: className, onChange: onChange, onFocus: onFocus, onBlur: onBlur }, props)), children] }) }));
1060
1068
  });
1061
1069
 
1070
+ /**
1071
+ * @returns [refCallback, pointerDownHandler]
1072
+ */
1073
+ function useDragWithElement({ baseElementRef, onDrag, onDragStart, onDragEnd, }) {
1074
+ const dragged = React.useRef(false);
1075
+ const normalizedX = React.useRef(0);
1076
+ const normalizedY = React.useRef(0);
1077
+ const handleDrag = React.useCallback((event) => {
1078
+ if (!baseElementRef.current || !dragged.current) {
1079
+ return;
1080
+ }
1081
+ const isTouch = event instanceof TouchEvent;
1082
+ if (isTouch && event.cancelable)
1083
+ event.preventDefault();
1084
+ const { left, top, right, bottom } = baseElementRef.current.getBoundingClientRect();
1085
+ const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
1086
+ const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
1087
+ const nx = normalizeValue(mouseX, left, right);
1088
+ const ny = normalizeValue(mouseY, top, bottom);
1089
+ normalizedX.current = nx;
1090
+ normalizedY.current = ny;
1091
+ onDrag(nx, ny);
1092
+ }, [onDrag, baseElementRef]);
1093
+ const refHandler = useRefCallbackEvent('touchmove', handleDrag, { passive: false }, [onDrag]);
1094
+ const pointerDownHandler = React.useCallback((event) => {
1095
+ dragged.current = true;
1096
+ handleDrag(event);
1097
+ onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(normalizedX.current, normalizedY.current);
1098
+ }, [handleDrag, onDragStart]);
1099
+ useEventListener(globalThis.window, 'pointermove', handleDrag);
1100
+ useEventListener(globalThis.window, 'pointerup', () => {
1101
+ if (!dragged.current)
1102
+ return;
1103
+ dragged.current = false;
1104
+ onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(normalizedX.current, normalizedY.current);
1105
+ });
1106
+ return [refHandler, pointerDownHandler];
1107
+ }
1108
+
1062
1109
  /** @category Piano */
1063
1110
  function KeyLabel(_a) {
1064
- var { label, className, wrapperClassName, wrapperStyle, __note, __index, __label } = _a, props = __rest(_a, ["label", "className", "wrapperClassName", "wrapperStyle", "__note", "__index", "__label"]);
1111
+ var { label, className, wrapperClassName, wrapperStyle, __note, __label } = _a, props = __rest(_a, ["label", "className", "wrapperClassName", "wrapperStyle", "__note", "__label"]);
1112
+ const noteRange = usePianoContext((s) => s.noteRange);
1113
+ const noteRangeArray = getNoteRangeArray(noteRange);
1114
+ const index = noteRangeArray.indexOf(__note);
1065
1115
  const content = label
1066
- ? label(__note, __index)
1067
- : __label && __label(__note, __index);
1116
+ ? label(__note, index)
1117
+ : __label && __label(__note, index);
1068
1118
  return ((content != undefined || content != null) && (jsxRuntime.jsx("div", { className: clsx('tremolo-piano-key-label-wrapper', wrapperClassName), style: wrapperStyle, children: jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-piano-key-label', className) }, props, { children: content })) })));
1069
1119
  }
1070
1120
 
1071
1121
  /** @category Piano */
1072
1122
  const defaultWhiteKeyWidth = 40;
1073
1123
  /** @category Piano */
1074
- const WhiteKey = React.forwardRef((_a, ref) => {
1075
- var { width = defaultWhiteKeyWidth, height = '100%', bg, color, activeBg, activeColor, className, style, children, __glissando, __position, __note, __disabled, __index, __fill, __width, __onPlayNote, __onStopNote, __label, onContextMenu = (e) => e.preventDefault() } = _a, props = __rest(_a, ["width", "height", "bg", "color", "activeBg", "activeColor", "className", "style", "children", "__glissando", "__position", "__note", "__disabled", "__index", "__fill", "__width", "__onPlayNote", "__onStopNote", "__label", "onContextMenu"]);
1124
+ const defaultBlackKeyWidth = 26;
1125
+ const KeyImpl = React.forwardRef((_a, ref) => {
1126
+ var { keyType, noteNumber, width, height, bg, color, activeBg, activeColor, className, style, children, __width } = _a, props = __rest(_a, ["keyType", "noteNumber", "width", "height", "bg", "color", "activeBg", "activeColor", "className", "style", "children", "__width"]);
1076
1127
  const [played, setPlayed] = React.useState(false);
1128
+ const midiMax = usePianoContext((s) => s.midiMax);
1129
+ const fill = usePianoContext((s) => s.fill);
1130
+ // const glissando = usePianoContext(s => s.glissando)
1131
+ const onPlayNote = usePianoContext((s) => s.onPlayNote);
1132
+ const onStopNote = usePianoContext((s) => s.onStopNote);
1133
+ const label = usePianoContext((s) => s.label);
1134
+ const notePosition = usePianoContext((s) => s.notePosition);
1135
+ const position = notePosition(noteNumber);
1136
+ const disabled = noteNumber > midiMax;
1077
1137
  const colors = {
1078
1138
  '--bg': bg,
1079
1139
  '--color': color,
@@ -1083,22 +1143,22 @@ const WhiteKey = React.forwardRef((_a, ref) => {
1083
1143
  React.useImperativeHandle(ref, () => {
1084
1144
  return {
1085
1145
  play() {
1086
- if (__disabled)
1146
+ if (disabled)
1087
1147
  return;
1088
1148
  setPlayed(true);
1089
- if (__onPlayNote)
1090
- __onPlayNote(__note);
1149
+ if (onPlayNote)
1150
+ onPlayNote(noteNumber);
1091
1151
  },
1092
1152
  stop() {
1093
1153
  setPlayed(false);
1094
- if (__onStopNote)
1095
- __onStopNote(__note);
1154
+ if (onStopNote)
1155
+ onStopNote(noteNumber);
1096
1156
  },
1097
1157
  played() {
1098
1158
  return played;
1099
1159
  },
1100
1160
  };
1101
- }, [__disabled, __note, __onPlayNote, __onStopNote, played]);
1161
+ }, [disabled, noteNumber, onPlayNote, onStopNote, played]);
1102
1162
  let keyLabelProps = {};
1103
1163
  if (children != undefined) {
1104
1164
  React.Children.forEach(children, (child) => {
@@ -1115,112 +1175,82 @@ const WhiteKey = React.forwardRef((_a, ref) => {
1115
1175
  }
1116
1176
  });
1117
1177
  }
1118
- return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-white-key`, className), "aria-disabled": __disabled, "data-active": played, style: Object.assign(Object.assign(Object.assign({}, colors), { left: __position, width: __fill ? __width : (width !== null && width !== void 0 ? width : __width), height: height }), style), onPointerDown: () => {
1119
- if (__disabled)
1120
- return;
1121
- setPlayed(true);
1122
- if (__onPlayNote)
1123
- __onPlayNote(__note);
1124
- }, onPointerEnter: () => {
1125
- if (__disabled)
1126
- return;
1127
- if (__glissando) {
1128
- setPlayed(true);
1129
- if (__onPlayNote)
1130
- __onPlayNote(__note);
1131
- }
1132
- }, onPointerUp: () => {
1133
- if (__disabled)
1134
- return;
1135
- setPlayed(false);
1136
- if (__onStopNote)
1137
- __onStopNote(__note);
1138
- }, onPointerLeave: () => {
1139
- if (__disabled)
1140
- return;
1141
- if (__glissando) {
1142
- setPlayed(false);
1143
- if (__onStopNote)
1144
- __onStopNote(__note);
1145
- }
1146
- }, onContextMenu: onContextMenu }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
1178
+ return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-${keyType}-key`, className), "aria-disabled": disabled, "data-active": played, style: Object.assign(Object.assign(Object.assign({}, colors), { left: position, width: fill ? __width : width, height: height }), style) }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ label: label, __note: noteNumber }, keyLabelProps)) })));
1179
+ });
1180
+ /** @category Piano */
1181
+ const WhiteKey = React.forwardRef((_a, ref) => {
1182
+ var { width = defaultWhiteKeyWidth, height = '100%', onContextMenu = (e) => e.preventDefault() } = _a, props = __rest(_a, ["width", "height", "onContextMenu"]);
1183
+ return (jsxRuntime.jsx(KeyImpl, Object.assign({ ref: ref, keyType: "white", width: width, height: height, onContextMenu: onContextMenu }, props)));
1147
1184
  });
1148
-
1149
1185
  /** @category Piano */
1150
1186
  const BlackKey = React.forwardRef((_a, ref) => {
1151
- var { width = defaultWhiteKeyWidth * 0.65, height = '60%', bg, color, activeBg, activeColor, className, style, children, __glissando, __position, __note, __disabled, __index, __fill, __width, __onPlayNote, __onStopNote, __label, onContextMenu = (e) => e.preventDefault() } = _a, props = __rest(_a, ["width", "height", "bg", "color", "activeBg", "activeColor", "className", "style", "children", "__glissando", "__position", "__note", "__disabled", "__index", "__fill", "__width", "__onPlayNote", "__onStopNote", "__label", "onContextMenu"]);
1152
- const [played, setPlayed] = React.useState(false);
1153
- const colors = {
1154
- '--bg': bg,
1155
- '--color': color,
1156
- '--active-bg': activeBg,
1157
- '--active-color': activeColor,
1187
+ var { width = defaultBlackKeyWidth, height = '60%', onContextMenu = (e) => e.preventDefault() } = _a, props = __rest(_a, ["width", "height", "onContextMenu"]);
1188
+ return (jsxRuntime.jsx(KeyImpl, Object.assign({ ref: ref, keyType: "black", width: width, height: height, onContextMenu: onContextMenu }, props)));
1189
+ });
1190
+
1191
+ const createPianoStore = (initProps) => {
1192
+ const noteRange = (initProps === null || initProps === void 0 ? void 0 : initProps.noteRange) || { first: 0};
1193
+ const DEFAULT_PROPS = {
1194
+ noteRange: { first: 0, last: 127 },
1195
+ glissando: true,
1196
+ midiMax: 127,
1197
+ fill: false,
1198
+ label: () => undefined,
1199
+ onPlayNote: () => { },
1200
+ onStopNote: () => { },
1158
1201
  };
1159
- React.useImperativeHandle(ref, () => {
1160
- return {
1161
- play() {
1162
- if (__disabled)
1163
- return;
1164
- setPlayed(true);
1165
- if (__onPlayNote)
1166
- __onPlayNote(__note);
1167
- },
1168
- stop() {
1169
- setPlayed(false);
1170
- if (__onStopNote)
1171
- __onStopNote(__note);
1172
- },
1173
- played() {
1174
- return played;
1175
- },
1176
- };
1177
- }, [__disabled, __note, __onPlayNote, __onStopNote, played]);
1178
- let keyLabelProps = {};
1179
- if (children != undefined) {
1180
- React.Children.forEach(children, (child) => {
1181
- if (React.isValidElement(child)) {
1182
- if (child.type == KeyLabel) {
1183
- keyLabelProps = child.props;
1184
- }
1185
- else {
1186
- throw new Error('only <KeyLabel>');
1187
- }
1188
- }
1189
- else {
1190
- throw new Error('children is an invalid element.');
1191
- }
1192
- });
1202
+ return createStore()(() => (Object.assign(Object.assign(Object.assign({}, DEFAULT_PROPS), initProps), { notePosition: (note) => {
1203
+ const pitchPositions = {
1204
+ C: 0,
1205
+ 'C#': 1,
1206
+ D: 1,
1207
+ 'D#': 2,
1208
+ E: 2,
1209
+ F: 3,
1210
+ 'F#': 4,
1211
+ G: 4,
1212
+ 'G#': 5,
1213
+ A: 5,
1214
+ 'A#': 6,
1215
+ B: 6,
1216
+ };
1217
+ const whiteNoteWidth = defaultWhiteKeyWidth;
1218
+ const blackNoteWidth = defaultBlackKeyWidth;
1219
+ const padding = 1;
1220
+ const targetNoteKey = noteKey(note);
1221
+ const firstNoteKey = noteKey(noteRange.first);
1222
+ const octave = Math.floor((note - noteRange.first) / 12);
1223
+ const octaveOffset = noteKeys.indexOf(firstNoteKey) > noteKeys.indexOf(targetNoteKey) ? 1 : 0;
1224
+ const w = whiteNoteWidth + padding;
1225
+ const pos = pitchPositions[targetNoteKey] - pitchPositions[firstNoteKey];
1226
+ const blackKeyOffset = isBlackKey(note) ? blackNoteWidth / 2 : 0;
1227
+ return pos * w + (octave + octaveOffset) * 7 * w - blackKeyOffset;
1228
+ } })));
1229
+ };
1230
+ const PianoContext = React.createContext(null);
1231
+ function PianoProvider(_a) {
1232
+ var { children } = _a, props = __rest(_a, ["children"]);
1233
+ const storeRef = React.useRef(null);
1234
+ if (!storeRef.current) {
1235
+ storeRef.current = createPianoStore(props);
1193
1236
  }
1194
- return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-black-key`, className), "aria-disabled": __disabled, "data-active": played, style: Object.assign(Object.assign(Object.assign({}, colors), { left: __position, width: __fill ? __width : (width !== null && width !== void 0 ? width : __width), height: height }), style), onPointerDown: () => {
1195
- if (__disabled)
1196
- return;
1197
- setPlayed(true);
1198
- if (__onPlayNote)
1199
- __onPlayNote(__note);
1200
- }, onPointerEnter: () => {
1201
- if (__disabled)
1202
- return;
1203
- if (__glissando) {
1204
- setPlayed(true);
1205
- if (__onPlayNote)
1206
- __onPlayNote(__note);
1207
- }
1208
- }, onPointerUp: () => {
1209
- if (__disabled)
1210
- return;
1211
- setPlayed(false);
1212
- if (__onStopNote)
1213
- __onStopNote(__note);
1214
- }, onPointerLeave: () => {
1215
- if (__disabled)
1216
- return;
1217
- if (__glissando) {
1218
- setPlayed(false);
1219
- if (__onStopNote)
1220
- __onStopNote(__note);
1221
- }
1222
- }, onContextMenu: onContextMenu }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
1223
- });
1237
+ React.useEffect(() => {
1238
+ if (storeRef.current) {
1239
+ storeRef.current.setState(props);
1240
+ }
1241
+ else {
1242
+ storeRef.current = createPianoStore(props);
1243
+ }
1244
+ }, [props]);
1245
+ return (jsxRuntime.jsx(PianoContext.Provider, { value: storeRef.current, children: children }));
1246
+ }
1247
+ /** @category Piano */
1248
+ function usePianoContext(selector) {
1249
+ const store = React.useContext(PianoContext);
1250
+ if (!store)
1251
+ throw new Error('Missing PianoContext.Provider in the tree');
1252
+ return useStore(store, selector);
1253
+ }
1224
1254
 
1225
1255
  /** @category Piano */
1226
1256
  const SHORTCUTS = {
@@ -1247,66 +1277,121 @@ const SHORTCUTS = {
1247
1277
  },
1248
1278
  };
1249
1279
 
1280
+ /**
1281
+ * Piano component
1282
+ *
1283
+ * TODO:
1284
+ * - add scale highlight
1285
+ */
1286
+ /** @category Piano */
1287
+ function getNoteRangeArray(noteRange) {
1288
+ return Array.from({ length: noteRange.last - noteRange.first + 1 }, (_, i) => i + noteRange.first);
1289
+ }
1250
1290
  /**
1251
1291
  * Customizable piano component.
1252
1292
  * @category Piano
1253
1293
  */
1254
1294
  function Piano(_a) {
1255
- var { noteRange, glissando = true, midiMax = 127, keyboardShortcuts, fill = false, height = fill ? '100%' : 160, style, className, onPlayNote, onStopNote, label, children, onPointerUp, onPointerDown } = _a, props = __rest(_a, ["noteRange", "glissando", "midiMax", "keyboardShortcuts", "fill", "height", "style", "className", "onPlayNote", "onStopNote", "label", "children", "onPointerUp", "onPointerDown"]);
1295
+ var { noteRange, glissando = true, midiMax = 127, keyboardShortcuts, fill = false, height = fill ? '100%' : 160, whiteNoteWidth: _whiteNoteWidth = defaultWhiteKeyWidth, style, className, onPlayNote, onStopNote, label, children, onPointerDown } = _a, props = __rest(_a, ["noteRange", "glissando", "midiMax", "keyboardShortcuts", "fill", "height", "whiteNoteWidth", "style", "className", "onPlayNote", "onStopNote", "label", "children", "onPointerDown"]);
1256
1296
  // -- state and ref ---
1257
- const [pressed, setPressed] = React.useState(false);
1258
- const [whiteNoteWidth, setWhiteNoteWidth] = React.useState(-1);
1297
+ const [whiteNoteWidth, setWhiteNoteWidth] = React.useState(_whiteNoteWidth);
1259
1298
  const keyRefs = React.useRef([]);
1260
1299
  for (let i = 0; i < noteRange.last - noteRange.first + 1; i++) {
1261
1300
  keyRefs.current[i] = React.createRef();
1262
1301
  }
1263
1302
  const pianoRef = React.useRef(null);
1303
+ const hitKeyIndex = React.useRef(-1);
1264
1304
  // --- interpret props ---
1265
- const noteRangeArray = Array.from({ length: noteRange.last - noteRange.first + 1 }, (_, i) => i + noteRange.first);
1266
- const whiteNoteCount = noteRangeArray.filter((v) => isWhiteKey(v)).length;
1267
- let whiteKeyProps = {}, blackKeyProps = {};
1268
- if (children != undefined) {
1269
- React.Children.forEach(children, (child) => {
1270
- if (React.isValidElement(child)) {
1271
- if (child.type == WhiteKey) {
1272
- whiteKeyProps = child.props;
1273
- }
1274
- else if (child.type == BlackKey) {
1275
- blackKeyProps = child.props;
1276
- }
1277
- else {
1278
- throw new Error('only <WhiteKey> or <BlackKey>');
1305
+ const noteRangeArray = getNoteRangeArray(noteRange);
1306
+ const whiteNotes = noteRangeArray.filter((v) => isWhiteKey(v));
1307
+ const blackNotes = noteRangeArray.filter((v) => isBlackKey(v));
1308
+ const whiteNoteCount = whiteNotes.length;
1309
+ const padding = 1;
1310
+ const staticWidth = (whiteNoteWidth + padding) * whiteNoteCount;
1311
+ // const blackNoteShiftPercent = 0.3
1312
+ // TODO: if fill setWhiteNoteWidth
1313
+ // useMemo
1314
+ // __width
1315
+ const childrenWithProps = React.useMemo(() => {
1316
+ return (children &&
1317
+ React.Children.map(children, (child, index) => {
1318
+ if (React.isValidElement(child)) {
1319
+ const props = { ref: keyRefs.current[index] };
1320
+ return React.cloneElement(child, props);
1279
1321
  }
1280
- }
1281
- else {
1282
- throw new Error('children is an invalid element.');
1283
- }
1284
- });
1285
- }
1322
+ return child;
1323
+ }));
1324
+ }, [children]);
1286
1325
  // --- internal functions ---
1287
- function notePosition(note) {
1326
+ const notePosition = React.useCallback((note) => {
1288
1327
  const pitchPositions = {
1289
1328
  C: 0,
1290
- 'C#': 0.55,
1329
+ 'C#': 1,
1291
1330
  D: 1,
1292
- 'D#': 1.8,
1331
+ 'D#': 2,
1293
1332
  E: 2,
1294
1333
  F: 3,
1295
- 'F#': 3.5,
1334
+ 'F#': 4,
1296
1335
  G: 4,
1297
- 'G#': 4.7,
1336
+ 'G#': 5,
1298
1337
  A: 5,
1299
- 'A#': 5.85,
1338
+ 'A#': 6,
1300
1339
  B: 6,
1301
1340
  };
1341
+ const whiteNoteWidth = defaultWhiteKeyWidth;
1342
+ const blackNoteWidth = defaultBlackKeyWidth;
1343
+ const padding = 1;
1302
1344
  const targetNoteKey = noteKey(note);
1303
1345
  const firstNoteKey = noteKey(noteRange.first);
1304
- const pos = pitchPositions[targetNoteKey] - pitchPositions[firstNoteKey];
1305
1346
  const octave = Math.floor((note - noteRange.first) / 12);
1306
1347
  const octaveOffset = noteKeys.indexOf(firstNoteKey) > noteKeys.indexOf(targetNoteKey) ? 1 : 0;
1307
- const length = whiteNoteWidth + 3;
1308
- return pos * length + (octave + octaveOffset) * 7 * length;
1309
- }
1348
+ const w = whiteNoteWidth + padding;
1349
+ const pos = pitchPositions[targetNoteKey] - pitchPositions[firstNoteKey];
1350
+ const blackKeyOffset = isBlackKey(note) ? blackNoteWidth / 2 : 0;
1351
+ return pos * w + (octave + octaveOffset) * 7 * w - blackKeyOffset;
1352
+ }, [noteRange.first]);
1353
+ const getHitKeyIndex = React.useCallback((x, y) => {
1354
+ if (!pianoRef.current)
1355
+ return -1;
1356
+ const containerHeight = pianoRef.current.clientHeight;
1357
+ const notes = [...blackNotes, ...whiteNotes];
1358
+ for (let i = 0; i < notes.length; i++) {
1359
+ const note = notes[i];
1360
+ const pos = notePosition(note);
1361
+ const w = isWhiteKey(note) ? defaultWhiteKeyWidth : defaultBlackKeyWidth;
1362
+ const h = isWhiteKey(note) ? containerHeight : containerHeight * 0.6;
1363
+ if (pos <= x && x < pos + w && 0 <= y && y < h) {
1364
+ return note;
1365
+ }
1366
+ }
1367
+ return -1;
1368
+ }, [blackNotes, notePosition, whiteNotes]);
1369
+ // TODO: 単一のポインターに対しては、useDragで対応可能だが、
1370
+ // マルチタッチに対しては、TouchEventを使う必要がありそう
1371
+ // 取り敢えず、シングルタッチだけ対応
1372
+ const onDrag = React.useCallback((perX, perY) => {
1373
+ var _a, _b, _c, _d;
1374
+ if (!pianoRef.current)
1375
+ return;
1376
+ const x = perX * staticWidth;
1377
+ const y = perY * pianoRef.current.clientHeight;
1378
+ const note = getHitKeyIndex(x, y);
1379
+ const index = noteRangeArray.indexOf(note);
1380
+ if (index == -1)
1381
+ return;
1382
+ if (hitKeyIndex.current != index) {
1383
+ (_b = (_a = keyRefs.current[hitKeyIndex.current]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.stop();
1384
+ (_d = (_c = keyRefs.current[index]) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.play();
1385
+ hitKeyIndex.current = index;
1386
+ }
1387
+ }, [getHitKeyIndex, noteRangeArray, staticWidth]);
1388
+ const onDragEnd = React.useCallback(() => {
1389
+ var _a, _b, _c, _d;
1390
+ if ((_b = (_a = keyRefs.current[hitKeyIndex.current]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.played()) {
1391
+ (_d = (_c = keyRefs.current[hitKeyIndex.current]) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.stop();
1392
+ }
1393
+ hitKeyIndex.current = -1;
1394
+ }, [keyRefs]);
1310
1395
  // --- hooks ---
1311
1396
  React.useEffect(() => {
1312
1397
  if (fill && pianoRef.current) {
@@ -1315,7 +1400,7 @@ function Piano(_a) {
1315
1400
  throw new Error("doesn't have a parent element.");
1316
1401
  const resizeObserver = new ResizeObserver(() => {
1317
1402
  const w = pianoRef.current.clientWidth;
1318
- setWhiteNoteWidth(w / whiteNoteCount - 3);
1403
+ setWhiteNoteWidth(w / whiteNoteCount - padding);
1319
1404
  });
1320
1405
  resizeObserver.observe(parent);
1321
1406
  return () => {
@@ -1323,9 +1408,14 @@ function Piano(_a) {
1323
1408
  };
1324
1409
  }
1325
1410
  else {
1326
- setWhiteNoteWidth((whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width) || defaultWhiteKeyWidth);
1411
+ setWhiteNoteWidth(_whiteNoteWidth);
1327
1412
  }
1328
- }, [fill, whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width, whiteNoteCount]);
1413
+ }, [fill, _whiteNoteWidth, whiteNoteCount]);
1414
+ const [touchMoveRefCallback, pointerDownHandler] = useDragWithElement({
1415
+ baseElementRef: pianoRef,
1416
+ onDrag: onDrag,
1417
+ onDragEnd: onDragEnd,
1418
+ });
1329
1419
  useEventListener(globalThis.window, 'keydown', (e) => {
1330
1420
  var _a, _b, _c, _d;
1331
1421
  if (e.repeat)
@@ -1350,15 +1440,14 @@ function Piano(_a) {
1350
1440
  (_b = (_a = keyRefs.current[index]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.stop();
1351
1441
  }
1352
1442
  });
1353
- return (jsxRuntime.jsx("div", Object.assign({ ref: pianoRef, className: clsx('tremolo-piano', className), style: Object.assign({ width: fill ? '100%' : (whiteNoteWidth + 3) * whiteNoteCount, height: height }, style), onPointerDown: (e) => {
1354
- setPressed(true);
1355
- onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(e);
1356
- }, onPointerUp: (e) => {
1357
- setPressed(false);
1358
- onPointerUp === null || onPointerUp === void 0 ? void 0 : onPointerUp(e);
1359
- } }, props, { children: noteRangeArray.map((note, index) => {
1360
- return isWhiteKey(note) ? (jsxRuntime.jsx(WhiteKey, Object.assign({ ref: keyRefs.current[index], __glissando: glissando && pressed, __position: notePosition(note), __note: note, __disabled: note > midiMax, __index: index, __fill: fill, __width: whiteNoteWidth, __onPlayNote: onPlayNote, __onStopNote: onStopNote, __label: label }, whiteKeyProps), note)) : (jsxRuntime.jsx(BlackKey, Object.assign({ ref: keyRefs.current[index], __glissando: glissando && pressed, __position: notePosition(note), __note: note, __disabled: note > midiMax, __index: index, __fill: fill, __width: whiteNoteWidth * 0.65, __onPlayNote: onPlayNote, __onStopNote: onStopNote, __label: label }, blackKeyProps), note));
1361
- }) })));
1443
+ return (jsxRuntime.jsx(PianoProvider, { noteRange: noteRange, glissando: glissando, midiMax: midiMax, fill: fill, onPlayNote: onPlayNote, onStopNote: onStopNote, label: label, children: jsxRuntime.jsx("div", Object.assign({ ref: (div) => {
1444
+ pianoRef.current = div;
1445
+ touchMoveRefCallback(div);
1446
+ }, className: clsx('tremolo-piano', className), style: Object.assign({ width: fill ? '100%' : staticWidth, height: height }, style), onPointerDown: (event) => {
1447
+ pointerDownHandler(event);
1448
+ onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
1449
+ } }, props, { children: childrenWithProps ||
1450
+ getNoteRangeArray(noteRange).map((note, index) => isWhiteKey(note) ? (jsxRuntime.jsx(WhiteKey, { ref: keyRefs.current[index], noteNumber: note }, note)) : (jsxRuntime.jsx(BlackKey, { ref: keyRefs.current[index], noteNumber: note }, note))) })) }));
1362
1451
  }
1363
1452
 
1364
1453
  const createSliderStore = (initProps) => {
@@ -1529,7 +1618,6 @@ const Slider = React.forwardRef((_a, ref) => {
1529
1618
  // -- state and ref ---
1530
1619
  const trackElementRef = React.useRef(null);
1531
1620
  const thumbRef = React.useRef(null);
1532
- const thumbDragged = React.useRef(false);
1533
1621
  // --- interpret props ---
1534
1622
  const p = toFixed$1(normalizeValue(value, min, max, skew) * 100);
1535
1623
  const rev = toFixed$1(100 - p);
@@ -1565,29 +1653,14 @@ const Slider = React.forwardRef((_a, ref) => {
1565
1653
  });
1566
1654
  }
1567
1655
  // --- internal functions ---
1568
- const handleValue = (event) => {
1569
- if (!trackElementRef.current ||
1570
- !thumbDragged.current ||
1571
- !onChange ||
1572
- readonly) {
1656
+ const onDrag = React.useCallback((nx, ny) => {
1657
+ if (!onChange || readonly)
1573
1658
  return;
1574
- }
1575
- const isTouch = event instanceof TouchEvent;
1576
- if (isTouch && event.cancelable)
1577
- event.preventDefault();
1578
- if (bodyNoSelect)
1579
- addNoSelect();
1580
- const { left: x1, top: y1, right: x2, bottom: y2, } = trackElementRef.current.getBoundingClientRect();
1581
- const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
1582
- const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
1583
- const n = vertical
1584
- ? normalizeValue(mouseY, y1, y2)
1585
- : normalizeValue(mouseX, x1, x2);
1659
+ const n = vertical ? ny : nx;
1586
1660
  const v = rawValue(displayReversed ? 1 - n : n, min, max, skew);
1587
1661
  const v2 = clamp(stepValue(v, step), min, max);
1588
1662
  onChange(v2);
1589
- return v2;
1590
- };
1663
+ }, [displayReversed, max, min, onChange, readonly, skew, step, vertical]);
1591
1664
  const updateValueByEvent = React.useCallback((eventType, x) => {
1592
1665
  let newValue;
1593
1666
  if (eventType == 'normalized') {
@@ -1612,7 +1685,26 @@ const Slider = React.forwardRef((_a, ref) => {
1612
1685
  }
1613
1686
  }, [keyboard, onChange, readonly, reverse, updateValueByEvent]);
1614
1687
  // --- hooks ---
1615
- const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleValue, { passive: false }, [min, max, skew, step, vertical, reverse, onChange, readonly]);
1688
+ const [touchMoveRefCallback, pointerDownHandler] = useDragWithElement({
1689
+ baseElementRef: trackElementRef,
1690
+ onDrag: onDrag,
1691
+ onDragStart: (nx, ny) => {
1692
+ var _a;
1693
+ if (readonly)
1694
+ return;
1695
+ if (bodyNoSelect)
1696
+ addNoSelect();
1697
+ (_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.focus();
1698
+ onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(clamp(stepValue(rawValue(vertical ? ny : nx, min, max, skew), step), min, max));
1699
+ },
1700
+ onDragEnd: (nx, ny) => {
1701
+ if (readonly)
1702
+ return;
1703
+ if (bodyNoSelect)
1704
+ removeNoSelect();
1705
+ onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(clamp(stepValue(rawValue(vertical ? ny : nx, min, max, skew), step), min, max));
1706
+ },
1707
+ });
1616
1708
  const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
1617
1709
  if (!wheel || !onChange || readonly)
1618
1710
  return;
@@ -1632,17 +1724,6 @@ const Slider = React.forwardRef((_a, ref) => {
1632
1724
  }, {
1633
1725
  passive: false,
1634
1726
  }, [wheel, vertical, readonly, onChange, updateValueByEvent]);
1635
- useEventListener(globalThis.window, 'mousemove', (event) => {
1636
- handleValue(event);
1637
- });
1638
- useEventListener(globalThis.window, 'mouseup', () => {
1639
- if (!thumbDragged.current || readonly)
1640
- return;
1641
- thumbDragged.current = false;
1642
- onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(value);
1643
- if (bodyNoSelect)
1644
- removeNoSelect();
1645
- });
1646
1727
  React.useImperativeHandle(ref, () => {
1647
1728
  return {
1648
1729
  focus() {
@@ -1659,10 +1740,7 @@ const Slider = React.forwardRef((_a, ref) => {
1659
1740
  wheelRefCallback(div);
1660
1741
  touchMoveRefCallback(div);
1661
1742
  }, tabIndex: -1, role: "slider", "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-orientation": vertical ? 'vertical' : 'horizontal', "aria-disabled": disabled, "aria-readonly": readonly, style: Object.assign({ margin: `calc(${styleHelper((_b = thumbProps === null || thumbProps === void 0 ? void 0 : thumbProps.size) !== null && _b !== void 0 ? _b : 22)} / 2)` }, style), onPointerDown: (event) => {
1662
- thumbDragged.current = true;
1663
- const v = handleValue(event);
1664
- if (!readonly)
1665
- onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(v !== null && v !== void 0 ? v : value);
1743
+ pointerDownHandler(event);
1666
1744
  onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
1667
1745
  }, onKeyDown: (event) => {
1668
1746
  handleKeyDown(event);
@@ -1745,13 +1823,13 @@ const XYPad = React.forwardRef((_a, ref) => {
1745
1823
  // -- state and ref ---
1746
1824
  const areaElementRef = React.useRef(null);
1747
1825
  const thumbRef = React.useRef(null);
1748
- const thumbDragged = React.useRef(false);
1749
1826
  // --- interpret props ---
1750
1827
  const nx = normalizeValue(x.value, x.min, x.max, x.skew);
1751
1828
  const ny = normalizeValue(y.value, y.min, y.max, y.skew);
1752
1829
  const percentX = toFixed$1((x.reverse ? 1 - nx : nx) * 100);
1753
1830
  const percentY = toFixed$1((y.reverse ? 1 - ny : ny) * 100);
1754
- let areaProps = {}, thumbProps = {};
1831
+ let areaProps = {};
1832
+ let thumbProps = {};
1755
1833
  if (children != undefined) {
1756
1834
  React.Children.forEach(children, (child) => {
1757
1835
  if (React.isValidElement(child)) {
@@ -1771,29 +1849,28 @@ const XYPad = React.forwardRef((_a, ref) => {
1771
1849
  });
1772
1850
  }
1773
1851
  // --- internal functions ---
1774
- const handleValue = (event) => {
1775
- if (!areaElementRef.current ||
1776
- !thumbDragged.current ||
1777
- !onChange ||
1778
- readonly)
1852
+ const onDrag = React.useCallback((nx, ny) => {
1853
+ if (!onChange || readonly)
1779
1854
  return;
1780
- const isTouch = event instanceof TouchEvent;
1781
- if (isTouch && event.cancelable)
1782
- event.preventDefault();
1783
- if (bodyNoSelect)
1784
- addNoSelect();
1785
- const { left: x1, top: y1, right: x2, bottom: y2, } = areaElementRef.current.getBoundingClientRect();
1786
- const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
1787
- const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
1788
- const nx = normalizeValue(mouseX, x1, x2);
1789
- const ny = normalizeValue(mouseY, y1, y2);
1790
1855
  const vx = rawValue(x.reverse ? 1 - nx : nx, x.min, x.max, x.skew);
1791
1856
  const vy = rawValue(y.reverse ? 1 - ny : ny, y.min, y.max, y.skew);
1792
1857
  const newX = clamp(stepValue(vx, x.step), x.min, x.max);
1793
1858
  const newY = clamp(stepValue(vy, y.step), y.min, y.max);
1794
1859
  onChange(newX, newY);
1795
- return [newX, newY];
1796
- };
1860
+ }, [
1861
+ onChange,
1862
+ readonly,
1863
+ x.max,
1864
+ x.min,
1865
+ x.reverse,
1866
+ x.skew,
1867
+ x.step,
1868
+ y.max,
1869
+ y.min,
1870
+ y.reverse,
1871
+ y.skew,
1872
+ y.step,
1873
+ ]);
1797
1874
  const updateValueByEvent = React.useCallback((eventType, target, x) => {
1798
1875
  let v;
1799
1876
  if (eventType == 'normalized') {
@@ -1830,7 +1907,30 @@ const XYPad = React.forwardRef((_a, ref) => {
1830
1907
  }
1831
1908
  }, [onChange, readonly, x, y, updateValueByEvent]);
1832
1909
  // --- hooks ---
1833
- const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleValue, { passive: false }, [x, onChange, readonly]);
1910
+ const [touchMoveRefCallback, pointerDownHandler] = useDragWithElement({
1911
+ baseElementRef: areaElementRef,
1912
+ onDrag: onDrag,
1913
+ onDragStart: (nx, ny) => {
1914
+ var _a;
1915
+ if (readonly)
1916
+ return;
1917
+ if (bodyNoSelect)
1918
+ addNoSelect();
1919
+ (_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.focus();
1920
+ const valueX = clamp(stepValue(rawValue(nx, x.min, x.max, x.skew), x.step), x.min, x.max);
1921
+ const valueY = clamp(stepValue(rawValue(ny, y.min, y.max, y.skew), y.step), y.min, y.max);
1922
+ onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(valueX, valueY);
1923
+ },
1924
+ onDragEnd: (nx, ny) => {
1925
+ if (readonly)
1926
+ return;
1927
+ if (bodyNoSelect)
1928
+ removeNoSelect();
1929
+ const valueX = clamp(stepValue(rawValue(nx, x.min, x.max, x.skew), x.step), x.min, x.max);
1930
+ const valueY = clamp(stepValue(rawValue(ny, y.min, y.max, y.skew), y.step), y.min, y.max);
1931
+ onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(valueX, valueY);
1932
+ },
1933
+ });
1834
1934
  const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
1835
1935
  if (!onChange || readonly)
1836
1936
  return;
@@ -1853,17 +1953,6 @@ const XYPad = React.forwardRef((_a, ref) => {
1853
1953
  }, {
1854
1954
  passive: false,
1855
1955
  }, [x, y, onChange, readonly, updateValueByEvent]);
1856
- useEventListener(globalThis.window, 'mousemove', (event) => {
1857
- handleValue(event);
1858
- });
1859
- useEventListener(globalThis.window, 'mouseup', () => {
1860
- if (!thumbDragged.current || readonly)
1861
- return;
1862
- thumbDragged.current = false;
1863
- onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(x.value, y.value);
1864
- if (bodyNoSelect)
1865
- removeNoSelect();
1866
- });
1867
1956
  React.useImperativeHandle(ref, () => {
1868
1957
  return {
1869
1958
  focus() {
@@ -1882,11 +1971,7 @@ const XYPad = React.forwardRef((_a, ref) => {
1882
1971
  wheelRefCallback(div);
1883
1972
  touchMoveRefCallback(div);
1884
1973
  }, tabIndex: -1, "aria-disabled": disabled, "aria-readonly": readonly, style: Object.assign({ margin: `calc(${styleHelper((_b = thumbProps === null || thumbProps === void 0 ? void 0 : thumbProps.size) !== null && _b !== void 0 ? _b : 22)} / 2)`, cursor: readonly ? 'not-allowed' : 'pointer', WebkitTapHighlightColor: 'transparent' }, style), onPointerDown: (event) => {
1885
- var _a, _b;
1886
- thumbDragged.current = true;
1887
- const v = handleValue(event);
1888
- if (!readonly)
1889
- onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart((_a = v === null || v === void 0 ? void 0 : v[0]) !== null && _a !== void 0 ? _a : x.value, (_b = v === null || v === void 0 ? void 0 : v[1]) !== null && _b !== void 0 ? _b : y.value);
1974
+ pointerDownHandler(event);
1890
1975
  onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
1891
1976
  }, onKeyDown: (event) => {
1892
1977
  handleKeyDown(event);
@@ -1940,8 +2025,10 @@ exports.WhiteKey = WhiteKey;
1940
2025
  exports.XYPad = XYPad;
1941
2026
  exports.XYPadArea = XYPadArea;
1942
2027
  exports.XYPadThumb = XYPadThumb;
2028
+ exports.getNoteRangeArray = getNoteRangeArray;
1943
2029
  exports.useAnimationFrame = useAnimationFrame;
1944
2030
  exports.useDrag = useDrag;
2031
+ exports.useDragWithElement = useDragWithElement;
1945
2032
  exports.useEventListener = useEventListener;
1946
2033
  exports.useInterval = useInterval;
1947
2034
  exports.useLongPress = useLongPress;