@tremolo-ui/react 0.0.11 → 0.1.0-alpha.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/cjs/index.js +711 -395
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts +2 -2
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/cjs/types/components/AnimationKnob/index.d.ts +10 -3
- package/dist/cjs/types/components/AnimationKnob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Knob/index.d.ts +25 -3
- package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts +2 -0
- package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts +2 -0
- package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/InternalInput.d.ts +18 -0
- package/dist/cjs/types/components/NumberInput/InternalInput.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/Stepper.d.ts +2 -0
- package/dist/cjs/types/components/NumberInput/Stepper.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/context.d.ts +3 -2
- package/dist/cjs/types/components/NumberInput/context.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/index.d.ts +12 -3
- package/dist/cjs/types/components/NumberInput/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 +15 -12
- package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/key.d.ts +14 -19
- package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +2 -2
- package/dist/cjs/types/components/Slider/Scale.d.ts +1 -3
- package/dist/cjs/types/components/Slider/Scale.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Thumb.d.ts +1 -0
- package/dist/cjs/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Track.d.ts +2 -2
- package/dist/cjs/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/index.d.ts +5 -1
- package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
- package/dist/cjs/types/components/WheelObserver/index.d.ts +3 -3
- package/dist/cjs/types/components/WheelObserver/index.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/Area.d.ts +3 -3
- package/dist/cjs/types/components/XYPad/Area.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/Thumb.d.ts +1 -0
- package/dist/cjs/types/components/XYPad/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/index.d.ts +6 -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/hooks/useInterval.d.ts +2 -0
- package/dist/cjs/types/hooks/useInterval.d.ts.map +1 -0
- package/dist/cjs/types/hooks/useLongPress.d.ts +2 -0
- package/dist/cjs/types/hooks/useLongPress.d.ts.map +1 -0
- package/dist/cjs/types/index.d.ts +5 -0
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/esm/index.js +706 -396
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/AnimationCanvas/index.d.ts +2 -2
- package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/esm/types/components/AnimationKnob/index.d.ts +10 -3
- package/dist/esm/types/components/AnimationKnob/index.d.ts.map +1 -1
- package/dist/esm/types/components/Knob/index.d.ts +25 -3
- package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts +2 -0
- package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts +2 -0
- package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/InternalInput.d.ts +18 -0
- package/dist/esm/types/components/NumberInput/InternalInput.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/Stepper.d.ts +2 -0
- package/dist/esm/types/components/NumberInput/Stepper.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/context.d.ts +3 -2
- package/dist/esm/types/components/NumberInput/context.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/index.d.ts +12 -3
- package/dist/esm/types/components/NumberInput/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 +15 -12
- package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/key.d.ts +14 -19
- package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +2 -2
- package/dist/esm/types/components/Slider/Scale.d.ts +1 -3
- package/dist/esm/types/components/Slider/Scale.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Thumb.d.ts +1 -0
- package/dist/esm/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Track.d.ts +2 -2
- package/dist/esm/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/index.d.ts +5 -1
- package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
- package/dist/esm/types/components/WheelObserver/index.d.ts +3 -3
- package/dist/esm/types/components/WheelObserver/index.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/Area.d.ts +3 -3
- package/dist/esm/types/components/XYPad/Area.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/Thumb.d.ts +1 -0
- package/dist/esm/types/components/XYPad/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/index.d.ts +6 -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/hooks/useInterval.d.ts +2 -0
- package/dist/esm/types/hooks/useInterval.d.ts.map +1 -0
- package/dist/esm/types/hooks/useLongPress.d.ts +2 -0
- package/dist/esm/types/hooks/useLongPress.d.ts.map +1 -0
- package/dist/esm/types/index.d.ts +5 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/styles/index.css +117 -33
- package/package.json +3 -2
- package/src/components/AnimationCanvas/index.tsx +14 -6
- package/src/components/AnimationKnob/index.tsx +216 -187
- package/src/components/Knob/index.tsx +244 -171
- package/src/components/NumberInput/DecrementStepper.tsx +9 -2
- package/src/components/NumberInput/IncrementStepper.tsx +9 -2
- package/src/components/NumberInput/InternalInput.tsx +219 -0
- package/src/components/NumberInput/Stepper.tsx +2 -0
- package/src/components/NumberInput/context.tsx +20 -8
- package/src/components/NumberInput/index.css +76 -22
- package/src/components/NumberInput/index.tsx +94 -162
- package/src/components/Piano/KeyLabel.tsx +9 -5
- package/src/components/Piano/context.tsx +108 -0
- package/src/components/Piano/index.css +24 -6
- package/src/components/Piano/index.tsx +192 -122
- package/src/components/Piano/key.tsx +215 -0
- package/src/components/Piano/keyboardShortcuts.ts +2 -2
- package/src/components/Slider/Scale.tsx +1 -4
- package/src/components/Slider/Thumb.tsx +4 -0
- package/src/components/Slider/Track.tsx +5 -2
- package/src/components/Slider/index.css +5 -2
- package/src/components/Slider/index.tsx +84 -71
- package/src/components/WheelObserver/index.tsx +4 -2
- package/src/components/XYPad/Area.tsx +7 -6
- package/src/components/XYPad/Thumb.tsx +6 -0
- package/src/components/XYPad/index.css +12 -2
- package/src/components/XYPad/index.tsx +116 -90
- package/src/hooks/useDrag.ts +6 -7
- package/src/hooks/useDragWithElement.ts +76 -0
- package/src/hooks/useInterval.ts +27 -0
- package/src/hooks/useLongPress.ts +31 -0
- package/src/index.ts +6 -0
- package/src/styles/index.css +0 -1
- 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 -118
- package/src/components/Piano/WhiteKey.tsx +0 -120
- package/src/components/Piano/key.ts +0 -46
package/dist/cjs/index.js
CHANGED
|
@@ -69,7 +69,7 @@ function setDprConfig(canvas, context, width, height, dpr) {
|
|
|
69
69
|
canvas.style.height = `${height}px`;
|
|
70
70
|
}
|
|
71
71
|
function AnimationCanvas(_a) {
|
|
72
|
-
var { width = 100, height = 100, relativeSize = false, reduceFlickering = true, options, init, draw, className } = _a, props = __rest(_a, ["width", "height", "relativeSize", "reduceFlickering", "options", "init", "draw", "className"]);
|
|
72
|
+
var { width = 100, height = 100, relativeSize = false, reduceFlickering = true, options, init, draw, className, onContextMenu = (event) => event.preventDefault() } = _a, props = __rest(_a, ["width", "height", "relativeSize", "reduceFlickering", "options", "init", "draw", "className", "onContextMenu"]);
|
|
73
73
|
const canvasRef = React.useRef(null);
|
|
74
74
|
const memoCanvasRef = React.useRef(null);
|
|
75
75
|
const reqIdRef = React.useRef(-1);
|
|
@@ -118,7 +118,11 @@ function AnimationCanvas(_a) {
|
|
|
118
118
|
for (const prop of drawingState) {
|
|
119
119
|
context[prop] = contextMemo[prop];
|
|
120
120
|
}
|
|
121
|
-
if (reduceFlickering &&
|
|
121
|
+
if (reduceFlickering &&
|
|
122
|
+
memoContext &&
|
|
123
|
+
memoCanvas &&
|
|
124
|
+
memoCanvas.width > 0 &&
|
|
125
|
+
memoCanvas.height > 0) {
|
|
122
126
|
context.drawImage(memoContext.canvas, 0, 0);
|
|
123
127
|
}
|
|
124
128
|
}
|
|
@@ -150,7 +154,7 @@ function AnimationCanvas(_a) {
|
|
|
150
154
|
};
|
|
151
155
|
}
|
|
152
156
|
}, [loop, init, options, reduceFlickering, relativeSize]);
|
|
153
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("canvas", Object.assign({ className: clsx('tremolo-animation-canvas', className), width: relativeSize ? 0 : width, height: relativeSize ? 0 : height, ref: canvasRef }, props)), relativeSize && reduceFlickering && (jsxRuntime.jsx("canvas", { style: { display: 'none' }, ref: memoCanvasRef }))] }));
|
|
157
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("canvas", Object.assign({ className: clsx('tremolo-animation-canvas', className), width: relativeSize ? 0 : width, height: relativeSize ? 0 : height, ref: canvasRef, onContextMenu: onContextMenu }, props)), relativeSize && reduceFlickering && (jsxRuntime.jsx("canvas", { style: { display: 'none' }, ref: memoCanvasRef }))] }));
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
/**
|
|
@@ -258,7 +262,7 @@ function xor(a = false, b = false) {
|
|
|
258
262
|
/**
|
|
259
263
|
* @category MIDI
|
|
260
264
|
*/
|
|
261
|
-
const
|
|
265
|
+
const noteKeys = [
|
|
262
266
|
'C',
|
|
263
267
|
'C#',
|
|
264
268
|
'D',
|
|
@@ -292,18 +296,16 @@ function parseNoteName(noteName) {
|
|
|
292
296
|
*/
|
|
293
297
|
function noteNumber(noteName) {
|
|
294
298
|
const { letter, accidental, octave } = parseNoteName(noteName);
|
|
295
|
-
const noteIndex =
|
|
299
|
+
const noteIndex = noteKeys.indexOf(letter.toLocaleUpperCase());
|
|
296
300
|
const accidentalValue = (accidental[0] == 'b' ? -1 : 1) * accidental.length;
|
|
297
301
|
return noteIndex + 12 * (Number(octave) + 1) + accidentalValue;
|
|
298
302
|
}
|
|
299
303
|
/**
|
|
300
|
-
* Convert noteNumber to
|
|
304
|
+
* Convert noteNumber to noteKey
|
|
301
305
|
* @category MIDI
|
|
302
306
|
*/
|
|
303
|
-
function
|
|
304
|
-
|
|
305
|
-
const octave = Math.floor(noteNumber / 12) - 1;
|
|
306
|
-
return noteNames[noteIndex] + octave;
|
|
307
|
+
function noteKey(noteNumber) {
|
|
308
|
+
return noteKeys[mod(noteNumber, 12)];
|
|
307
309
|
}
|
|
308
310
|
/**
|
|
309
311
|
* @param note noteNumber: 0 ~ 127 or noteName e.g. 'C3'
|
|
@@ -319,6 +321,13 @@ function isWhiteKey(note) {
|
|
|
319
321
|
mod(n, 12) == 9 ||
|
|
320
322
|
mod(n, 12) == 11);
|
|
321
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* @param note noteNumber: 0 ~ 127 or noteName e.g. 'C3'
|
|
326
|
+
* @category MIDI
|
|
327
|
+
*/
|
|
328
|
+
function isBlackKey(note) {
|
|
329
|
+
return !isWhiteKey(note);
|
|
330
|
+
}
|
|
322
331
|
|
|
323
332
|
/**
|
|
324
333
|
* This hook is user-land implementation of the experimental `useEffectEvent` hook.
|
|
@@ -399,8 +408,7 @@ function useDrag({ threshold = 1, onDrag, onDragStart, onDragEnd, }) {
|
|
|
399
408
|
}
|
|
400
409
|
if (Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold)
|
|
401
410
|
return;
|
|
402
|
-
|
|
403
|
-
onDrag(screenX - dragStartX.current, screenY - dragStartY.current, deltaX, deltaY);
|
|
411
|
+
onDrag(screenX - dragStartX.current, screenY - dragStartY.current, deltaX, deltaY);
|
|
404
412
|
}, [threshold, onDrag]);
|
|
405
413
|
const refHandler = useRefCallbackEvent('touchmove', handleDrag, { passive: false }, [onDrag]);
|
|
406
414
|
const pointerDownHandler = React.useCallback((event) => {
|
|
@@ -426,13 +434,14 @@ function removeNoSelect() {
|
|
|
426
434
|
}
|
|
427
435
|
|
|
428
436
|
/**
|
|
429
|
-
*
|
|
437
|
+
* Animatable rotary knob.
|
|
430
438
|
* @category AnimationKnob
|
|
431
439
|
*/
|
|
432
|
-
|
|
440
|
+
const AnimationKnob = React.forwardRef((_a, ref) => {
|
|
433
441
|
var { value, min, max, defaultValue = min, startValue = min, step = 1, skew = 1, size, width = 50, height = 50, activeColor = '#7998ec', inactiveColor = '#eee', bg = '#ccc', thumb = '#4e76e6', lineWeight = 6, thumbWeight = 4, draw, bodyNoSelect = true, wheel = ['raw', 1], keyboard = ['raw', 1], enableDoubleClickDefault = true, style, className, onChange } = _a, props = __rest(_a, ["value", "min", "max", "defaultValue", "startValue", "step", "skew", "size", "width", "height", "activeColor", "inactiveColor", "bg", "thumb", "lineWeight", "thumbWeight", "draw", "bodyNoSelect", "wheel", "keyboard", "enableDoubleClickDefault", "style", "className", "onChange"]);
|
|
434
442
|
// -- state and ref ---
|
|
435
443
|
const valueRef = React.useRef(0);
|
|
444
|
+
const elmRef = React.useRef(null);
|
|
436
445
|
// --- interpret props ---
|
|
437
446
|
const isRelativeSize = typeof (size !== null && size !== void 0 ? size : width) == 'string' || typeof height == 'string';
|
|
438
447
|
const onDrag = React.useCallback((_x, y) => {
|
|
@@ -489,14 +498,27 @@ function AnimationKnob(_a) {
|
|
|
489
498
|
if (onChange)
|
|
490
499
|
onChange(clamp(stepValue(v, step), min, max));
|
|
491
500
|
}, { passive: false }, [wheel, value, min, max, skew, step, onChange]);
|
|
501
|
+
React.useImperativeHandle(ref, () => {
|
|
502
|
+
return {
|
|
503
|
+
focus() {
|
|
504
|
+
var _a;
|
|
505
|
+
(_a = elmRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
506
|
+
},
|
|
507
|
+
blur() {
|
|
508
|
+
var _a;
|
|
509
|
+
(_a = elmRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
}, []);
|
|
492
513
|
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-animation-knob', className), ref: (div) => {
|
|
514
|
+
elmRef.current = div;
|
|
493
515
|
wheelRefCallback(div);
|
|
494
516
|
touchMoveRefCallback(div);
|
|
495
517
|
}, role: "slider", tabIndex: 0, "aria-valuenow": value, "aria-valuemax": max, "aria-valuemin": min, style: Object.assign({ display: 'inline-block', width: size !== null && size !== void 0 ? size : width, height: size !== null && size !== void 0 ? size : height, cursor: 'pointer', WebkitTapHighlightColor: 'transparent' }, style), onPointerDown: pointerDownHandler, onDoubleClick: () => {
|
|
496
518
|
if (enableDoubleClickDefault && onChange) {
|
|
497
519
|
onChange(defaultValue);
|
|
498
520
|
}
|
|
499
|
-
}, onKeyDown: handleKeyDown
|
|
521
|
+
}, onKeyDown: handleKeyDown }, props, { children: jsxRuntime.jsx(AnimationCanvas, Object.assign({}, (isRelativeSize
|
|
500
522
|
? { relativeSize: true }
|
|
501
523
|
: {
|
|
502
524
|
width: size !== null && size !== void 0 ? size : width,
|
|
@@ -543,7 +565,7 @@ function AnimationKnob(_a) {
|
|
|
543
565
|
ctx.lineWidth = thumbWeight;
|
|
544
566
|
ctx.stroke();
|
|
545
567
|
} })) })));
|
|
546
|
-
}
|
|
568
|
+
});
|
|
547
569
|
|
|
548
570
|
/** @category DragObserver */
|
|
549
571
|
function DragObserver(props) {
|
|
@@ -557,15 +579,20 @@ function DragObserver(props) {
|
|
|
557
579
|
return (jsxRuntime.jsx(Component, Object.assign({ ref: refCallback, onPointerDown: pointerDownHandler }, attributes, { children: children })));
|
|
558
580
|
}
|
|
559
581
|
|
|
560
|
-
/**
|
|
561
|
-
|
|
562
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Interactive rotary knob component implemented in SVG.
|
|
584
|
+
*
|
|
585
|
+
* @category Knob
|
|
586
|
+
*/
|
|
587
|
+
const Knob = React.forwardRef((_a, ref) => {
|
|
588
|
+
var { value, min, max, step = 1, skew = 1, defaultValue = min, startValue = min, size = 50, bodyNoSelect = true, wheel = ['raw', 1], keyboard = ['raw', 1], enableDoubleClickDefault = true, disabled = false, readonly = false, activeLine, inactiveLine, thumb, thumbLine, onChange, onKeyDown, onPointerDown, onDoubleClick, className, classes } = _a, props = __rest(_a, ["value", "min", "max", "step", "skew", "defaultValue", "startValue", "size", "bodyNoSelect", "wheel", "keyboard", "enableDoubleClickDefault", "disabled", "readonly", "activeLine", "inactiveLine", "thumb", "thumbLine", "onChange", "onKeyDown", "onPointerDown", "onDoubleClick", "className", "classes"]);
|
|
563
589
|
const valueRef = React.useRef(0);
|
|
590
|
+
const elmRef = React.useRef(null);
|
|
564
591
|
// --- interpret props ---
|
|
565
592
|
const padding = 8; // %
|
|
566
593
|
const thumbLineWeight = 6; // %
|
|
567
|
-
const
|
|
568
|
-
const lineWeight =
|
|
594
|
+
const thumbLineLength = 35; // %
|
|
595
|
+
const lineWeight = size * 0.06; // px
|
|
569
596
|
const p = normalizeValue(value, min, max, skew);
|
|
570
597
|
const s = normalizeValue(startValue, min, max, skew);
|
|
571
598
|
// --- internal functions ---
|
|
@@ -576,6 +603,17 @@ function Knob(_a) {
|
|
|
576
603
|
const v2 = clamp(stepValue(v, step), min, max);
|
|
577
604
|
onChange(v2);
|
|
578
605
|
}, [max, min, onChange, readonly, skew, step]);
|
|
606
|
+
const updateValueByEvent = React.useCallback((eventType, x) => {
|
|
607
|
+
let newValue;
|
|
608
|
+
if (eventType == 'normalized') {
|
|
609
|
+
const n = normalizeValue(value, min, max, skew);
|
|
610
|
+
newValue = rawValue(n + x, min, max, skew);
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
newValue = value + x;
|
|
614
|
+
}
|
|
615
|
+
return clamp(stepValue(newValue, step), min, max);
|
|
616
|
+
}, [max, min, skew, step, value]);
|
|
579
617
|
const handleKeyDown = React.useCallback((event) => {
|
|
580
618
|
if (!keyboard || !onChange || readonly)
|
|
581
619
|
return;
|
|
@@ -583,17 +621,9 @@ function Knob(_a) {
|
|
|
583
621
|
if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {
|
|
584
622
|
event.preventDefault();
|
|
585
623
|
const x = key == 'ArrowRight' || key == 'ArrowUp' ? keyboard[1] : -keyboard[1];
|
|
586
|
-
|
|
587
|
-
if (keyboard[0] == 'normalized') {
|
|
588
|
-
const n = normalizeValue(value, min, max, skew);
|
|
589
|
-
v = rawValue(n + x, min, max, skew);
|
|
590
|
-
}
|
|
591
|
-
else {
|
|
592
|
-
v = value + x;
|
|
593
|
-
}
|
|
594
|
-
onChange(clamp(stepValue(v, step), min, max));
|
|
624
|
+
onChange(updateValueByEvent(keyboard[0], x));
|
|
595
625
|
}
|
|
596
|
-
}, [
|
|
626
|
+
}, [keyboard, onChange, readonly, updateValueByEvent]);
|
|
597
627
|
// --- hooks ---
|
|
598
628
|
const [touchMoveRefCallback, pointerDownHandler] = useDrag({
|
|
599
629
|
onDrag: onDrag,
|
|
@@ -608,21 +638,26 @@ function Knob(_a) {
|
|
|
608
638
|
},
|
|
609
639
|
});
|
|
610
640
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
611
|
-
if (!wheel)
|
|
641
|
+
if (!wheel || readonly)
|
|
612
642
|
return;
|
|
613
643
|
event.preventDefault();
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
644
|
+
if (!onChange || event.deltaY == 0)
|
|
645
|
+
return;
|
|
646
|
+
const x = Math.sign(event.deltaY) * -wheel[1];
|
|
647
|
+
onChange(updateValueByEvent(wheel[0], x));
|
|
648
|
+
}, { passive: false }, [wheel, onChange, readonly, updateValueByEvent]);
|
|
649
|
+
React.useImperativeHandle(ref, () => {
|
|
650
|
+
return {
|
|
651
|
+
focus() {
|
|
652
|
+
var _a;
|
|
653
|
+
(_a = elmRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
654
|
+
},
|
|
655
|
+
blur() {
|
|
656
|
+
var _a;
|
|
657
|
+
(_a = elmRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
}, []);
|
|
626
661
|
const center = size / 2;
|
|
627
662
|
const r1 = -135;
|
|
628
663
|
const r2 = -135 + Math.min(p, s) * 270;
|
|
@@ -637,13 +672,62 @@ function Knob(_a) {
|
|
|
637
672
|
const x4 = center + center * Math.cos(radian(r4 - 90));
|
|
638
673
|
const y4 = center + center * Math.sin(radian(r4 - 90));
|
|
639
674
|
return (jsxRuntime.jsxs("svg", Object.assign({ className: clsx('tremolo-knob', className), ref: (div) => {
|
|
675
|
+
elmRef.current = div;
|
|
640
676
|
wheelRefCallback(div);
|
|
641
677
|
touchMoveRefCallback(div);
|
|
642
|
-
}, width: size, height: size, tabIndex: 0, "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled, "aria-readonly": readonly, onPointerDown:
|
|
678
|
+
}, 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) => {
|
|
679
|
+
pointerDownHandler(event);
|
|
680
|
+
onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
|
|
681
|
+
}, onDoubleClick: (event) => {
|
|
643
682
|
if (enableDoubleClickDefault && onChange) {
|
|
644
683
|
onChange(defaultValue);
|
|
645
684
|
}
|
|
646
|
-
|
|
685
|
+
onDoubleClick === null || onDoubleClick === void 0 ? void 0 : onDoubleClick(event);
|
|
686
|
+
}, onKeyDown: (event) => {
|
|
687
|
+
handleKeyDown(event);
|
|
688
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
689
|
+
} }, props, { children: [startValue > min && (jsxRuntime.jsx("path", { className: clsx('tremolo-knob-inactive-line', classes === null || classes === void 0 ? void 0 : classes.inactiveLine), d: `M ${x1} ${y1} A ${center} ${center} -135 ${r2 - r1 > 180 ? 1 : 0} 1 ${x2}, ${y2}`, fill: "none", stroke: inactiveLine || 'currentColor', strokeWidth: lineWeight })), jsxRuntime.jsx("path", { className: clsx('tremolo-knob-active-line', classes === null || classes === void 0 ? void 0 : classes.activeLine), d: `M ${x2} ${y2} A ${center} ${center} -135 ${r3 - r2 > 180 ? 1 : 0} 1 ${x3}, ${y3}`, fill: "none", stroke: activeLine || 'currentColor', strokeWidth: lineWeight }), startValue < max && (jsxRuntime.jsx("path", { className: clsx('tremolo-knob-inactive-line', classes === null || classes === void 0 ? void 0 : classes.inactiveLine), d: `M ${x3} ${y3} A ${center} ${center} -135 ${r4 - r3 > 180 ? 1 : 0} 1 ${x4}, ${y4}`, fill: "none", stroke: inactiveLine || 'currentColor', strokeWidth: lineWeight })), jsxRuntime.jsxs("svg", { className: clsx('tremolo-knob-thumb', classes === null || classes === void 0 ? void 0 : classes.thumb), children: [jsxRuntime.jsx("circle", { cx: "50%", cy: "50%", r: `${50 - padding}%`, fill: thumb || 'currentColor' }), jsxRuntime.jsx("line", { className: clsx('tremolo-knob-thumb-line', classes === null || classes === void 0 ? void 0 : classes.thumbLine), x1: "50%", y1: `${padding}%`, x2: "50%", y2: `${thumbLineLength}%`, stroke: thumbLine || 'currentColor', strokeWidth: `${thumbLineWeight}%`,
|
|
690
|
+
// NOTE
|
|
691
|
+
// https://bugs.webkit.org/show_bug.cgi?id=201854
|
|
692
|
+
// https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/transform-origin#browser_compatibility
|
|
693
|
+
style: {
|
|
694
|
+
transform: `rotate(${ -135 + p * 270}deg)`,
|
|
695
|
+
transformOrigin: '50% 50%',
|
|
696
|
+
} })] })] })));
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
const createStoreImpl = (createState) => {
|
|
700
|
+
let state;
|
|
701
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
702
|
+
const setState = (partial, replace) => {
|
|
703
|
+
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
704
|
+
if (!Object.is(nextState, state)) {
|
|
705
|
+
const previousState = state;
|
|
706
|
+
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
|
707
|
+
listeners.forEach((listener) => listener(state, previousState));
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
const getState = () => state;
|
|
711
|
+
const getInitialState = () => initialState;
|
|
712
|
+
const subscribe = (listener) => {
|
|
713
|
+
listeners.add(listener);
|
|
714
|
+
return () => listeners.delete(listener);
|
|
715
|
+
};
|
|
716
|
+
const api = { setState, getState, getInitialState, subscribe };
|
|
717
|
+
const initialState = state = createState(setState, getState, api);
|
|
718
|
+
return api;
|
|
719
|
+
};
|
|
720
|
+
const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
721
|
+
|
|
722
|
+
const identity = (arg) => arg;
|
|
723
|
+
function useStore(api, selector = identity) {
|
|
724
|
+
const slice = React.useSyncExternalStore(
|
|
725
|
+
api.subscribe,
|
|
726
|
+
() => selector(api.getState()),
|
|
727
|
+
() => selector(api.getInitialState())
|
|
728
|
+
);
|
|
729
|
+
React.useDebugValue(slice);
|
|
730
|
+
return slice;
|
|
647
731
|
}
|
|
648
732
|
|
|
649
733
|
/**
|
|
@@ -692,40 +776,6 @@ function parseValue(inputString, units, digit) {
|
|
|
692
776
|
};
|
|
693
777
|
}
|
|
694
778
|
|
|
695
|
-
const createStoreImpl = (createState) => {
|
|
696
|
-
let state;
|
|
697
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
698
|
-
const setState = (partial, replace) => {
|
|
699
|
-
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
700
|
-
if (!Object.is(nextState, state)) {
|
|
701
|
-
const previousState = state;
|
|
702
|
-
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
|
703
|
-
listeners.forEach((listener) => listener(state, previousState));
|
|
704
|
-
}
|
|
705
|
-
};
|
|
706
|
-
const getState = () => state;
|
|
707
|
-
const getInitialState = () => initialState;
|
|
708
|
-
const subscribe = (listener) => {
|
|
709
|
-
listeners.add(listener);
|
|
710
|
-
return () => listeners.delete(listener);
|
|
711
|
-
};
|
|
712
|
-
const api = { setState, getState, getInitialState, subscribe };
|
|
713
|
-
const initialState = state = createState(setState, getState, api);
|
|
714
|
-
return api;
|
|
715
|
-
};
|
|
716
|
-
const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
717
|
-
|
|
718
|
-
const identity = (arg) => arg;
|
|
719
|
-
function useStore(api, selector = identity) {
|
|
720
|
-
const slice = React.useSyncExternalStore(
|
|
721
|
-
api.subscribe,
|
|
722
|
-
() => selector(api.getState()),
|
|
723
|
-
() => selector(api.getInitialState())
|
|
724
|
-
);
|
|
725
|
-
React.useDebugValue(slice);
|
|
726
|
-
return slice;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
779
|
function safeClamp(value, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
|
|
730
780
|
return clamp(value, min, max);
|
|
731
781
|
}
|
|
@@ -736,6 +786,7 @@ const createNumberInputStore = (initProps) => {
|
|
|
736
786
|
min: 0,
|
|
737
787
|
max: 0,
|
|
738
788
|
step: 1,
|
|
789
|
+
readonly: false,
|
|
739
790
|
keepWithinRange: true,
|
|
740
791
|
onChange: (_v, _t) => { },
|
|
741
792
|
};
|
|
@@ -744,8 +795,10 @@ const createNumberInputStore = (initProps) => {
|
|
|
744
795
|
valueAsNumber: parseValue(String((initProps === null || initProps === void 0 ? void 0 : initProps.value) || ''), initProps === null || initProps === void 0 ? void 0 : initProps.units, initProps === null || initProps === void 0 ? void 0 : initProps.digit).rawValue,
|
|
745
796
|
}), { increment: () => set((state) => {
|
|
746
797
|
var _a, _b;
|
|
747
|
-
|
|
748
|
-
|
|
798
|
+
if (state.readonly)
|
|
799
|
+
return {};
|
|
800
|
+
const current = parseValue(state.value, state.units, state.digit).rawValue;
|
|
801
|
+
let next = current + ((_a = state.step) !== null && _a !== void 0 ? _a : 1);
|
|
749
802
|
if (state.keepWithinRange) {
|
|
750
803
|
next = safeClamp(next, state.min, state.max);
|
|
751
804
|
}
|
|
@@ -757,8 +810,10 @@ const createNumberInputStore = (initProps) => {
|
|
|
757
810
|
};
|
|
758
811
|
}), decrement: () => set((state) => {
|
|
759
812
|
var _a, _b;
|
|
760
|
-
|
|
761
|
-
|
|
813
|
+
if (state.readonly)
|
|
814
|
+
return {};
|
|
815
|
+
const current = parseValue(state.value, state.units, state.digit).rawValue;
|
|
816
|
+
let next = current - ((_a = state.step) !== null && _a !== void 0 ? _a : 1);
|
|
762
817
|
if (state.keepWithinRange) {
|
|
763
818
|
next = safeClamp(next, state.min, state.max);
|
|
764
819
|
}
|
|
@@ -769,6 +824,8 @@ const createNumberInputStore = (initProps) => {
|
|
|
769
824
|
valueAsNumber: next,
|
|
770
825
|
};
|
|
771
826
|
}), change: (value) => set((state) => {
|
|
827
|
+
if (state.readonly)
|
|
828
|
+
return {};
|
|
772
829
|
const v = value !== null && value !== void 0 ? value : '';
|
|
773
830
|
return {
|
|
774
831
|
value: v,
|
|
@@ -805,36 +862,17 @@ function useNumberInputContext(selector) {
|
|
|
805
862
|
return useStore(store, selector);
|
|
806
863
|
}
|
|
807
864
|
|
|
808
|
-
|
|
809
|
-
var {
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
function IncrementStepper(_a) {
|
|
814
|
-
var { size = 12, children, className } = _a, props = __rest(_a, ["size", "children", "className"]);
|
|
815
|
-
const max = useNumberInputContext((s) => s.max);
|
|
816
|
-
const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber);
|
|
817
|
-
const keepWithinRange = useNumberInputContext((s) => s.keepWithinRange);
|
|
818
|
-
const increment = useNumberInputContext((s) => s.increment);
|
|
819
|
-
// TODO: add long press event
|
|
820
|
-
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-number-input-increment-stepper', className), role: "button", tabIndex: -1, "aria-disabled": keepWithinRange && valueAsNumber >= (max !== null && max !== void 0 ? max : Number.MAX_SAFE_INTEGER), onPointerDown: increment }, props, { children: children || (jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" }) })) })));
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
function DecrementStepper(_a) {
|
|
824
|
-
var { size = 12, children, className } = _a, props = __rest(_a, ["size", "children", "className"]);
|
|
825
|
-
const min = useNumberInputContext((s) => s.min);
|
|
826
|
-
const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber);
|
|
827
|
-
const keepWithinRange = useNumberInputContext((s) => s.keepWithinRange);
|
|
828
|
-
const decrement = useNumberInputContext((s) => s.decrement);
|
|
829
|
-
// TODO: add long press event
|
|
830
|
-
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-number-input-decrement-stepper', className), role: "button", tabIndex: -1, "aria-disabled": keepWithinRange && valueAsNumber <= (min !== null && min !== void 0 ? min : Number.MIN_SAFE_INTEGER), onPointerDown: decrement }, props, { children: children || (jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) })) })));
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
function InternalInput(_a) {
|
|
834
|
-
var { min, max, step, defaultValue, units, disabled, digit, selectWithFocus, blurOnEnter, keepWithinRange, clampValueOnBlur, wheel, keyboard, wrapperClassName, className, onChange, onFocus, onBlur, children: _children } = _a, props = __rest(_a, ["min", "max", "step", "defaultValue", "units", "disabled", "digit", "selectWithFocus", "blurOnEnter", "keepWithinRange", "clampValueOnBlur", "wheel", "keyboard", "wrapperClassName", "className", "onChange", "onFocus", "onBlur", "children"]);
|
|
865
|
+
const InternalInput = React.forwardRef((_a, ref) => {
|
|
866
|
+
var { disabled, readonly, selectWithFocus, blurOnEnter, clampValueOnBlur, wheel, keyboard, className, onChange, onFocus, onBlur, onKeyDown, children: _children } = _a, props = __rest(_a, ["disabled", "readonly", "selectWithFocus", "blurOnEnter", "clampValueOnBlur", "wheel", "keyboard", "className", "onChange", "onFocus", "onBlur", "onKeyDown", "children"]);
|
|
867
|
+
const elmRef = React.useRef(null);
|
|
835
868
|
const [editing, setEditing] = React.useState(false);
|
|
836
869
|
const value = useNumberInputContext((s) => s.value);
|
|
837
870
|
const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber);
|
|
871
|
+
const min = useNumberInputContext((s) => s.min);
|
|
872
|
+
const max = useNumberInputContext((s) => s.max);
|
|
873
|
+
const step = useNumberInputContext((s) => s.step);
|
|
874
|
+
const units = useNumberInputContext((s) => s.units);
|
|
875
|
+
const digit = useNumberInputContext((s) => s.digit);
|
|
838
876
|
const change = useNumberInputContext((s) => s.change);
|
|
839
877
|
const error = React.useMemo(() => {
|
|
840
878
|
if (editing)
|
|
@@ -842,11 +880,71 @@ function InternalInput(_a) {
|
|
|
842
880
|
const v = valueAsNumber;
|
|
843
881
|
return (min !== null && min !== void 0 ? min : -Infinity) > v || v > (max !== null && max !== void 0 ? max : Infinity);
|
|
844
882
|
}, [editing, max, min, valueAsNumber]);
|
|
845
|
-
|
|
883
|
+
const updateValueByEvent = React.useCallback((eventType, x) => {
|
|
884
|
+
let newValue;
|
|
885
|
+
if (eventType == 'normalized') {
|
|
886
|
+
if (!min || !max) {
|
|
887
|
+
throw new Error('required parameter: min, max'); // TODO
|
|
888
|
+
}
|
|
889
|
+
const n = normalizeValue(valueAsNumber, min, max);
|
|
890
|
+
newValue = rawValue(n + x, min, max);
|
|
891
|
+
return clamp(stepValue(newValue, step), min, max);
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
newValue = valueAsNumber + x;
|
|
895
|
+
return stepValue(newValue, step);
|
|
896
|
+
}
|
|
897
|
+
}, [max, min, step, valueAsNumber]);
|
|
898
|
+
const handleKeyDown = React.useCallback((event) => {
|
|
899
|
+
if (!keyboard || !onChange || readonly)
|
|
900
|
+
return;
|
|
901
|
+
const key = event.key;
|
|
902
|
+
if (!['ArrowUp', 'ArrowDown'].includes(key))
|
|
903
|
+
return;
|
|
904
|
+
event.preventDefault();
|
|
905
|
+
const x = key == 'ArrowUp' ? keyboard[1] : -keyboard[1];
|
|
906
|
+
const parsed = parseValue(String(updateValueByEvent(keyboard[0], x)));
|
|
907
|
+
console.log('key control');
|
|
908
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(parsed.rawValue, parsed.formatValue);
|
|
909
|
+
}, [keyboard, readonly, onChange, updateValueByEvent]);
|
|
910
|
+
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
911
|
+
if (!wheel || readonly)
|
|
912
|
+
return;
|
|
913
|
+
event.preventDefault();
|
|
914
|
+
if (!onChange || event.deltaY == 0)
|
|
915
|
+
return;
|
|
916
|
+
const x = Math.sign(event.deltaY) * -wheel[1];
|
|
917
|
+
const parsed = parseValue(String(updateValueByEvent(wheel[0], x)));
|
|
918
|
+
console.log('wheel control');
|
|
919
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(parsed.rawValue, parsed.formatValue);
|
|
920
|
+
}, { passive: false }, [wheel, readonly, onChange, updateValueByEvent]);
|
|
921
|
+
React.useImperativeHandle(ref, () => {
|
|
922
|
+
return {
|
|
923
|
+
focus() {
|
|
924
|
+
var _a;
|
|
925
|
+
(_a = elmRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
926
|
+
},
|
|
927
|
+
blur() {
|
|
928
|
+
var _a;
|
|
929
|
+
(_a = elmRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
930
|
+
},
|
|
931
|
+
};
|
|
932
|
+
}, []);
|
|
933
|
+
return (jsxRuntime.jsx("input", Object.assign({ ref: (input) => {
|
|
934
|
+
elmRef.current = input;
|
|
935
|
+
wheelRefCallback(input);
|
|
936
|
+
}, className: clsx('tremolo-number-input', className), value: value, min: min, max: max, step: step, type: "text", "aria-disabled": disabled, "aria-readonly": readonly, tabIndex: -1, "data-error": error, onChange: (event) => {
|
|
937
|
+
if (readonly)
|
|
938
|
+
return;
|
|
846
939
|
const v = event.currentTarget.value;
|
|
940
|
+
const cursorPos = event.target.selectionStart;
|
|
847
941
|
change(v);
|
|
848
942
|
const valueAsNumber = parseValue(v, units, digit).rawValue;
|
|
849
943
|
onChange === null || onChange === void 0 ? void 0 : onChange(valueAsNumber, v);
|
|
944
|
+
if (cursorPos) {
|
|
945
|
+
event.target.selectionStart = cursorPos;
|
|
946
|
+
event.target.selectionEnd = cursorPos;
|
|
947
|
+
}
|
|
850
948
|
}, onFocus: (event) => {
|
|
851
949
|
setEditing(true);
|
|
852
950
|
const v = event.currentTarget.value;
|
|
@@ -875,53 +973,190 @@ function InternalInput(_a) {
|
|
|
875
973
|
if (blurOnEnter && event.key == 'Enter') {
|
|
876
974
|
event.currentTarget.blur();
|
|
877
975
|
}
|
|
976
|
+
handleKeyDown(event);
|
|
977
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
878
978
|
} }, props)));
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
/** @category NumberInput */
|
|
982
|
+
function Stepper(_a) {
|
|
983
|
+
var { dynamic = true, children, className } = _a, props = __rest(_a, ["dynamic", "children", "className"]);
|
|
984
|
+
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-number-input-stepper', className), "data-dynamic": dynamic }, props, { children: children })));
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function useInterval(callback, delay) {
|
|
988
|
+
const savedCallback = React.useRef(callback);
|
|
989
|
+
// Remember the latest callback if it changes.
|
|
990
|
+
React.useEffect(() => {
|
|
991
|
+
savedCallback.current = callback;
|
|
992
|
+
}, [callback]);
|
|
993
|
+
// Set up the interval.
|
|
994
|
+
React.useEffect(() => {
|
|
995
|
+
// Don't schedule if no delay is specified.
|
|
996
|
+
// Note: 0 is a valid value for delay.
|
|
997
|
+
if (delay === null) {
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
const id = setInterval(() => {
|
|
1001
|
+
savedCallback.current();
|
|
1002
|
+
}, delay);
|
|
1003
|
+
return () => {
|
|
1004
|
+
clearInterval(id);
|
|
1005
|
+
};
|
|
1006
|
+
}, [delay]);
|
|
879
1007
|
}
|
|
1008
|
+
|
|
1009
|
+
function useLongPress(callback, initialDelay = 500, interval = 40) {
|
|
1010
|
+
const [pressed, setPressed] = React.useState(false);
|
|
1011
|
+
const [delay, setDelay] = React.useState(initialDelay);
|
|
1012
|
+
useInterval(() => {
|
|
1013
|
+
callback();
|
|
1014
|
+
setDelay(interval);
|
|
1015
|
+
}, pressed ? delay : null);
|
|
1016
|
+
useEventListener(globalThis.window, 'pointerup', () => {
|
|
1017
|
+
setPressed(false);
|
|
1018
|
+
setDelay(initialDelay);
|
|
1019
|
+
});
|
|
1020
|
+
return React.useCallback(() => {
|
|
1021
|
+
callback();
|
|
1022
|
+
setPressed(true);
|
|
1023
|
+
}, [callback]);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
/** @category NumberInput */
|
|
1027
|
+
function IncrementStepper(_a) {
|
|
1028
|
+
var { size = 12, children, className } = _a, props = __rest(_a, ["size", "children", "className"]);
|
|
1029
|
+
const max = useNumberInputContext((s) => s.max);
|
|
1030
|
+
const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber);
|
|
1031
|
+
const readonly = useNumberInputContext((s) => s.readonly);
|
|
1032
|
+
const keepWithinRange = useNumberInputContext((s) => s.keepWithinRange);
|
|
1033
|
+
const increment = useNumberInputContext((s) => s.increment);
|
|
1034
|
+
const press = useLongPress(increment);
|
|
1035
|
+
return (
|
|
1036
|
+
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
|
1037
|
+
jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-number-input-increment-stepper', className), role: "button", tabIndex: -1, "aria-disabled": keepWithinRange && valueAsNumber >= (max !== null && max !== void 0 ? max : Number.MAX_SAFE_INTEGER), "aria-readonly": readonly, onPointerDown: press }, props, { children: children || (jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" }) })) })));
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/** @category NumberInput */
|
|
1041
|
+
function DecrementStepper(_a) {
|
|
1042
|
+
var { size = 12, children, className } = _a, props = __rest(_a, ["size", "children", "className"]);
|
|
1043
|
+
const min = useNumberInputContext((s) => s.min);
|
|
1044
|
+
const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber);
|
|
1045
|
+
const readonly = useNumberInputContext((s) => s.readonly);
|
|
1046
|
+
const keepWithinRange = useNumberInputContext((s) => s.keepWithinRange);
|
|
1047
|
+
const decrement = useNumberInputContext((s) => s.decrement);
|
|
1048
|
+
const press = useLongPress(decrement);
|
|
1049
|
+
return (
|
|
1050
|
+
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
|
1051
|
+
jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-number-input-decrement-stepper', className), role: "button", tabIndex: -1, "aria-disabled": keepWithinRange && valueAsNumber <= (min !== null && min !== void 0 ? min : Number.MIN_SAFE_INTEGER), "aria-readonly": readonly, onPointerDown: press }, props, { children: children || (jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) })) })));
|
|
1052
|
+
}
|
|
1053
|
+
|
|
880
1054
|
/**
|
|
881
1055
|
* Input with some useful functions for entering numerical values.
|
|
882
1056
|
* @category NumberInput
|
|
883
1057
|
*/
|
|
884
|
-
|
|
885
|
-
var { value, min, max, step = 1,
|
|
886
|
-
|
|
1058
|
+
const NumberInput = React.forwardRef((_a, ref) => {
|
|
1059
|
+
var { value, min, max, step = 1, units, readonly = false, disabled = false, digit, variant = 'outline', selectWithFocus = 'none', blurOnEnter = true, keepWithinRange = true, clampValueOnBlur = true, wheel = ['raw', 1], keyboard = ['raw', 1], activeColor, wrapperClassName, className, onChange, onFocus, onBlur, children } = _a, props = __rest(_a, ["value", "min", "max", "step", "units", "readonly", "disabled", "digit", "variant", "selectWithFocus", "blurOnEnter", "keepWithinRange", "clampValueOnBlur", "wheel", "keyboard", "activeColor", "wrapperClassName", "className", "onChange", "onFocus", "onBlur", "children"]);
|
|
1060
|
+
const colors = {
|
|
1061
|
+
'--active-color': activeColor,
|
|
1062
|
+
};
|
|
1063
|
+
return (jsxRuntime.jsx(NumberInputProvider, { value: String(value), min: min, max: max, step: step, units: units, digit: digit, readonly: readonly, keepWithinRange: keepWithinRange, onChange: onChange, children: jsxRuntime.jsxs("div", { className: clsx('tremolo-number-input-wrapper', wrapperClassName),
|
|
887
1064
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
888
|
-
tabIndex: 0, "data-stepper": !!children, children: [jsxRuntime.jsx(InternalInput, Object.assign({
|
|
1065
|
+
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] }) }));
|
|
1066
|
+
});
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* @returns [refCallback, pointerDownHandler]
|
|
1070
|
+
*/
|
|
1071
|
+
function useDragWithElement({ baseElementRef, onDrag, onDragStart, onDragEnd, }) {
|
|
1072
|
+
const dragged = React.useRef(false);
|
|
1073
|
+
const normalizedX = React.useRef(0);
|
|
1074
|
+
const normalizedY = React.useRef(0);
|
|
1075
|
+
const handleDrag = React.useCallback((event) => {
|
|
1076
|
+
if (!baseElementRef.current || !dragged.current) {
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
const isTouch = event instanceof TouchEvent;
|
|
1080
|
+
if (isTouch && event.cancelable)
|
|
1081
|
+
event.preventDefault();
|
|
1082
|
+
const { left, top, right, bottom } = baseElementRef.current.getBoundingClientRect();
|
|
1083
|
+
const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
|
|
1084
|
+
const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
|
|
1085
|
+
const nx = normalizeValue(mouseX, left, right);
|
|
1086
|
+
const ny = normalizeValue(mouseY, top, bottom);
|
|
1087
|
+
normalizedX.current = nx;
|
|
1088
|
+
normalizedY.current = ny;
|
|
1089
|
+
onDrag(nx, ny);
|
|
1090
|
+
}, [onDrag, baseElementRef]);
|
|
1091
|
+
const refHandler = useRefCallbackEvent('touchmove', handleDrag, { passive: false }, [onDrag]);
|
|
1092
|
+
const pointerDownHandler = React.useCallback((event) => {
|
|
1093
|
+
dragged.current = true;
|
|
1094
|
+
handleDrag(event);
|
|
1095
|
+
onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(normalizedX.current, normalizedY.current);
|
|
1096
|
+
}, [handleDrag, onDragStart]);
|
|
1097
|
+
useEventListener(globalThis.window, 'pointermove', handleDrag);
|
|
1098
|
+
useEventListener(globalThis.window, 'pointerup', () => {
|
|
1099
|
+
if (!dragged.current)
|
|
1100
|
+
return;
|
|
1101
|
+
dragged.current = false;
|
|
1102
|
+
onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(normalizedX.current, normalizedY.current);
|
|
1103
|
+
});
|
|
1104
|
+
return [refHandler, pointerDownHandler];
|
|
889
1105
|
}
|
|
890
1106
|
|
|
891
1107
|
/** @category Piano */
|
|
892
1108
|
function KeyLabel(_a) {
|
|
893
|
-
var { label, className, wrapperClassName, wrapperStyle, __note,
|
|
1109
|
+
var { label, className, wrapperClassName, wrapperStyle, __note, __label } = _a, props = __rest(_a, ["label", "className", "wrapperClassName", "wrapperStyle", "__note", "__label"]);
|
|
1110
|
+
const noteRange = usePianoContext((s) => s.noteRange);
|
|
1111
|
+
const noteRangeArray = getNoteRangeArray(noteRange);
|
|
1112
|
+
const index = noteRangeArray.indexOf(__note);
|
|
894
1113
|
const content = label
|
|
895
|
-
? label(__note,
|
|
896
|
-
: __label && __label(__note,
|
|
1114
|
+
? label(__note, index)
|
|
1115
|
+
: __label && __label(__note, index);
|
|
897
1116
|
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 })) })));
|
|
898
1117
|
}
|
|
899
1118
|
|
|
900
1119
|
/** @category Piano */
|
|
901
1120
|
const defaultWhiteKeyWidth = 40;
|
|
902
1121
|
/** @category Piano */
|
|
903
|
-
const
|
|
904
|
-
|
|
1122
|
+
const defaultBlackKeyWidth = 26;
|
|
1123
|
+
const KeyImpl = React.forwardRef((_a, ref) => {
|
|
1124
|
+
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"]);
|
|
905
1125
|
const [played, setPlayed] = React.useState(false);
|
|
1126
|
+
const midiMax = usePianoContext((s) => s.midiMax);
|
|
1127
|
+
const fill = usePianoContext((s) => s.fill);
|
|
1128
|
+
// const glissando = usePianoContext(s => s.glissando)
|
|
1129
|
+
const onPlayNote = usePianoContext((s) => s.onPlayNote);
|
|
1130
|
+
const onStopNote = usePianoContext((s) => s.onStopNote);
|
|
1131
|
+
const label = usePianoContext((s) => s.label);
|
|
1132
|
+
const notePosition = usePianoContext((s) => s.notePosition);
|
|
1133
|
+
const position = notePosition(noteNumber);
|
|
1134
|
+
const disabled = noteNumber > midiMax;
|
|
1135
|
+
const colors = {
|
|
1136
|
+
'--bg': bg,
|
|
1137
|
+
'--color': color,
|
|
1138
|
+
'--active-bg': activeBg,
|
|
1139
|
+
'--active-color': activeColor,
|
|
1140
|
+
};
|
|
906
1141
|
React.useImperativeHandle(ref, () => {
|
|
907
1142
|
return {
|
|
908
1143
|
play() {
|
|
909
|
-
if (
|
|
1144
|
+
if (disabled)
|
|
910
1145
|
return;
|
|
911
1146
|
setPlayed(true);
|
|
912
|
-
if (
|
|
913
|
-
|
|
1147
|
+
if (onPlayNote)
|
|
1148
|
+
onPlayNote(noteNumber);
|
|
914
1149
|
},
|
|
915
1150
|
stop() {
|
|
916
1151
|
setPlayed(false);
|
|
917
|
-
if (
|
|
918
|
-
|
|
1152
|
+
if (onStopNote)
|
|
1153
|
+
onStopNote(noteNumber);
|
|
919
1154
|
},
|
|
920
1155
|
played() {
|
|
921
1156
|
return played;
|
|
922
1157
|
},
|
|
923
1158
|
};
|
|
924
|
-
}, [
|
|
1159
|
+
}, [disabled, noteNumber, onPlayNote, onStopNote, played]);
|
|
925
1160
|
let keyLabelProps = {};
|
|
926
1161
|
if (children != undefined) {
|
|
927
1162
|
React.Children.forEach(children, (child) => {
|
|
@@ -938,109 +1173,85 @@ const WhiteKey = React.forwardRef((_a, ref) => {
|
|
|
938
1173
|
}
|
|
939
1174
|
});
|
|
940
1175
|
}
|
|
941
|
-
return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
}, onPointerEnter: () => {
|
|
948
|
-
if (__disabled)
|
|
949
|
-
return;
|
|
950
|
-
if (__glissando) {
|
|
951
|
-
setPlayed(true);
|
|
952
|
-
if (__onPlayNote)
|
|
953
|
-
__onPlayNote(__note);
|
|
954
|
-
}
|
|
955
|
-
}, onPointerUp: () => {
|
|
956
|
-
if (__disabled)
|
|
957
|
-
return;
|
|
958
|
-
setPlayed(false);
|
|
959
|
-
if (__onStopNote)
|
|
960
|
-
__onStopNote(__note);
|
|
961
|
-
}, onPointerLeave: () => {
|
|
962
|
-
if (__disabled)
|
|
963
|
-
return;
|
|
964
|
-
if (__glissando) {
|
|
965
|
-
setPlayed(false);
|
|
966
|
-
if (__onStopNote)
|
|
967
|
-
__onStopNote(__note);
|
|
968
|
-
}
|
|
969
|
-
} }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
|
|
1176
|
+
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)) })));
|
|
1177
|
+
});
|
|
1178
|
+
/** @category Piano */
|
|
1179
|
+
const WhiteKey = React.forwardRef((_a, ref) => {
|
|
1180
|
+
var { width = defaultWhiteKeyWidth, height = '100%', onContextMenu = (e) => e.preventDefault() } = _a, props = __rest(_a, ["width", "height", "onContextMenu"]);
|
|
1181
|
+
return (jsxRuntime.jsx(KeyImpl, Object.assign({ ref: ref, keyType: "white", width: width, height: height, onContextMenu: onContextMenu }, props)));
|
|
970
1182
|
});
|
|
971
|
-
|
|
972
1183
|
/** @category Piano */
|
|
973
1184
|
const BlackKey = React.forwardRef((_a, ref) => {
|
|
974
|
-
var { width =
|
|
975
|
-
|
|
976
|
-
React.useImperativeHandle(ref, () => {
|
|
977
|
-
return {
|
|
978
|
-
play() {
|
|
979
|
-
if (__disabled)
|
|
980
|
-
return;
|
|
981
|
-
setPlayed(true);
|
|
982
|
-
if (__onPlayNote)
|
|
983
|
-
__onPlayNote(__note);
|
|
984
|
-
},
|
|
985
|
-
stop() {
|
|
986
|
-
setPlayed(false);
|
|
987
|
-
if (__onStopNote)
|
|
988
|
-
__onStopNote(__note);
|
|
989
|
-
},
|
|
990
|
-
played() {
|
|
991
|
-
return played;
|
|
992
|
-
},
|
|
993
|
-
};
|
|
994
|
-
}, [__disabled, __note, __onPlayNote, __onStopNote, played]);
|
|
995
|
-
let keyLabelProps = {};
|
|
996
|
-
if (children != undefined) {
|
|
997
|
-
React.Children.forEach(children, (child) => {
|
|
998
|
-
if (React.isValidElement(child)) {
|
|
999
|
-
if (child.type == KeyLabel) {
|
|
1000
|
-
keyLabelProps = child.props;
|
|
1001
|
-
}
|
|
1002
|
-
else {
|
|
1003
|
-
throw new Error('only <KeyLabel>');
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
1007
|
-
throw new Error('children is an invalid element.');
|
|
1008
|
-
}
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-black-key`, className), "aria-disabled": __disabled, "data-active": played, style: Object.assign({ left: __position, width: __fill ? __width : (width !== null && width !== void 0 ? width : __width), height: height }, style), onPointerDown: () => {
|
|
1012
|
-
if (__disabled)
|
|
1013
|
-
return;
|
|
1014
|
-
setPlayed(true);
|
|
1015
|
-
if (__onPlayNote)
|
|
1016
|
-
__onPlayNote(__note);
|
|
1017
|
-
}, onPointerEnter: () => {
|
|
1018
|
-
if (__disabled)
|
|
1019
|
-
return;
|
|
1020
|
-
if (__glissando) {
|
|
1021
|
-
setPlayed(true);
|
|
1022
|
-
if (__onPlayNote)
|
|
1023
|
-
__onPlayNote(__note);
|
|
1024
|
-
}
|
|
1025
|
-
}, onPointerUp: () => {
|
|
1026
|
-
if (__disabled)
|
|
1027
|
-
return;
|
|
1028
|
-
setPlayed(false);
|
|
1029
|
-
if (__onStopNote)
|
|
1030
|
-
__onStopNote(__note);
|
|
1031
|
-
}, onPointerLeave: () => {
|
|
1032
|
-
if (__disabled)
|
|
1033
|
-
return;
|
|
1034
|
-
if (__glissando) {
|
|
1035
|
-
setPlayed(false);
|
|
1036
|
-
if (__onStopNote)
|
|
1037
|
-
__onStopNote(__note);
|
|
1038
|
-
}
|
|
1039
|
-
} }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
|
|
1185
|
+
var { width = defaultBlackKeyWidth, height = '60%', onContextMenu = (e) => e.preventDefault() } = _a, props = __rest(_a, ["width", "height", "onContextMenu"]);
|
|
1186
|
+
return (jsxRuntime.jsx(KeyImpl, Object.assign({ ref: ref, keyType: "black", width: width, height: height, onContextMenu: onContextMenu }, props)));
|
|
1040
1187
|
});
|
|
1041
1188
|
|
|
1189
|
+
const createPianoStore = (initProps) => {
|
|
1190
|
+
const noteRange = (initProps === null || initProps === void 0 ? void 0 : initProps.noteRange) || { first: 0};
|
|
1191
|
+
const DEFAULT_PROPS = {
|
|
1192
|
+
noteRange: { first: 0, last: 127 },
|
|
1193
|
+
glissando: true,
|
|
1194
|
+
midiMax: 127,
|
|
1195
|
+
fill: false,
|
|
1196
|
+
label: () => undefined,
|
|
1197
|
+
onPlayNote: () => { },
|
|
1198
|
+
onStopNote: () => { },
|
|
1199
|
+
};
|
|
1200
|
+
return createStore()(() => (Object.assign(Object.assign(Object.assign({}, DEFAULT_PROPS), initProps), { notePosition: (note) => {
|
|
1201
|
+
const pitchPositions = {
|
|
1202
|
+
C: 0,
|
|
1203
|
+
'C#': 1,
|
|
1204
|
+
D: 1,
|
|
1205
|
+
'D#': 2,
|
|
1206
|
+
E: 2,
|
|
1207
|
+
F: 3,
|
|
1208
|
+
'F#': 4,
|
|
1209
|
+
G: 4,
|
|
1210
|
+
'G#': 5,
|
|
1211
|
+
A: 5,
|
|
1212
|
+
'A#': 6,
|
|
1213
|
+
B: 6,
|
|
1214
|
+
};
|
|
1215
|
+
const whiteNoteWidth = defaultWhiteKeyWidth;
|
|
1216
|
+
const blackNoteWidth = defaultBlackKeyWidth;
|
|
1217
|
+
const padding = 1;
|
|
1218
|
+
const targetNoteKey = noteKey(note);
|
|
1219
|
+
const firstNoteKey = noteKey(noteRange.first);
|
|
1220
|
+
const octave = Math.floor((note - noteRange.first) / 12);
|
|
1221
|
+
const octaveOffset = noteKeys.indexOf(firstNoteKey) > noteKeys.indexOf(targetNoteKey) ? 1 : 0;
|
|
1222
|
+
const w = whiteNoteWidth + padding;
|
|
1223
|
+
const pos = pitchPositions[targetNoteKey] - pitchPositions[firstNoteKey];
|
|
1224
|
+
const blackKeyOffset = isBlackKey(note) ? blackNoteWidth / 2 : 0;
|
|
1225
|
+
return pos * w + (octave + octaveOffset) * 7 * w - blackKeyOffset;
|
|
1226
|
+
} })));
|
|
1227
|
+
};
|
|
1228
|
+
const PianoContext = React.createContext(null);
|
|
1229
|
+
function PianoProvider(_a) {
|
|
1230
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
|
1231
|
+
const storeRef = React.useRef(null);
|
|
1232
|
+
if (!storeRef.current) {
|
|
1233
|
+
storeRef.current = createPianoStore(props);
|
|
1234
|
+
}
|
|
1235
|
+
React.useEffect(() => {
|
|
1236
|
+
if (storeRef.current) {
|
|
1237
|
+
storeRef.current.setState(props);
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
storeRef.current = createPianoStore(props);
|
|
1241
|
+
}
|
|
1242
|
+
}, [props]);
|
|
1243
|
+
return (jsxRuntime.jsx(PianoContext.Provider, { value: storeRef.current, children: children }));
|
|
1244
|
+
}
|
|
1245
|
+
/** @category Piano */
|
|
1246
|
+
function usePianoContext(selector) {
|
|
1247
|
+
const store = React.useContext(PianoContext);
|
|
1248
|
+
if (!store)
|
|
1249
|
+
throw new Error('Missing PianoContext.Provider in the tree');
|
|
1250
|
+
return useStore(store, selector);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1042
1253
|
/** @category Piano */
|
|
1043
|
-
const
|
|
1254
|
+
const SHORTCUTS = {
|
|
1044
1255
|
HOME_ROW: {
|
|
1045
1256
|
keys: [
|
|
1046
1257
|
'a',
|
|
@@ -1064,67 +1275,121 @@ const Shortcuts = {
|
|
|
1064
1275
|
},
|
|
1065
1276
|
};
|
|
1066
1277
|
|
|
1278
|
+
/**
|
|
1279
|
+
* Piano component
|
|
1280
|
+
*
|
|
1281
|
+
* TODO:
|
|
1282
|
+
* - add scale highlight
|
|
1283
|
+
*/
|
|
1067
1284
|
/** @category Piano */
|
|
1285
|
+
function getNoteRangeArray(noteRange) {
|
|
1286
|
+
return Array.from({ length: noteRange.last - noteRange.first + 1 }, (_, i) => i + noteRange.first);
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Customizable piano component.
|
|
1290
|
+
* @category Piano
|
|
1291
|
+
*/
|
|
1068
1292
|
function Piano(_a) {
|
|
1069
|
-
var { noteRange, glissando = true, midiMax = 127, keyboardShortcuts, fill = false, height = fill ? '100%' : 160, style, className, onPlayNote, onStopNote, label, children } = _a, props = __rest(_a, ["noteRange", "glissando", "midiMax", "keyboardShortcuts", "fill", "height", "style", "className", "onPlayNote", "onStopNote", "label", "children"]);
|
|
1293
|
+
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"]);
|
|
1070
1294
|
// -- state and ref ---
|
|
1071
|
-
const [
|
|
1072
|
-
const [whiteNoteWidth, setWhiteNoteWidth] = React.useState(-1);
|
|
1295
|
+
const [whiteNoteWidth, setWhiteNoteWidth] = React.useState(_whiteNoteWidth);
|
|
1073
1296
|
const keyRefs = React.useRef([]);
|
|
1074
1297
|
for (let i = 0; i < noteRange.last - noteRange.first + 1; i++) {
|
|
1075
1298
|
keyRefs.current[i] = React.createRef();
|
|
1076
1299
|
}
|
|
1077
1300
|
const pianoRef = React.useRef(null);
|
|
1301
|
+
const hitKeyIndex = React.useRef(-1);
|
|
1078
1302
|
// --- interpret props ---
|
|
1079
|
-
const noteRangeArray =
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1303
|
+
const noteRangeArray = getNoteRangeArray(noteRange);
|
|
1304
|
+
const whiteNotes = noteRangeArray.filter((v) => isWhiteKey(v));
|
|
1305
|
+
const blackNotes = noteRangeArray.filter((v) => isBlackKey(v));
|
|
1306
|
+
const whiteNoteCount = whiteNotes.length;
|
|
1307
|
+
const padding = 1;
|
|
1308
|
+
const staticWidth = (whiteNoteWidth + padding) * whiteNoteCount;
|
|
1309
|
+
// const blackNoteShiftPercent = 0.3
|
|
1310
|
+
// TODO: if fill setWhiteNoteWidth
|
|
1311
|
+
// useMemo
|
|
1312
|
+
// __width
|
|
1313
|
+
const childrenWithProps = React.useMemo(() => {
|
|
1314
|
+
return (children &&
|
|
1315
|
+
React.Children.map(children, (child, index) => {
|
|
1316
|
+
if (React.isValidElement(child)) {
|
|
1317
|
+
const props = { ref: keyRefs.current[index] };
|
|
1318
|
+
return React.cloneElement(child, props);
|
|
1093
1319
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
}
|
|
1098
|
-
});
|
|
1099
|
-
}
|
|
1320
|
+
return child;
|
|
1321
|
+
}));
|
|
1322
|
+
}, [children]);
|
|
1100
1323
|
// --- internal functions ---
|
|
1101
|
-
|
|
1324
|
+
const notePosition = React.useCallback((note) => {
|
|
1102
1325
|
const pitchPositions = {
|
|
1103
1326
|
C: 0,
|
|
1104
|
-
'C#':
|
|
1327
|
+
'C#': 1,
|
|
1105
1328
|
D: 1,
|
|
1106
|
-
'D#':
|
|
1329
|
+
'D#': 2,
|
|
1107
1330
|
E: 2,
|
|
1108
1331
|
F: 3,
|
|
1109
|
-
'F#':
|
|
1332
|
+
'F#': 4,
|
|
1110
1333
|
G: 4,
|
|
1111
|
-
'G#':
|
|
1334
|
+
'G#': 5,
|
|
1112
1335
|
A: 5,
|
|
1113
|
-
'A#':
|
|
1336
|
+
'A#': 6,
|
|
1114
1337
|
B: 6,
|
|
1115
1338
|
};
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
const
|
|
1121
|
-
const firstNoteName = toNoteName(noteRange.first);
|
|
1122
|
-
const pos = pitchPositions[_noteName] - pitchPositions[firstNoteName];
|
|
1339
|
+
const whiteNoteWidth = defaultWhiteKeyWidth;
|
|
1340
|
+
const blackNoteWidth = defaultBlackKeyWidth;
|
|
1341
|
+
const padding = 1;
|
|
1342
|
+
const targetNoteKey = noteKey(note);
|
|
1343
|
+
const firstNoteKey = noteKey(noteRange.first);
|
|
1123
1344
|
const octave = Math.floor((note - noteRange.first) / 12);
|
|
1124
|
-
const octaveOffset =
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1127
|
-
|
|
1345
|
+
const octaveOffset = noteKeys.indexOf(firstNoteKey) > noteKeys.indexOf(targetNoteKey) ? 1 : 0;
|
|
1346
|
+
const w = whiteNoteWidth + padding;
|
|
1347
|
+
const pos = pitchPositions[targetNoteKey] - pitchPositions[firstNoteKey];
|
|
1348
|
+
const blackKeyOffset = isBlackKey(note) ? blackNoteWidth / 2 : 0;
|
|
1349
|
+
return pos * w + (octave + octaveOffset) * 7 * w - blackKeyOffset;
|
|
1350
|
+
}, [noteRange.first]);
|
|
1351
|
+
const getHitKeyIndex = React.useCallback((x, y) => {
|
|
1352
|
+
if (!pianoRef.current)
|
|
1353
|
+
return -1;
|
|
1354
|
+
const containerHeight = pianoRef.current.clientHeight;
|
|
1355
|
+
const notes = [...blackNotes, ...whiteNotes];
|
|
1356
|
+
for (let i = 0; i < notes.length; i++) {
|
|
1357
|
+
const note = notes[i];
|
|
1358
|
+
const pos = notePosition(note);
|
|
1359
|
+
const w = isWhiteKey(note) ? defaultWhiteKeyWidth : defaultBlackKeyWidth;
|
|
1360
|
+
const h = isWhiteKey(note) ? containerHeight : containerHeight * 0.6;
|
|
1361
|
+
if (pos <= x && x < pos + w && 0 <= y && y < h) {
|
|
1362
|
+
return note;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
return -1;
|
|
1366
|
+
}, [blackNotes, notePosition, whiteNotes]);
|
|
1367
|
+
// TODO: 単一のポインターに対しては、useDragで対応可能だが、
|
|
1368
|
+
// マルチタッチに対しては、TouchEventを使う必要がありそう
|
|
1369
|
+
// 取り敢えず、シングルタッチだけ対応
|
|
1370
|
+
const onDrag = React.useCallback((perX, perY) => {
|
|
1371
|
+
var _a, _b, _c, _d;
|
|
1372
|
+
if (!pianoRef.current)
|
|
1373
|
+
return;
|
|
1374
|
+
const x = perX * staticWidth;
|
|
1375
|
+
const y = perY * pianoRef.current.clientHeight;
|
|
1376
|
+
const note = getHitKeyIndex(x, y);
|
|
1377
|
+
const index = noteRangeArray.indexOf(note);
|
|
1378
|
+
if (index == -1)
|
|
1379
|
+
return;
|
|
1380
|
+
if (hitKeyIndex.current != index) {
|
|
1381
|
+
(_b = (_a = keyRefs.current[hitKeyIndex.current]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.stop();
|
|
1382
|
+
(_d = (_c = keyRefs.current[index]) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.play();
|
|
1383
|
+
hitKeyIndex.current = index;
|
|
1384
|
+
}
|
|
1385
|
+
}, [getHitKeyIndex, noteRangeArray, staticWidth]);
|
|
1386
|
+
const onDragEnd = React.useCallback(() => {
|
|
1387
|
+
var _a, _b, _c, _d;
|
|
1388
|
+
if ((_b = (_a = keyRefs.current[hitKeyIndex.current]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.played()) {
|
|
1389
|
+
(_d = (_c = keyRefs.current[hitKeyIndex.current]) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.stop();
|
|
1390
|
+
}
|
|
1391
|
+
hitKeyIndex.current = -1;
|
|
1392
|
+
}, [keyRefs]);
|
|
1128
1393
|
// --- hooks ---
|
|
1129
1394
|
React.useEffect(() => {
|
|
1130
1395
|
if (fill && pianoRef.current) {
|
|
@@ -1133,14 +1398,22 @@ function Piano(_a) {
|
|
|
1133
1398
|
throw new Error("doesn't have a parent element.");
|
|
1134
1399
|
const resizeObserver = new ResizeObserver(() => {
|
|
1135
1400
|
const w = pianoRef.current.clientWidth;
|
|
1136
|
-
setWhiteNoteWidth(w / whiteNoteCount -
|
|
1401
|
+
setWhiteNoteWidth(w / whiteNoteCount - padding);
|
|
1137
1402
|
});
|
|
1138
1403
|
resizeObserver.observe(parent);
|
|
1404
|
+
return () => {
|
|
1405
|
+
resizeObserver.unobserve(parent);
|
|
1406
|
+
};
|
|
1139
1407
|
}
|
|
1140
1408
|
else {
|
|
1141
|
-
setWhiteNoteWidth(
|
|
1409
|
+
setWhiteNoteWidth(_whiteNoteWidth);
|
|
1142
1410
|
}
|
|
1143
|
-
}, [fill,
|
|
1411
|
+
}, [fill, _whiteNoteWidth, whiteNoteCount]);
|
|
1412
|
+
const [touchMoveRefCallback, pointerDownHandler] = useDragWithElement({
|
|
1413
|
+
baseElementRef: pianoRef,
|
|
1414
|
+
onDrag: onDrag,
|
|
1415
|
+
onDragEnd: onDragEnd,
|
|
1416
|
+
});
|
|
1144
1417
|
useEventListener(globalThis.window, 'keydown', (e) => {
|
|
1145
1418
|
var _a, _b, _c, _d;
|
|
1146
1419
|
if (e.repeat)
|
|
@@ -1165,17 +1438,14 @@ function Piano(_a) {
|
|
|
1165
1438
|
(_b = (_a = keyRefs.current[index]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.stop();
|
|
1166
1439
|
}
|
|
1167
1440
|
});
|
|
1168
|
-
return (jsxRuntime.jsx(
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
} }, props, { children: noteRangeArray.map((note, index) => {
|
|
1177
|
-
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));
|
|
1178
|
-
}) })));
|
|
1441
|
+
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) => {
|
|
1442
|
+
pianoRef.current = div;
|
|
1443
|
+
touchMoveRefCallback(div);
|
|
1444
|
+
}, className: clsx('tremolo-piano', className), style: Object.assign({ width: fill ? '100%' : staticWidth, height: height }, style), onPointerDown: (event) => {
|
|
1445
|
+
pointerDownHandler(event);
|
|
1446
|
+
onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
|
|
1447
|
+
} }, props, { children: childrenWithProps ||
|
|
1448
|
+
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))) })) }));
|
|
1179
1449
|
}
|
|
1180
1450
|
|
|
1181
1451
|
const createSliderStore = (initProps) => {
|
|
@@ -1289,7 +1559,7 @@ function Scale(_a) {
|
|
|
1289
1559
|
/** @category Slider */
|
|
1290
1560
|
const defaultThumbSize = 22;
|
|
1291
1561
|
/** @category Slider */
|
|
1292
|
-
const SliderThumb = React.forwardRef(({ size, width = defaultThumbSize, height = defaultThumbSize, children, className, style, __percent, }, ref) => {
|
|
1562
|
+
const SliderThumb = React.forwardRef(({ size, width = defaultThumbSize, height = defaultThumbSize, color, children, className, style, __percent, }, ref) => {
|
|
1293
1563
|
const wrapperRef = React.useRef(null);
|
|
1294
1564
|
const vertical = useSliderContext((s) => s.vertical);
|
|
1295
1565
|
const disabled = useSliderContext((s) => s.disabled);
|
|
@@ -1313,13 +1583,14 @@ const SliderThumb = React.forwardRef(({ size, width = defaultThumbSize, height =
|
|
|
1313
1583
|
// default slider thumb
|
|
1314
1584
|
jsxRuntime.jsx("div", { ref: wrapperRef, className: clsx('tremolo-slider-thumb', className),
|
|
1315
1585
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
1316
|
-
tabIndex: 0, "aria-disabled": disabled, "aria-readonly": readonly, style: Object.assign({ width: size !== null && size !== void 0 ? size : width, height: size !== null && size !== void 0 ? size : height }, style) })) }));
|
|
1586
|
+
tabIndex: 0, "aria-disabled": disabled, "aria-readonly": readonly, style: Object.assign(Object.assign({ '--color': color }, { width: size !== null && size !== void 0 ? size : width, height: size !== null && size !== void 0 ? size : height }), style) })) }));
|
|
1317
1587
|
});
|
|
1318
1588
|
|
|
1319
1589
|
const defaultLength = 140;
|
|
1320
1590
|
const defaultThickness = 10;
|
|
1321
1591
|
/** @category Slider */
|
|
1322
|
-
function SliderTrack(
|
|
1592
|
+
function SliderTrack(_a) {
|
|
1593
|
+
var { length = defaultLength, thickness = defaultThickness, active, inactive, children, className, style, defaultStyle = true, __thumb, __percent = 0 } = _a, props = __rest(_a, ["length", "thickness", "active", "inactive", "children", "className", "style", "defaultStyle", "__thumb", "__percent"]);
|
|
1323
1594
|
const vertical = useSliderContext((s) => s.vertical);
|
|
1324
1595
|
const reverse = useSliderContext((s) => s.reverse);
|
|
1325
1596
|
const disabled = useSliderContext((s) => s.disabled);
|
|
@@ -1328,11 +1599,11 @@ function SliderTrack({ length = defaultLength, thickness = defaultThickness, act
|
|
|
1328
1599
|
'--active': active,
|
|
1329
1600
|
'--inactive': inactive,
|
|
1330
1601
|
};
|
|
1331
|
-
return (jsxRuntime.jsxs("div", { className: clsx('tremolo-slider-track', className), "aria-disabled": disabled, "data-vertical": vertical, style: !defaultStyle
|
|
1602
|
+
return (jsxRuntime.jsxs("div", Object.assign({ className: clsx('tremolo-slider-track', className), "aria-disabled": disabled, "data-vertical": vertical, style: !defaultStyle
|
|
1332
1603
|
? style
|
|
1333
1604
|
: Object.assign(Object.assign(Object.assign({}, colors), { background: xor(vertical, reverse)
|
|
1334
1605
|
? `linear-gradient(to ${direction}, var(--inactive, #eee) ${__percent}%, var(--active, #7998ec) ${__percent}%)`
|
|
1335
|
-
: `linear-gradient(to ${direction}, var(--active, #7998ec) ${__percent}%, var(--inactive, #eee) ${__percent}%)`, borderRadius: styleHelper(thickness, '/', 2), width: !vertical ? length : thickness, height: vertical ? length : thickness }), style), children: [children, __thumb] }));
|
|
1606
|
+
: `linear-gradient(to ${direction}, var(--active, #7998ec) ${__percent}%, var(--inactive, #eee) ${__percent}%)`, borderRadius: styleHelper(thickness, '/', 2), width: !vertical ? length : thickness, height: vertical ? length : thickness }), style) }, props, { children: [children, __thumb] })));
|
|
1336
1607
|
}
|
|
1337
1608
|
|
|
1338
1609
|
/**
|
|
@@ -1340,12 +1611,11 @@ function SliderTrack({ length = defaultLength, thickness = defaultThickness, act
|
|
|
1340
1611
|
* @category Slider
|
|
1341
1612
|
*/
|
|
1342
1613
|
const Slider = React.forwardRef((_a, ref) => {
|
|
1343
|
-
var _b
|
|
1344
|
-
var { value, min, max, step = 1, skew = 1, vertical = false, reverse = false,
|
|
1614
|
+
var _b;
|
|
1615
|
+
var { value, min, max, step = 1, skew = 1, vertical = false, reverse = false, bodyNoSelect = true, wheel = ['raw', 1], keyboard = ['raw', 1], disabled = false, readonly = false, onChange, onDragStart, onDragEnd, className, style, children, onFocus, onBlur, onPointerDown, onKeyDown } = _a, props = __rest(_a, ["value", "min", "max", "step", "skew", "vertical", "reverse", "bodyNoSelect", "wheel", "keyboard", "disabled", "readonly", "onChange", "onDragStart", "onDragEnd", "className", "style", "children", "onFocus", "onBlur", "onPointerDown", "onKeyDown"]);
|
|
1345
1616
|
// -- state and ref ---
|
|
1346
1617
|
const trackElementRef = React.useRef(null);
|
|
1347
1618
|
const thumbRef = React.useRef(null);
|
|
1348
|
-
const thumbDragged = React.useRef(false);
|
|
1349
1619
|
// --- interpret props ---
|
|
1350
1620
|
const p = toFixed$1(normalizeValue(value, min, max, skew) * 100);
|
|
1351
1621
|
const rev = toFixed$1(100 - p);
|
|
@@ -1381,27 +1651,25 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1381
1651
|
});
|
|
1382
1652
|
}
|
|
1383
1653
|
// --- internal functions ---
|
|
1384
|
-
const
|
|
1385
|
-
if (!
|
|
1386
|
-
!thumbDragged.current ||
|
|
1387
|
-
!onChange ||
|
|
1388
|
-
readonly) {
|
|
1654
|
+
const onDrag = React.useCallback((nx, ny) => {
|
|
1655
|
+
if (!onChange || readonly)
|
|
1389
1656
|
return;
|
|
1390
|
-
|
|
1391
|
-
const isTouch = event instanceof TouchEvent;
|
|
1392
|
-
if (isTouch && event.cancelable)
|
|
1393
|
-
event.preventDefault();
|
|
1394
|
-
if (bodyNoSelect)
|
|
1395
|
-
addNoSelect();
|
|
1396
|
-
const { left: x1, top: y1, right: x2, bottom: y2, } = trackElementRef.current.getBoundingClientRect();
|
|
1397
|
-
const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
|
|
1398
|
-
const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
|
|
1399
|
-
const n = vertical
|
|
1400
|
-
? normalizeValue(mouseY, y1, y2)
|
|
1401
|
-
: normalizeValue(mouseX, x1, x2);
|
|
1657
|
+
const n = vertical ? ny : nx;
|
|
1402
1658
|
const v = rawValue(displayReversed ? 1 - n : n, min, max, skew);
|
|
1403
|
-
|
|
1404
|
-
|
|
1659
|
+
const v2 = clamp(stepValue(v, step), min, max);
|
|
1660
|
+
onChange(v2);
|
|
1661
|
+
}, [displayReversed, max, min, onChange, readonly, skew, step, vertical]);
|
|
1662
|
+
const updateValueByEvent = React.useCallback((eventType, x) => {
|
|
1663
|
+
let newValue;
|
|
1664
|
+
if (eventType == 'normalized') {
|
|
1665
|
+
const n = normalizeValue(value, min, max, skew);
|
|
1666
|
+
newValue = rawValue(n + x, min, max, skew);
|
|
1667
|
+
}
|
|
1668
|
+
else {
|
|
1669
|
+
newValue = value + x;
|
|
1670
|
+
}
|
|
1671
|
+
return clamp(stepValue(newValue, step), min, max);
|
|
1672
|
+
}, [max, min, skew, step, value]);
|
|
1405
1673
|
const handleKeyDown = React.useCallback((event) => {
|
|
1406
1674
|
if (!keyboard || !onChange || readonly)
|
|
1407
1675
|
return;
|
|
@@ -1411,19 +1679,30 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1411
1679
|
let x = key == 'ArrowRight' || key == 'ArrowUp' ? keyboard[1] : -keyboard[1];
|
|
1412
1680
|
if (reverse)
|
|
1413
1681
|
x *= -1;
|
|
1414
|
-
|
|
1415
|
-
if (keyboard[0] == 'normalized') {
|
|
1416
|
-
const n = normalizeValue(value, min, max, skew);
|
|
1417
|
-
v = rawValue(n + x, min, max, skew);
|
|
1418
|
-
}
|
|
1419
|
-
else {
|
|
1420
|
-
v = value + x;
|
|
1421
|
-
}
|
|
1422
|
-
onChange(clamp(stepValue(v, step), min, max));
|
|
1682
|
+
onChange(updateValueByEvent(keyboard[0], x));
|
|
1423
1683
|
}
|
|
1424
|
-
}, [
|
|
1684
|
+
}, [keyboard, onChange, readonly, reverse, updateValueByEvent]);
|
|
1425
1685
|
// --- hooks ---
|
|
1426
|
-
const touchMoveRefCallback =
|
|
1686
|
+
const [touchMoveRefCallback, pointerDownHandler] = useDragWithElement({
|
|
1687
|
+
baseElementRef: trackElementRef,
|
|
1688
|
+
onDrag: onDrag,
|
|
1689
|
+
onDragStart: (nx, ny) => {
|
|
1690
|
+
var _a;
|
|
1691
|
+
if (readonly)
|
|
1692
|
+
return;
|
|
1693
|
+
if (bodyNoSelect)
|
|
1694
|
+
addNoSelect();
|
|
1695
|
+
(_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1696
|
+
onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(clamp(stepValue(rawValue(vertical ? ny : nx, min, max, skew), step), min, max));
|
|
1697
|
+
},
|
|
1698
|
+
onDragEnd: (nx, ny) => {
|
|
1699
|
+
if (readonly)
|
|
1700
|
+
return;
|
|
1701
|
+
if (bodyNoSelect)
|
|
1702
|
+
removeNoSelect();
|
|
1703
|
+
onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(clamp(stepValue(rawValue(vertical ? ny : nx, min, max, skew), step), min, max));
|
|
1704
|
+
},
|
|
1705
|
+
});
|
|
1427
1706
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
1428
1707
|
if (!wheel || !onChange || readonly)
|
|
1429
1708
|
return;
|
|
@@ -1439,26 +1718,10 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1439
1718
|
}
|
|
1440
1719
|
if (vertical && reverse)
|
|
1441
1720
|
x *= -1;
|
|
1442
|
-
|
|
1443
|
-
if (wheel[0] == 'normalized') {
|
|
1444
|
-
const n = normalizeValue(value, min, max, skew);
|
|
1445
|
-
v = rawValue(n + x, min, max, skew);
|
|
1446
|
-
}
|
|
1447
|
-
else {
|
|
1448
|
-
v = value + x;
|
|
1449
|
-
}
|
|
1450
|
-
onChange(clamp(stepValue(v, step), min, max));
|
|
1721
|
+
onChange(updateValueByEvent(wheel[0], x));
|
|
1451
1722
|
}, {
|
|
1452
1723
|
passive: false,
|
|
1453
|
-
}, [wheel,
|
|
1454
|
-
useEventListener(globalThis.window, 'mousemove', (event) => {
|
|
1455
|
-
handleValue(event);
|
|
1456
|
-
});
|
|
1457
|
-
useEventListener(globalThis.window, 'mouseup', () => {
|
|
1458
|
-
thumbDragged.current = false;
|
|
1459
|
-
if (bodyNoSelect)
|
|
1460
|
-
removeNoSelect();
|
|
1461
|
-
});
|
|
1724
|
+
}, [wheel, vertical, readonly, onChange, updateValueByEvent]);
|
|
1462
1725
|
React.useImperativeHandle(ref, () => {
|
|
1463
1726
|
return {
|
|
1464
1727
|
focus() {
|
|
@@ -1475,9 +1738,20 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1475
1738
|
wheelRefCallback(div);
|
|
1476
1739
|
touchMoveRefCallback(div);
|
|
1477
1740
|
}, 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) => {
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
}, onKeyDown:
|
|
1741
|
+
pointerDownHandler(event);
|
|
1742
|
+
onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
|
|
1743
|
+
}, onKeyDown: (event) => {
|
|
1744
|
+
handleKeyDown(event);
|
|
1745
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
1746
|
+
}, onFocus: (event) => {
|
|
1747
|
+
var _a;
|
|
1748
|
+
(_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1749
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
1750
|
+
}, onBlur: (event) => {
|
|
1751
|
+
var _a;
|
|
1752
|
+
(_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
1753
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
1754
|
+
} }, props, { children: jsxRuntime.jsxs("div", { style: {
|
|
1481
1755
|
display: 'flex',
|
|
1482
1756
|
flexDirection: vertical ? 'row' : 'column',
|
|
1483
1757
|
width: !vertical ? '100%' : undefined,
|
|
@@ -1496,12 +1770,14 @@ function WheelObserver(props) {
|
|
|
1496
1770
|
}
|
|
1497
1771
|
|
|
1498
1772
|
/** @category XYPad */
|
|
1499
|
-
function XYPadArea(
|
|
1500
|
-
|
|
1773
|
+
function XYPadArea(_a) {
|
|
1774
|
+
var { width = 120, height = 120, color, children, className, style, __thumb } = _a, props = __rest(_a, ["width", "height", "color", "children", "className", "style", "__thumb"]);
|
|
1775
|
+
return (jsxRuntime.jsxs("div", Object.assign({ className: clsx('tremolo-xy-pad-area', className), style: Object.assign(Object.assign({ '--color': color }, { width: width, height: height }), style) }, props, { children: [children, __thumb] })));
|
|
1501
1776
|
}
|
|
1502
1777
|
|
|
1503
1778
|
/** @category XYPad */
|
|
1504
|
-
const XYPadThumb = React.forwardRef((
|
|
1779
|
+
const XYPadThumb = React.forwardRef((_a, ref) => {
|
|
1780
|
+
var { size, width = 22, height = 22, color, children, wrapperClassName, wrapperStyle, className, style, __disabled, __css } = _a, props = __rest(_a, ["size", "width", "height", "color", "children", "wrapperClassName", "wrapperStyle", "className", "style", "__disabled", "__css"]);
|
|
1505
1781
|
const wrapperRef = React.useRef(null);
|
|
1506
1782
|
React.useImperativeHandle(ref, () => {
|
|
1507
1783
|
return {
|
|
@@ -1515,11 +1791,11 @@ const XYPadThumb = React.forwardRef(({ size, width = 22, height = 22, children,
|
|
|
1515
1791
|
},
|
|
1516
1792
|
};
|
|
1517
1793
|
}, []);
|
|
1518
|
-
return (jsxRuntime.jsx("div", { className: clsx('tremolo-xy-pad-thumb-wrapper', wrapperClassName), style: Object.assign(Object.assign({}, __css), wrapperStyle), children: children ? (children) : (
|
|
1794
|
+
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-xy-pad-thumb-wrapper', wrapperClassName), style: Object.assign(Object.assign({}, __css), wrapperStyle) }, props, { children: children ? (children) : (
|
|
1519
1795
|
// default thumb
|
|
1520
1796
|
jsxRuntime.jsx("div", { ref: wrapperRef, className: clsx('tremolo-xy-pad-thumb', className),
|
|
1521
1797
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
1522
|
-
tabIndex: 0, "aria-disabled": __disabled, style: Object.assign({ width: size !== null && size !== void 0 ? size : width, height: size !== null && size !== void 0 ? size : height }, style) })) }));
|
|
1798
|
+
tabIndex: 0, "aria-disabled": __disabled, style: Object.assign(Object.assign({ '--color': color }, { width: size !== null && size !== void 0 ? size : width, height: size !== null && size !== void 0 ? size : height }), style) })) })));
|
|
1523
1799
|
});
|
|
1524
1800
|
|
|
1525
1801
|
const defaultValueOptions = {
|
|
@@ -1534,8 +1810,8 @@ const defaultValueOptions = {
|
|
|
1534
1810
|
* @category XYPad
|
|
1535
1811
|
*/
|
|
1536
1812
|
const XYPad = React.forwardRef((_a, ref) => {
|
|
1537
|
-
var _b
|
|
1538
|
-
var { x: _x, y: _y, className, style, bodyNoSelect = true, disabled = false, readonly = false, onChange, children } = _a, props = __rest(_a, ["x", "y", "className", "style", "bodyNoSelect", "disabled", "readonly", "onChange", "children"]);
|
|
1813
|
+
var _b;
|
|
1814
|
+
var { x: _x, y: _y, className, style, bodyNoSelect = true, disabled = false, readonly = false, onChange, onDragStart, onDragEnd, onPointerDown, onKeyDown, onFocus, onBlur, children } = _a, props = __rest(_a, ["x", "y", "className", "style", "bodyNoSelect", "disabled", "readonly", "onChange", "onDragStart", "onDragEnd", "onPointerDown", "onKeyDown", "onFocus", "onBlur", "children"]);
|
|
1539
1815
|
const x = React.useMemo(() => {
|
|
1540
1816
|
return Object.assign(Object.assign({}, defaultValueOptions), _x);
|
|
1541
1817
|
}, [_x]);
|
|
@@ -1545,13 +1821,13 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1545
1821
|
// -- state and ref ---
|
|
1546
1822
|
const areaElementRef = React.useRef(null);
|
|
1547
1823
|
const thumbRef = React.useRef(null);
|
|
1548
|
-
const thumbDragged = React.useRef(false);
|
|
1549
1824
|
// --- interpret props ---
|
|
1550
1825
|
const nx = normalizeValue(x.value, x.min, x.max, x.skew);
|
|
1551
1826
|
const ny = normalizeValue(y.value, y.min, y.max, y.skew);
|
|
1552
1827
|
const percentX = toFixed$1((x.reverse ? 1 - nx : nx) * 100);
|
|
1553
1828
|
const percentY = toFixed$1((y.reverse ? 1 - ny : ny) * 100);
|
|
1554
|
-
let areaProps = {}
|
|
1829
|
+
let areaProps = {};
|
|
1830
|
+
let thumbProps = {};
|
|
1555
1831
|
if (children != undefined) {
|
|
1556
1832
|
React.Children.forEach(children, (child) => {
|
|
1557
1833
|
if (React.isValidElement(child)) {
|
|
@@ -1571,28 +1847,39 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1571
1847
|
});
|
|
1572
1848
|
}
|
|
1573
1849
|
// --- internal functions ---
|
|
1574
|
-
const
|
|
1575
|
-
if (!
|
|
1576
|
-
!thumbDragged.current ||
|
|
1577
|
-
!onChange ||
|
|
1578
|
-
readonly)
|
|
1850
|
+
const onDrag = React.useCallback((nx, ny) => {
|
|
1851
|
+
if (!onChange || readonly)
|
|
1579
1852
|
return;
|
|
1580
|
-
const isTouch = event instanceof TouchEvent;
|
|
1581
|
-
if (isTouch && event.cancelable)
|
|
1582
|
-
event.preventDefault();
|
|
1583
|
-
if (bodyNoSelect)
|
|
1584
|
-
addNoSelect();
|
|
1585
|
-
const { left: x1, top: y1, right: x2, bottom: y2, } = areaElementRef.current.getBoundingClientRect();
|
|
1586
|
-
const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
|
|
1587
|
-
const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
|
|
1588
|
-
const nx = normalizeValue(mouseX, x1, x2);
|
|
1589
|
-
const ny = normalizeValue(mouseY, y1, y2);
|
|
1590
1853
|
const vx = rawValue(x.reverse ? 1 - nx : nx, x.min, x.max, x.skew);
|
|
1591
1854
|
const vy = rawValue(y.reverse ? 1 - ny : ny, y.min, y.max, y.skew);
|
|
1592
1855
|
const newX = clamp(stepValue(vx, x.step), x.min, x.max);
|
|
1593
1856
|
const newY = clamp(stepValue(vy, y.step), y.min, y.max);
|
|
1594
1857
|
onChange(newX, newY);
|
|
1595
|
-
}
|
|
1858
|
+
}, [
|
|
1859
|
+
onChange,
|
|
1860
|
+
readonly,
|
|
1861
|
+
x.max,
|
|
1862
|
+
x.min,
|
|
1863
|
+
x.reverse,
|
|
1864
|
+
x.skew,
|
|
1865
|
+
x.step,
|
|
1866
|
+
y.max,
|
|
1867
|
+
y.min,
|
|
1868
|
+
y.reverse,
|
|
1869
|
+
y.skew,
|
|
1870
|
+
y.step,
|
|
1871
|
+
]);
|
|
1872
|
+
const updateValueByEvent = React.useCallback((eventType, target, x) => {
|
|
1873
|
+
let v;
|
|
1874
|
+
if (eventType == 'normalized') {
|
|
1875
|
+
const n = normalizeValue(target.value, target.min, target.max, target.skew);
|
|
1876
|
+
v = rawValue(n + x, target.min, target.max, target.skew);
|
|
1877
|
+
}
|
|
1878
|
+
else {
|
|
1879
|
+
v = target.value + x;
|
|
1880
|
+
}
|
|
1881
|
+
return clamp(stepValue(v, target.step), target.min, target.max);
|
|
1882
|
+
}, []);
|
|
1596
1883
|
const handleKeyDown = React.useCallback((event) => {
|
|
1597
1884
|
if (!onChange || readonly)
|
|
1598
1885
|
return;
|
|
@@ -1608,15 +1895,7 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1608
1895
|
delta *= -1;
|
|
1609
1896
|
if (target.reverse)
|
|
1610
1897
|
delta *= -1;
|
|
1611
|
-
|
|
1612
|
-
if (target.keyboard[0] == 'normalized') {
|
|
1613
|
-
const n = normalizeValue(target.value, target.min, target.max, target.skew);
|
|
1614
|
-
v = rawValue(n + delta, target.min, target.max, target.skew);
|
|
1615
|
-
}
|
|
1616
|
-
else {
|
|
1617
|
-
v = target.value + delta;
|
|
1618
|
-
}
|
|
1619
|
-
const newValue = clamp(stepValue(v, target.step), target.min, target.max);
|
|
1898
|
+
const newValue = updateValueByEvent(target.keyboard[0], target, delta);
|
|
1620
1899
|
if (isHorizontal) {
|
|
1621
1900
|
onChange(newValue, y.value);
|
|
1622
1901
|
}
|
|
@@ -1624,9 +1903,32 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1624
1903
|
onChange(x.value, newValue);
|
|
1625
1904
|
}
|
|
1626
1905
|
}
|
|
1627
|
-
}, [x, y,
|
|
1906
|
+
}, [onChange, readonly, x, y, updateValueByEvent]);
|
|
1628
1907
|
// --- hooks ---
|
|
1629
|
-
const touchMoveRefCallback =
|
|
1908
|
+
const [touchMoveRefCallback, pointerDownHandler] = useDragWithElement({
|
|
1909
|
+
baseElementRef: areaElementRef,
|
|
1910
|
+
onDrag: onDrag,
|
|
1911
|
+
onDragStart: (nx, ny) => {
|
|
1912
|
+
var _a;
|
|
1913
|
+
if (readonly)
|
|
1914
|
+
return;
|
|
1915
|
+
if (bodyNoSelect)
|
|
1916
|
+
addNoSelect();
|
|
1917
|
+
(_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1918
|
+
const valueX = clamp(stepValue(rawValue(nx, x.min, x.max, x.skew), x.step), x.min, x.max);
|
|
1919
|
+
const valueY = clamp(stepValue(rawValue(ny, y.min, y.max, y.skew), y.step), y.min, y.max);
|
|
1920
|
+
onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(valueX, valueY);
|
|
1921
|
+
},
|
|
1922
|
+
onDragEnd: (nx, ny) => {
|
|
1923
|
+
if (readonly)
|
|
1924
|
+
return;
|
|
1925
|
+
if (bodyNoSelect)
|
|
1926
|
+
removeNoSelect();
|
|
1927
|
+
const valueX = clamp(stepValue(rawValue(nx, x.min, x.max, x.skew), x.step), x.min, x.max);
|
|
1928
|
+
const valueY = clamp(stepValue(rawValue(ny, y.min, y.max, y.skew), y.step), y.min, y.max);
|
|
1929
|
+
onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(valueX, valueY);
|
|
1930
|
+
},
|
|
1931
|
+
});
|
|
1630
1932
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
1631
1933
|
if (!onChange || readonly)
|
|
1632
1934
|
return;
|
|
@@ -1639,15 +1941,7 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1639
1941
|
delta *= -1;
|
|
1640
1942
|
if (target.reverse)
|
|
1641
1943
|
delta *= -1;
|
|
1642
|
-
|
|
1643
|
-
if (target.wheel[0] == 'normalized') {
|
|
1644
|
-
const n = normalizeValue(target.value, target.min, target.max, target.skew);
|
|
1645
|
-
v = rawValue(n + delta, target.min, target.max, target.skew);
|
|
1646
|
-
}
|
|
1647
|
-
else {
|
|
1648
|
-
v = target.value + delta;
|
|
1649
|
-
}
|
|
1650
|
-
const newValue = clamp(stepValue(v, target.step), target.min, target.max);
|
|
1944
|
+
const newValue = updateValueByEvent(target.wheel[0], target, delta);
|
|
1651
1945
|
if (event.shiftKey) {
|
|
1652
1946
|
onChange(newValue, y.value);
|
|
1653
1947
|
}
|
|
@@ -1656,15 +1950,7 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1656
1950
|
}
|
|
1657
1951
|
}, {
|
|
1658
1952
|
passive: false,
|
|
1659
|
-
}, [x, y]);
|
|
1660
|
-
useEventListener(globalThis.window, 'mousemove', (event) => {
|
|
1661
|
-
handleValue(event);
|
|
1662
|
-
});
|
|
1663
|
-
useEventListener(globalThis.window, 'mouseup', () => {
|
|
1664
|
-
thumbDragged.current = false;
|
|
1665
|
-
if (bodyNoSelect)
|
|
1666
|
-
removeNoSelect();
|
|
1667
|
-
});
|
|
1953
|
+
}, [x, y, onChange, readonly, updateValueByEvent]);
|
|
1668
1954
|
React.useImperativeHandle(ref, () => {
|
|
1669
1955
|
return {
|
|
1670
1956
|
focus() {
|
|
@@ -1683,14 +1969,38 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1683
1969
|
wheelRefCallback(div);
|
|
1684
1970
|
touchMoveRefCallback(div);
|
|
1685
1971
|
}, 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) => {
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
}, onKeyDown:
|
|
1972
|
+
pointerDownHandler(event);
|
|
1973
|
+
onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
|
|
1974
|
+
}, onKeyDown: (event) => {
|
|
1975
|
+
handleKeyDown(event);
|
|
1976
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
1977
|
+
}, onFocus: (event) => {
|
|
1978
|
+
var _a;
|
|
1979
|
+
(_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1980
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
1981
|
+
}, onBlur: (event) => {
|
|
1982
|
+
var _a;
|
|
1983
|
+
(_a = thumbRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
1984
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
1985
|
+
} }, props, { children: jsxRuntime.jsx("div", { className: "tremolo-xy-pad-area-wrapper", ref: areaElementRef, children: jsxRuntime.jsx(XYPadArea, Object.assign({ __thumb: jsxRuntime.jsx(XYPadThumb, Object.assign({ ref: thumbRef, __disabled: disabled, __css: {
|
|
1689
1986
|
top: `${percentY}%`,
|
|
1690
1987
|
left: `${percentX}%`,
|
|
1691
1988
|
} }, thumbProps)) }, areaProps)) }) })));
|
|
1692
1989
|
});
|
|
1693
1990
|
|
|
1991
|
+
const useAnimationFrame = (callback = () => { }, deps = []) => {
|
|
1992
|
+
const reqIdRef = React.useRef(-1);
|
|
1993
|
+
const loop = React.useCallback(() => {
|
|
1994
|
+
reqIdRef.current = requestAnimationFrame(loop);
|
|
1995
|
+
callback();
|
|
1996
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1997
|
+
}, [callback, ...deps]);
|
|
1998
|
+
React.useEffect(() => {
|
|
1999
|
+
reqIdRef.current = requestAnimationFrame(loop);
|
|
2000
|
+
return () => cancelAnimationFrame(reqIdRef.current);
|
|
2001
|
+
}, [loop]);
|
|
2002
|
+
};
|
|
2003
|
+
|
|
1694
2004
|
exports.AnimationCanvas = AnimationCanvas;
|
|
1695
2005
|
exports.AnimationKnob = AnimationKnob;
|
|
1696
2006
|
exports.BlackKey = BlackKey;
|
|
@@ -1701,9 +2011,9 @@ exports.KeyLabel = KeyLabel;
|
|
|
1701
2011
|
exports.Knob = Knob;
|
|
1702
2012
|
exports.NumberInput = NumberInput;
|
|
1703
2013
|
exports.Piano = Piano;
|
|
2014
|
+
exports.SHORTCUTS = SHORTCUTS;
|
|
1704
2015
|
exports.Scale = Scale;
|
|
1705
2016
|
exports.ScaleOption = ScaleOption;
|
|
1706
|
-
exports.Shortcuts = Shortcuts;
|
|
1707
2017
|
exports.Slider = Slider;
|
|
1708
2018
|
exports.SliderThumb = SliderThumb;
|
|
1709
2019
|
exports.SliderTrack = SliderTrack;
|
|
@@ -1713,5 +2023,11 @@ exports.WhiteKey = WhiteKey;
|
|
|
1713
2023
|
exports.XYPad = XYPad;
|
|
1714
2024
|
exports.XYPadArea = XYPadArea;
|
|
1715
2025
|
exports.XYPadThumb = XYPadThumb;
|
|
2026
|
+
exports.getNoteRangeArray = getNoteRangeArray;
|
|
2027
|
+
exports.useAnimationFrame = useAnimationFrame;
|
|
2028
|
+
exports.useDrag = useDrag;
|
|
2029
|
+
exports.useEventListener = useEventListener;
|
|
2030
|
+
exports.useInterval = useInterval;
|
|
2031
|
+
exports.useLongPress = useLongPress;
|
|
1716
2032
|
exports.useSliderContext = useSliderContext;
|
|
1717
2033
|
//# sourceMappingURL=index.js.map
|