@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.
- package/dist/cjs/index.js +320 -233
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Knob/index.d.ts +12 -0
- package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts +1 -3
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/context.d.ts +24 -0
- package/dist/cjs/types/components/Piano/context.d.ts.map +1 -0
- package/dist/cjs/types/components/Piano/index.d.ts +9 -9
- package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/key.d.ts +10 -19
- package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/index.d.ts.map +1 -1
- package/dist/cjs/types/hooks/useDrag.d.ts.map +1 -1
- package/dist/cjs/types/hooks/useDragWithElement.d.ts +16 -0
- package/dist/cjs/types/hooks/useDragWithElement.d.ts.map +1 -0
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/esm/index.js +319 -234
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/Knob/index.d.ts +12 -0
- package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/KeyLabel.d.ts +1 -3
- package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/context.d.ts +24 -0
- package/dist/esm/types/components/Piano/context.d.ts.map +1 -0
- package/dist/esm/types/components/Piano/index.d.ts +9 -9
- package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/key.d.ts +10 -19
- package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/index.d.ts.map +1 -1
- package/dist/esm/types/hooks/useDrag.d.ts.map +1 -1
- package/dist/esm/types/hooks/useDragWithElement.d.ts +16 -0
- package/dist/esm/types/hooks/useDragWithElement.d.ts.map +1 -0
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/styles/index.css +2 -0
- package/package.json +2 -1
- package/src/components/AnimationCanvas/index.tsx +3 -1
- package/src/components/Knob/index.tsx +14 -0
- package/src/components/Piano/KeyLabel.tsx +9 -5
- package/src/components/Piano/context.tsx +108 -0
- package/src/components/Piano/index.css +2 -0
- package/src/components/Piano/index.tsx +186 -114
- package/src/components/Piano/key.tsx +215 -0
- package/src/components/Slider/index.tsx +40 -52
- package/src/components/XYPad/index.tsx +64 -54
- package/src/hooks/useDrag.ts +6 -7
- package/src/hooks/useDragWithElement.ts +76 -0
- package/src/index.ts +1 -0
- package/dist/cjs/types/components/Piano/BlackKey.d.ts +0 -5
- package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +0 -1
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts +0 -7
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +0 -1
- package/dist/esm/types/components/Piano/BlackKey.d.ts +0 -5
- package/dist/esm/types/components/Piano/BlackKey.d.ts.map +0 -1
- package/dist/esm/types/components/Piano/WhiteKey.d.ts +0 -7
- package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +0 -1
- package/src/components/Piano/BlackKey.tsx +0 -132
- package/src/components/Piano/WhiteKey.tsx +0 -134
- 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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
1067
|
-
: __label && __label(__note,
|
|
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
|
|
1075
|
-
|
|
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 (
|
|
1146
|
+
if (disabled)
|
|
1087
1147
|
return;
|
|
1088
1148
|
setPlayed(true);
|
|
1089
|
-
if (
|
|
1090
|
-
|
|
1149
|
+
if (onPlayNote)
|
|
1150
|
+
onPlayNote(noteNumber);
|
|
1091
1151
|
},
|
|
1092
1152
|
stop() {
|
|
1093
1153
|
setPlayed(false);
|
|
1094
|
-
if (
|
|
1095
|
-
|
|
1154
|
+
if (onStopNote)
|
|
1155
|
+
onStopNote(noteNumber);
|
|
1096
1156
|
},
|
|
1097
1157
|
played() {
|
|
1098
1158
|
return played;
|
|
1099
1159
|
},
|
|
1100
1160
|
};
|
|
1101
|
-
}, [
|
|
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-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
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 =
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
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
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
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,
|
|
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 [
|
|
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 =
|
|
1266
|
-
const
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
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
|
-
|
|
1282
|
-
|
|
1283
|
-
}
|
|
1284
|
-
});
|
|
1285
|
-
}
|
|
1322
|
+
return child;
|
|
1323
|
+
}));
|
|
1324
|
+
}, [children]);
|
|
1286
1325
|
// --- internal functions ---
|
|
1287
|
-
|
|
1326
|
+
const notePosition = React.useCallback((note) => {
|
|
1288
1327
|
const pitchPositions = {
|
|
1289
1328
|
C: 0,
|
|
1290
|
-
'C#':
|
|
1329
|
+
'C#': 1,
|
|
1291
1330
|
D: 1,
|
|
1292
|
-
'D#':
|
|
1331
|
+
'D#': 2,
|
|
1293
1332
|
E: 2,
|
|
1294
1333
|
F: 3,
|
|
1295
|
-
'F#':
|
|
1334
|
+
'F#': 4,
|
|
1296
1335
|
G: 4,
|
|
1297
|
-
'G#':
|
|
1336
|
+
'G#': 5,
|
|
1298
1337
|
A: 5,
|
|
1299
|
-
'A#':
|
|
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
|
|
1308
|
-
|
|
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 -
|
|
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(
|
|
1411
|
+
setWhiteNoteWidth(_whiteNoteWidth);
|
|
1327
1412
|
}
|
|
1328
|
-
}, [fill,
|
|
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(
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
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
|
|
1569
|
-
if (!
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 = {}
|
|
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
|
|
1775
|
-
if (!
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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;
|