@tremolo-ui/react 0.0.8 → 0.0.10
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 +439 -275
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts +9 -4
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/cjs/types/components/AnimationKnob/index.d.ts +2 -0
- package/dist/cjs/types/components/AnimationKnob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/DragObserver/index.d.ts +3 -1
- package/dist/cjs/types/components/DragObserver/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Knob/index.d.ts +2 -0
- package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts +7 -0
- package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts +7 -0
- package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/Stepper.d.ts +8 -0
- package/dist/cjs/types/components/NumberInput/Stepper.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/context.d.ts +27 -0
- package/dist/cjs/types/components/NumberInput/context.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/index.d.ts +31 -16
- package/dist/cjs/types/components/NumberInput/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/BlackKey.d.ts +1 -0
- package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts +2 -0
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts +3 -0
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/index.d.ts +6 -4
- package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/key.d.ts +8 -2
- package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +2 -0
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Scale.d.ts +2 -0
- package/dist/cjs/types/components/Slider/Scale.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/ScaleOption.d.ts +2 -0
- package/dist/cjs/types/components/Slider/ScaleOption.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Thumb.d.ts +4 -0
- package/dist/cjs/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Track.d.ts +6 -1
- package/dist/cjs/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/context.d.ts +15 -12
- package/dist/cjs/types/components/Slider/context.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/index.d.ts +8 -5
- package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
- package/dist/cjs/types/components/WheelObserver/index.d.ts +1 -0
- package/dist/cjs/types/components/WheelObserver/index.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/Area.d.ts +2 -0
- package/dist/cjs/types/components/XYPad/Area.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/Thumb.d.ts +3 -0
- package/dist/cjs/types/components/XYPad/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/index.d.ts +4 -0
- package/dist/cjs/types/components/XYPad/index.d.ts.map +1 -1
- package/dist/cjs/types/hooks/useAnimationFrame.d.ts +3 -0
- package/dist/cjs/types/hooks/useAnimationFrame.d.ts.map +1 -0
- package/dist/cjs/types/hooks/useDrag.d.ts +15 -0
- package/dist/cjs/types/hooks/useDrag.d.ts.map +1 -0
- package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts +1 -4
- package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts.map +1 -1
- package/dist/esm/index.js +437 -266
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/AnimationCanvas/index.d.ts +9 -4
- package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/esm/types/components/AnimationKnob/index.d.ts +2 -0
- package/dist/esm/types/components/AnimationKnob/index.d.ts.map +1 -1
- package/dist/esm/types/components/DragObserver/index.d.ts +3 -1
- package/dist/esm/types/components/DragObserver/index.d.ts.map +1 -1
- package/dist/esm/types/components/Knob/index.d.ts +2 -0
- package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts +7 -0
- package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts +7 -0
- package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/Stepper.d.ts +8 -0
- package/dist/esm/types/components/NumberInput/Stepper.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/context.d.ts +27 -0
- package/dist/esm/types/components/NumberInput/context.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/index.d.ts +31 -16
- package/dist/esm/types/components/NumberInput/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/BlackKey.d.ts +1 -0
- package/dist/esm/types/components/Piano/BlackKey.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/KeyLabel.d.ts +2 -0
- package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/WhiteKey.d.ts +3 -0
- package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/index.d.ts +6 -4
- package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/key.d.ts +8 -2
- package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +2 -0
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Scale.d.ts +2 -0
- package/dist/esm/types/components/Slider/Scale.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/ScaleOption.d.ts +2 -0
- package/dist/esm/types/components/Slider/ScaleOption.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Thumb.d.ts +4 -0
- package/dist/esm/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Track.d.ts +6 -1
- package/dist/esm/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/context.d.ts +15 -12
- package/dist/esm/types/components/Slider/context.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/index.d.ts +8 -5
- package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
- package/dist/esm/types/components/WheelObserver/index.d.ts +1 -0
- package/dist/esm/types/components/WheelObserver/index.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/Area.d.ts +2 -0
- package/dist/esm/types/components/XYPad/Area.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/Thumb.d.ts +3 -0
- package/dist/esm/types/components/XYPad/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/index.d.ts +4 -0
- package/dist/esm/types/components/XYPad/index.d.ts.map +1 -1
- package/dist/esm/types/hooks/useAnimationFrame.d.ts +3 -0
- package/dist/esm/types/hooks/useAnimationFrame.d.ts.map +1 -0
- package/dist/esm/types/hooks/useDrag.d.ts +15 -0
- package/dist/esm/types/hooks/useDrag.d.ts.map +1 -0
- package/dist/esm/types/hooks/useRefCallbackEvent.d.ts +1 -4
- package/dist/esm/types/hooks/useRefCallbackEvent.d.ts.map +1 -1
- package/dist/styles/index.css +110 -13
- package/package.json +8 -5
- package/src/components/AnimationCanvas/index.tsx +13 -4
- package/src/components/AnimationKnob/index.tsx +24 -42
- package/src/components/DragObserver/index.tsx +14 -52
- package/src/components/Knob/index.tsx +23 -40
- package/src/components/NumberInput/DecrementStepper.tsx +52 -0
- package/src/components/NumberInput/IncrementStepper.tsx +52 -0
- package/src/components/NumberInput/Stepper.tsx +25 -0
- package/src/components/NumberInput/context.tsx +150 -0
- package/src/components/NumberInput/index.css +102 -13
- package/src/components/NumberInput/index.tsx +164 -55
- package/src/components/Piano/BlackKey.tsx +15 -11
- package/src/components/Piano/KeyLabel.tsx +2 -0
- package/src/components/Piano/WhiteKey.tsx +17 -11
- package/src/components/Piano/index.tsx +16 -14
- package/src/components/Piano/key.ts +8 -2
- package/src/components/Piano/keyboardShortcuts.ts +2 -0
- package/src/components/Slider/Scale.tsx +8 -6
- package/src/components/Slider/ScaleOption.tsx +8 -6
- package/src/components/Slider/Thumb.tsx +7 -3
- package/src/components/Slider/Track.tsx +27 -15
- package/src/components/Slider/context.tsx +65 -51
- package/src/components/Slider/index.css +8 -0
- package/src/components/Slider/index.tsx +19 -10
- package/src/components/WheelObserver/index.tsx +1 -0
- package/src/components/XYPad/Area.tsx +2 -0
- package/src/components/XYPad/Thumb.tsx +3 -0
- package/src/components/XYPad/index.tsx +6 -2
- package/src/hooks/useAnimationFrame.ts +18 -0
- package/src/hooks/useDrag.ts +92 -0
- package/src/hooks/useRefCallbackEvent.ts +4 -7
package/dist/cjs/index.js
CHANGED
|
@@ -86,7 +86,7 @@ function AnimationCanvas(_a) {
|
|
|
86
86
|
const context = canvas.getContext('2d', options);
|
|
87
87
|
if (!context)
|
|
88
88
|
throw new Error('Cannot get canvas context.');
|
|
89
|
-
const dpr = window.devicePixelRatio;
|
|
89
|
+
const dpr = globalThis.window.devicePixelRatio;
|
|
90
90
|
if (relativeSize) {
|
|
91
91
|
const parent = canvas.parentElement;
|
|
92
92
|
if (!parent)
|
|
@@ -99,6 +99,7 @@ function AnimationCanvas(_a) {
|
|
|
99
99
|
// https://zenn.dev/megeton/articles/be1c677e174c84#%E6%A0%B9%E6%9C%AC%E7%9A%84%E3%81%AB-resizeobserver-loop-limit-exceeded-%E3%81%8C%E5%87%BA%E3%82%8B%E5%95%8F%E9%A1%8C%E3%81%AB%E5%90%91%E3%81%8D%E5%90%88%E3%81%86
|
|
100
100
|
for (const entry of entries) {
|
|
101
101
|
// Prevents loss of some context when the canvas is resized
|
|
102
|
+
// TODO: saving scale and translate
|
|
102
103
|
const contextMemo = {};
|
|
103
104
|
for (const prop of drawingState) {
|
|
104
105
|
contextMemo[prop] = context[prop];
|
|
@@ -191,15 +192,15 @@ function stepValue(value, step) {
|
|
|
191
192
|
throw new RangeError('requirements: step > 0');
|
|
192
193
|
const quotient = Math.floor(value / step);
|
|
193
194
|
const decimalDigits = (_a = decimalPart$1(step)) === null || _a === void 0 ? void 0 : _a.length;
|
|
194
|
-
const v = toFixed$
|
|
195
|
-
const next = toFixed$
|
|
195
|
+
const v = toFixed$1(quotient * step, decimalDigits);
|
|
196
|
+
const next = toFixed$1((quotient + 1) * step, decimalDigits);
|
|
196
197
|
return Math.abs(value - v) < Math.abs(value - next) ? v : next;
|
|
197
198
|
}
|
|
198
199
|
/**
|
|
199
200
|
*
|
|
200
201
|
* @category Math
|
|
201
202
|
*/
|
|
202
|
-
function toFixed$
|
|
203
|
+
function toFixed$1(x, fractionDigits) {
|
|
203
204
|
return Number(x.toFixed(fractionDigits));
|
|
204
205
|
}
|
|
205
206
|
/**
|
|
@@ -286,7 +287,7 @@ function parseNoteName(noteName) {
|
|
|
286
287
|
};
|
|
287
288
|
}
|
|
288
289
|
/**
|
|
289
|
-
*
|
|
290
|
+
* Convert noteName to noteNumber
|
|
290
291
|
* @category MIDI
|
|
291
292
|
*/
|
|
292
293
|
function noteNumber(noteName) {
|
|
@@ -296,7 +297,7 @@ function noteNumber(noteName) {
|
|
|
296
297
|
return noteIndex + 12 * (Number(octave) + 1) + accidentalValue;
|
|
297
298
|
}
|
|
298
299
|
/**
|
|
299
|
-
*
|
|
300
|
+
* Convert noteNumber to noteName
|
|
300
301
|
* @category MIDI
|
|
301
302
|
*/
|
|
302
303
|
function noteName(noteNumber) {
|
|
@@ -305,6 +306,7 @@ function noteName(noteNumber) {
|
|
|
305
306
|
return noteNames[noteIndex] + octave;
|
|
306
307
|
}
|
|
307
308
|
/**
|
|
309
|
+
* @param note noteNumber: 0 ~ 127 or noteName e.g. 'C3'
|
|
308
310
|
* @category MIDI
|
|
309
311
|
*/
|
|
310
312
|
function isWhiteKey(note) {
|
|
@@ -367,6 +369,55 @@ function useRefCallbackEvent(event, handler, options, deps = []) {
|
|
|
367
369
|
}, deps);
|
|
368
370
|
}
|
|
369
371
|
|
|
372
|
+
/**
|
|
373
|
+
* @returns [refCallback, pointerDownHandler]
|
|
374
|
+
*/
|
|
375
|
+
function useDrag({ threshold = 1, onDrag, onDragStart, onDragEnd, }) {
|
|
376
|
+
const dragOffsetX = React.useRef(undefined);
|
|
377
|
+
const dragOffsetY = React.useRef(undefined);
|
|
378
|
+
const dragStartX = React.useRef(0);
|
|
379
|
+
const dragStartY = React.useRef(0);
|
|
380
|
+
const handleDrag = React.useCallback((event, first = false) => {
|
|
381
|
+
const isTouch = event instanceof TouchEvent;
|
|
382
|
+
if (isTouch && event.cancelable)
|
|
383
|
+
event.preventDefault();
|
|
384
|
+
const screenX = isTouch ? event.touches[0].screenX : event.screenX;
|
|
385
|
+
const screenY = isTouch ? event.touches[0].screenY : event.screenY;
|
|
386
|
+
let deltaX = 0;
|
|
387
|
+
let deltaY = 0;
|
|
388
|
+
if (first) {
|
|
389
|
+
dragStartX.current = screenX;
|
|
390
|
+
dragStartY.current = screenY;
|
|
391
|
+
}
|
|
392
|
+
if (dragOffsetX.current) {
|
|
393
|
+
deltaX = screenX - dragOffsetX.current;
|
|
394
|
+
dragOffsetX.current = screenX;
|
|
395
|
+
}
|
|
396
|
+
if (dragOffsetY.current) {
|
|
397
|
+
deltaY = screenY - dragOffsetY.current;
|
|
398
|
+
dragOffsetY.current = screenY;
|
|
399
|
+
}
|
|
400
|
+
if (Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold)
|
|
401
|
+
return;
|
|
402
|
+
if (onDrag)
|
|
403
|
+
onDrag(screenX - dragStartX.current, screenY - dragStartY.current, deltaX, deltaY);
|
|
404
|
+
}, [threshold, onDrag]);
|
|
405
|
+
const refHandler = useRefCallbackEvent('touchmove', handleDrag, { passive: false }, [onDrag]);
|
|
406
|
+
const pointerDownHandler = React.useCallback((event) => {
|
|
407
|
+
dragOffsetX.current = event.screenX;
|
|
408
|
+
dragOffsetY.current = event.screenY;
|
|
409
|
+
handleDrag(event, true);
|
|
410
|
+
onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart();
|
|
411
|
+
}, [handleDrag, onDragStart]);
|
|
412
|
+
useEventListener(globalThis.window, 'mousemove', handleDrag);
|
|
413
|
+
useEventListener(globalThis.window, 'pointerup', () => {
|
|
414
|
+
dragOffsetX.current = undefined;
|
|
415
|
+
dragOffsetY.current = undefined;
|
|
416
|
+
onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd();
|
|
417
|
+
});
|
|
418
|
+
return [refHandler, pointerDownHandler];
|
|
419
|
+
}
|
|
420
|
+
|
|
370
421
|
function addNoSelect() {
|
|
371
422
|
document.body.classList.add('tremolo-no-select');
|
|
372
423
|
}
|
|
@@ -376,34 +427,21 @@ function removeNoSelect() {
|
|
|
376
427
|
|
|
377
428
|
/**
|
|
378
429
|
* simple rotary Knob.
|
|
430
|
+
* @category AnimationKnob
|
|
379
431
|
*/
|
|
380
432
|
function AnimationKnob(_a) {
|
|
381
433
|
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"]);
|
|
382
434
|
// -- state and ref ---
|
|
383
|
-
|
|
384
|
-
const dragOffsetY = React.useRef(undefined);
|
|
435
|
+
const valueRef = React.useRef(0);
|
|
385
436
|
// --- interpret props ---
|
|
386
|
-
// const percent = normalizeValue(value, min, max, skew)
|
|
387
437
|
const isRelativeSize = typeof (size !== null && size !== void 0 ? size : width) == 'string' || typeof height == 'string';
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const screenY = isTouch ? event.touches[0].screenY : event.screenY;
|
|
396
|
-
const delta = dragOffsetY.current - screenY;
|
|
397
|
-
if (Math.abs(delta) < 1)
|
|
398
|
-
return;
|
|
399
|
-
dragOffsetY.current = screenY;
|
|
400
|
-
const n = normalizeValue(value, min, max, skew);
|
|
401
|
-
const v = rawValue(n + delta / 100, min, max, skew);
|
|
402
|
-
const v2 = clamp(stepValue(v, step), min, max);
|
|
403
|
-
if (onChange)
|
|
404
|
-
onChange(v2);
|
|
405
|
-
}
|
|
406
|
-
};
|
|
438
|
+
const onDrag = React.useCallback((_x, y) => {
|
|
439
|
+
if (!onChange)
|
|
440
|
+
return;
|
|
441
|
+
const v = rawValue(valueRef.current - y / 100, min, max, skew);
|
|
442
|
+
const v2 = clamp(stepValue(v, step), min, max);
|
|
443
|
+
onChange(v2);
|
|
444
|
+
}, [max, min, onChange, skew, step]);
|
|
407
445
|
const handleKeyDown = React.useCallback((event) => {
|
|
408
446
|
if (!keyboard || !onChange)
|
|
409
447
|
return;
|
|
@@ -423,6 +461,18 @@ function AnimationKnob(_a) {
|
|
|
423
461
|
}
|
|
424
462
|
}, [value, min, max, step, skew, keyboard, onChange]);
|
|
425
463
|
// --- hooks ---
|
|
464
|
+
const [touchMoveRefCallback, pointerDownHandler] = useDrag({
|
|
465
|
+
onDrag: onDrag,
|
|
466
|
+
onDragStart: () => {
|
|
467
|
+
valueRef.current = normalizeValue(value, min, max, skew);
|
|
468
|
+
if (bodyNoSelect)
|
|
469
|
+
addNoSelect();
|
|
470
|
+
},
|
|
471
|
+
onDragEnd: () => {
|
|
472
|
+
if (bodyNoSelect)
|
|
473
|
+
removeNoSelect();
|
|
474
|
+
},
|
|
475
|
+
});
|
|
426
476
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
427
477
|
if (!wheel)
|
|
428
478
|
return;
|
|
@@ -439,20 +489,10 @@ function AnimationKnob(_a) {
|
|
|
439
489
|
if (onChange)
|
|
440
490
|
onChange(clamp(stepValue(v, step), min, max));
|
|
441
491
|
}, { passive: false }, [wheel, value, min, max, skew, step, onChange]);
|
|
442
|
-
const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleEvent, { passive: false }, [value, min, max, skew, step, onChange, bodyNoSelect]);
|
|
443
|
-
useEventListener(window, 'mousemove', handleEvent);
|
|
444
|
-
useEventListener(window, 'pointerup', () => {
|
|
445
|
-
dragOffsetY.current = undefined;
|
|
446
|
-
if (bodyNoSelect)
|
|
447
|
-
removeNoSelect();
|
|
448
|
-
});
|
|
449
492
|
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-animation-knob', className), ref: (div) => {
|
|
450
493
|
wheelRefCallback(div);
|
|
451
494
|
touchMoveRefCallback(div);
|
|
452
|
-
}, 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: (
|
|
453
|
-
dragOffsetY.current = event.screenY;
|
|
454
|
-
handleEvent(event);
|
|
455
|
-
}, onDoubleClick: () => {
|
|
495
|
+
}, 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: () => {
|
|
456
496
|
if (enableDoubleClickDefault && onChange) {
|
|
457
497
|
onChange(defaultValue);
|
|
458
498
|
}
|
|
@@ -505,49 +545,22 @@ function AnimationKnob(_a) {
|
|
|
505
545
|
} })) })));
|
|
506
546
|
}
|
|
507
547
|
|
|
548
|
+
/** @category DragObserver */
|
|
508
549
|
function DragObserver(props) {
|
|
509
|
-
const { children, onDrag, onDragStart, onDragEnd
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
event.preventDefault();
|
|
516
|
-
const screenX = isTouch ? event.touches[0].screenX : event.screenX;
|
|
517
|
-
const screenY = isTouch ? event.touches[0].screenY : event.screenY;
|
|
518
|
-
let deltaX = 0, deltaY = 0;
|
|
519
|
-
if (dragOffsetX.current) {
|
|
520
|
-
deltaX = screenX - dragOffsetX.current;
|
|
521
|
-
dragOffsetX.current = screenX;
|
|
522
|
-
}
|
|
523
|
-
if (dragOffsetY.current) {
|
|
524
|
-
deltaY = screenY - dragOffsetY.current;
|
|
525
|
-
dragOffsetY.current = screenY;
|
|
526
|
-
}
|
|
527
|
-
if (Math.abs(deltaX) < 1 && Math.abs(deltaY) < 1)
|
|
528
|
-
return;
|
|
529
|
-
if (onDrag)
|
|
530
|
-
onDrag(deltaX, deltaY);
|
|
531
|
-
};
|
|
532
|
-
const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleEvent, { passive: false }, [onDrag]);
|
|
533
|
-
useEventListener(window, 'mousemove', handleEvent);
|
|
534
|
-
useEventListener(window, 'pointerup', () => {
|
|
535
|
-
dragOffsetX.current = undefined;
|
|
536
|
-
dragOffsetY.current = undefined;
|
|
537
|
-
onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd();
|
|
550
|
+
const { as: Component = 'div', threshold = 1, children, onDrag, onDragStart, onDragEnd } = props, attributes = __rest(props, ["as", "threshold", "children", "onDrag", "onDragStart", "onDragEnd"]);
|
|
551
|
+
const [refCallback, pointerDownHandler] = useDrag({
|
|
552
|
+
threshold: threshold,
|
|
553
|
+
onDrag: onDrag,
|
|
554
|
+
onDragStart: onDragStart,
|
|
555
|
+
onDragEnd: onDragEnd,
|
|
538
556
|
});
|
|
539
|
-
return (jsxRuntime.jsx(Component, Object.assign({ ref:
|
|
540
|
-
dragOffsetX.current = event.screenX;
|
|
541
|
-
dragOffsetY.current = event.screenY;
|
|
542
|
-
handleEvent(event);
|
|
543
|
-
onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart();
|
|
544
|
-
} }, attributes, { children: children })));
|
|
557
|
+
return (jsxRuntime.jsx(Component, Object.assign({ ref: refCallback, onPointerDown: pointerDownHandler }, attributes, { children: children })));
|
|
545
558
|
}
|
|
546
559
|
|
|
560
|
+
/** @category Knob */
|
|
547
561
|
function Knob(_a) {
|
|
548
562
|
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, 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", "className", "classes"]);
|
|
549
|
-
|
|
550
|
-
const dragOffsetY = React.useRef(undefined);
|
|
563
|
+
const valueRef = React.useRef(0);
|
|
551
564
|
// --- interpret props ---
|
|
552
565
|
const padding = 8; // %
|
|
553
566
|
const thumbLineWeight = 6; // %
|
|
@@ -556,26 +569,13 @@ function Knob(_a) {
|
|
|
556
569
|
const p = normalizeValue(value, min, max, skew);
|
|
557
570
|
const s = normalizeValue(startValue, min, max, skew);
|
|
558
571
|
// --- internal functions ---
|
|
559
|
-
const
|
|
572
|
+
const onDrag = React.useCallback((_x, y) => {
|
|
560
573
|
if (!onChange || readonly)
|
|
561
574
|
return;
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if (bodyNoSelect)
|
|
567
|
-
addNoSelect();
|
|
568
|
-
const screenY = isTouch ? event.touches[0].screenY : event.screenY;
|
|
569
|
-
const delta = dragOffsetY.current - screenY;
|
|
570
|
-
if (Math.abs(delta) < 1)
|
|
571
|
-
return;
|
|
572
|
-
dragOffsetY.current = screenY;
|
|
573
|
-
const n = normalizeValue(value, min, max, skew);
|
|
574
|
-
const v = rawValue(n + delta / 100, min, max, skew);
|
|
575
|
-
const v2 = clamp(stepValue(v, step), min, max);
|
|
576
|
-
onChange(v2);
|
|
577
|
-
}
|
|
578
|
-
};
|
|
575
|
+
const v = rawValue(valueRef.current - y / 100, min, max, skew);
|
|
576
|
+
const v2 = clamp(stepValue(v, step), min, max);
|
|
577
|
+
onChange(v2);
|
|
578
|
+
}, [max, min, onChange, readonly, skew, step]);
|
|
579
579
|
const handleKeyDown = React.useCallback((event) => {
|
|
580
580
|
if (!keyboard || !onChange || readonly)
|
|
581
581
|
return;
|
|
@@ -595,6 +595,18 @@ function Knob(_a) {
|
|
|
595
595
|
}
|
|
596
596
|
}, [value, min, max, step, skew, keyboard, readonly, onChange]);
|
|
597
597
|
// --- hooks ---
|
|
598
|
+
const [touchMoveRefCallback, pointerDownHandler] = useDrag({
|
|
599
|
+
onDrag: onDrag,
|
|
600
|
+
onDragStart: () => {
|
|
601
|
+
valueRef.current = normalizeValue(value, min, max, skew);
|
|
602
|
+
if (bodyNoSelect)
|
|
603
|
+
addNoSelect();
|
|
604
|
+
},
|
|
605
|
+
onDragEnd: () => {
|
|
606
|
+
if (bodyNoSelect)
|
|
607
|
+
removeNoSelect();
|
|
608
|
+
},
|
|
609
|
+
});
|
|
598
610
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
599
611
|
if (!wheel)
|
|
600
612
|
return;
|
|
@@ -611,13 +623,6 @@ function Knob(_a) {
|
|
|
611
623
|
if (onChange)
|
|
612
624
|
onChange(clamp(stepValue(v, step), min, max));
|
|
613
625
|
}, { passive: false }, [wheel, value, min, max, skew, step, onChange]);
|
|
614
|
-
const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleEvent, { passive: false }, [value, min, max, skew, step, onChange, bodyNoSelect]);
|
|
615
|
-
useEventListener(window, 'mousemove', handleEvent);
|
|
616
|
-
useEventListener(window, 'pointerup', () => {
|
|
617
|
-
dragOffsetY.current = undefined;
|
|
618
|
-
if (bodyNoSelect)
|
|
619
|
-
removeNoSelect();
|
|
620
|
-
});
|
|
621
626
|
const center = size / 2;
|
|
622
627
|
const r1 = -135;
|
|
623
628
|
const r2 = -135 + Math.min(p, s) * 270;
|
|
@@ -634,34 +639,17 @@ function Knob(_a) {
|
|
|
634
639
|
return (jsxRuntime.jsxs("svg", Object.assign({ className: clsx('tremolo-knob', className), ref: (div) => {
|
|
635
640
|
wheelRefCallback(div);
|
|
636
641
|
touchMoveRefCallback(div);
|
|
637
|
-
}, width: size, height: size, tabIndex: 0, "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled, "aria-readonly": readonly, onPointerDown: (
|
|
638
|
-
dragOffsetY.current = event.screenY;
|
|
639
|
-
handleEvent(event);
|
|
640
|
-
}, onDoubleClick: () => {
|
|
642
|
+
}, width: size, height: size, tabIndex: 0, "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled, "aria-readonly": readonly, onPointerDown: pointerDownHandler, onDoubleClick: () => {
|
|
641
643
|
if (enableDoubleClickDefault && onChange) {
|
|
642
644
|
onChange(defaultValue);
|
|
643
645
|
}
|
|
644
646
|
}, onKeyDown: handleKeyDown, onContextMenu: (e) => e.preventDefault() }, 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: `${thumbLength}%`, stroke: thumbLine || 'currentColor', strokeWidth: `${thumbLineWeight}%`, transform: `rotate(${ -135 + p * 270})`, "transform-origin": "50% 50%" })] })] })));
|
|
645
647
|
}
|
|
646
648
|
|
|
647
|
-
/**
|
|
648
|
-
* clamp value between min and max
|
|
649
|
-
* @category Math
|
|
650
|
-
*/
|
|
651
|
-
/**
|
|
652
|
-
*
|
|
653
|
-
* @category Math
|
|
654
|
-
*/
|
|
655
|
-
function toFixed$1(x, fractionDigits) {
|
|
656
|
-
return Number(x.toFixed(fractionDigits));
|
|
657
|
-
}
|
|
658
|
-
|
|
659
649
|
/**
|
|
660
650
|
* @module NumberInput
|
|
661
651
|
*/
|
|
662
652
|
function selectUnit(units, value) {
|
|
663
|
-
if (typeof units == 'string')
|
|
664
|
-
return [units, 1];
|
|
665
653
|
let i = 0;
|
|
666
654
|
for (; i < units.length; i++) {
|
|
667
655
|
if (Math.abs(units[i][1]) > Math.abs(value))
|
|
@@ -669,46 +657,33 @@ function selectUnit(units, value) {
|
|
|
669
657
|
}
|
|
670
658
|
return units[Math.max(0, i - 1)];
|
|
671
659
|
}
|
|
672
|
-
function parseValue(inputString, units, digit
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
formatValue: str,
|
|
680
|
-
unit: '',
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
else if (typeof units == 'string') {
|
|
660
|
+
function parseValue(inputString, units, digit) {
|
|
661
|
+
var _a;
|
|
662
|
+
const str = inputString.trim();
|
|
663
|
+
if (!units || typeof units == 'string') {
|
|
664
|
+
const m = str.match(/-?\d+(\.\d+)?/);
|
|
665
|
+
let v = Number((_a = m === null || m === void 0 ? void 0 : m[0]) !== null && _a !== void 0 ? _a : '0');
|
|
666
|
+
v = isNaN(v) ? 0 : v;
|
|
684
667
|
return {
|
|
685
|
-
rawValue:
|
|
686
|
-
formatValue:
|
|
687
|
-
unit: units,
|
|
668
|
+
rawValue: v,
|
|
669
|
+
formatValue: (digit != undefined ? v.toFixed(digit) : v) + (units !== null && units !== void 0 ? units : ''),
|
|
670
|
+
unit: units !== null && units !== void 0 ? units : '',
|
|
688
671
|
};
|
|
689
672
|
}
|
|
690
673
|
const unitList = units.map(([u, _s]) => u);
|
|
691
674
|
const scaleList = units.map(([_u, s]) => s);
|
|
692
|
-
let rawValue =
|
|
693
|
-
let formatValue = `${scaleList[0]}`;
|
|
675
|
+
let rawValue = 0;
|
|
694
676
|
let unit = unitList[0];
|
|
677
|
+
let formatValue = (digit != undefined ? rawValue.toFixed(digit) : rawValue) + unit;
|
|
695
678
|
const m = str.match(/^(-?\d+(\.\d+)?)\s*(\w*)$/);
|
|
696
679
|
if (m) {
|
|
697
680
|
rawValue = Number(m[1]) || 0;
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
unit = s[0];
|
|
705
|
-
}
|
|
706
|
-
else {
|
|
707
|
-
const [u, scale] = selectUnit(units, rawValue);
|
|
708
|
-
const v = rawValue / scale;
|
|
709
|
-
formatValue = `${digit != undefined ? toFixed$1(v, digit) : v}${u}`;
|
|
710
|
-
unit = u;
|
|
711
|
-
}
|
|
681
|
+
const uIndex = unitList.indexOf(m[3]);
|
|
682
|
+
rawValue *= uIndex != -1 ? scaleList[uIndex] : 1;
|
|
683
|
+
const [u, scale] = selectUnit(units, rawValue);
|
|
684
|
+
const v = rawValue / scale;
|
|
685
|
+
formatValue = (digit != undefined ? v.toFixed(digit) : v) + u;
|
|
686
|
+
unit = u;
|
|
712
687
|
}
|
|
713
688
|
return {
|
|
714
689
|
rawValue: rawValue,
|
|
@@ -717,44 +692,203 @@ function parseValue(inputString, units, digit, defaultValue = 0) {
|
|
|
717
692
|
};
|
|
718
693
|
}
|
|
719
694
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
*/
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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
|
+
function safeClamp(value, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
|
|
730
|
+
return clamp(value, min, max);
|
|
731
|
+
}
|
|
732
|
+
const createNumberInputStore = (initProps) => {
|
|
733
|
+
const DEFAULT_PROPS = {
|
|
734
|
+
value: '',
|
|
735
|
+
valueAsNumber: 0,
|
|
736
|
+
min: 0,
|
|
737
|
+
max: 0,
|
|
738
|
+
step: 1,
|
|
739
|
+
keepWithinRange: true,
|
|
740
|
+
onChange: (_v, _t) => { },
|
|
741
|
+
};
|
|
742
|
+
return createStore()((set) => (Object.assign(Object.assign(Object.assign(Object.assign({}, DEFAULT_PROPS), initProps), {
|
|
743
|
+
value: 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).formatValue,
|
|
744
|
+
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
|
+
}), { increment: () => set((state) => {
|
|
746
|
+
var _a, _b;
|
|
747
|
+
let next = parseValue(state.value, state.units, state.digit).rawValue +
|
|
748
|
+
((_a = state.step) !== null && _a !== void 0 ? _a : 1);
|
|
749
|
+
if (state.keepWithinRange) {
|
|
750
|
+
next = safeClamp(next, state.min, state.max);
|
|
751
|
+
}
|
|
752
|
+
const v = parseValue(String(next), state.units, state.digit).formatValue;
|
|
753
|
+
(_b = state === null || state === void 0 ? void 0 : state.onChange) === null || _b === void 0 ? void 0 : _b.call(state, next, v);
|
|
754
|
+
return {
|
|
755
|
+
value: v,
|
|
756
|
+
valueAsNumber: next,
|
|
757
|
+
};
|
|
758
|
+
}), decrement: () => set((state) => {
|
|
759
|
+
var _a, _b;
|
|
760
|
+
let next = parseValue(state.value, state.units, state.digit).rawValue -
|
|
761
|
+
((_a = state.step) !== null && _a !== void 0 ? _a : 1);
|
|
762
|
+
if (state.keepWithinRange) {
|
|
763
|
+
next = safeClamp(next, state.min, state.max);
|
|
764
|
+
}
|
|
765
|
+
const v = parseValue(String(next), state.units, state.digit).formatValue;
|
|
766
|
+
(_b = state === null || state === void 0 ? void 0 : state.onChange) === null || _b === void 0 ? void 0 : _b.call(state, next, v);
|
|
767
|
+
return {
|
|
768
|
+
value: v,
|
|
769
|
+
valueAsNumber: next,
|
|
770
|
+
};
|
|
771
|
+
}), change: (value) => set((state) => {
|
|
772
|
+
const v = value !== null && value !== void 0 ? value : '';
|
|
773
|
+
return {
|
|
774
|
+
value: v,
|
|
775
|
+
valueAsNumber: parseValue(v, state.units, state.digit).rawValue,
|
|
776
|
+
};
|
|
777
|
+
}) })));
|
|
778
|
+
};
|
|
779
|
+
const NumberInputContext = React.createContext(null);
|
|
780
|
+
function NumberInputProvider(_a) {
|
|
781
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
|
782
|
+
const storeRef = React.useRef();
|
|
783
|
+
if (!storeRef.current) {
|
|
784
|
+
storeRef.current = createNumberInputStore(props);
|
|
785
|
+
}
|
|
786
|
+
React.useEffect(() => {
|
|
787
|
+
if (storeRef.current) {
|
|
788
|
+
const parsed = parseValue(String((props === null || props === void 0 ? void 0 : props.value) || ''), props === null || props === void 0 ? void 0 : props.units, props === null || props === void 0 ? void 0 : props.digit);
|
|
789
|
+
storeRef.current.setState(Object.assign(Object.assign({}, props), {
|
|
790
|
+
value: parsed.formatValue,
|
|
791
|
+
valueAsNumber: parsed.rawValue,
|
|
792
|
+
}));
|
|
793
|
+
}
|
|
794
|
+
else {
|
|
795
|
+
storeRef.current = createNumberInputStore(props);
|
|
796
|
+
}
|
|
797
|
+
}, [props]);
|
|
798
|
+
return (jsxRuntime.jsx(NumberInputContext.Provider, { value: storeRef.current, children: children }));
|
|
799
|
+
}
|
|
800
|
+
/** @category NumberInput */
|
|
801
|
+
function useNumberInputContext(selector) {
|
|
802
|
+
const store = React.useContext(NumberInputContext);
|
|
803
|
+
if (!store)
|
|
804
|
+
throw new Error('Missing NumberInputContext.Provider in the tree');
|
|
805
|
+
return useStore(store, selector);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function Stepper(_a) {
|
|
809
|
+
var { dynamic = true, children, className } = _a, props = __rest(_a, ["dynamic", "children", "className"]);
|
|
810
|
+
return (jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-number-input-stepper', className), "data-dynamic": dynamic }, props, { children: children })));
|
|
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"]);
|
|
835
|
+
const [editing, setEditing] = React.useState(false);
|
|
836
|
+
const value = useNumberInputContext((s) => s.value);
|
|
837
|
+
const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber);
|
|
838
|
+
const change = useNumberInputContext((s) => s.change);
|
|
839
|
+
const error = React.useMemo(() => {
|
|
840
|
+
if (editing)
|
|
841
|
+
return false;
|
|
842
|
+
const v = valueAsNumber;
|
|
843
|
+
return (min !== null && min !== void 0 ? min : -Infinity) > v || v > (max !== null && max !== void 0 ? max : Infinity);
|
|
844
|
+
}, [editing, max, min, valueAsNumber]);
|
|
845
|
+
return (jsxRuntime.jsx("input", Object.assign({ className: clsx('tremolo-number-input', className), value: value, min: min, max: max, step: step, type: "text", disabled: disabled, tabIndex: -1, "data-error": error, onChange: (event) => {
|
|
728
846
|
const v = event.currentTarget.value;
|
|
729
|
-
|
|
730
|
-
const
|
|
731
|
-
|
|
732
|
-
onChange(newValue, event);
|
|
847
|
+
change(v);
|
|
848
|
+
const valueAsNumber = parseValue(v, units, digit).rawValue;
|
|
849
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(valueAsNumber, v);
|
|
733
850
|
}, onFocus: (event) => {
|
|
851
|
+
setEditing(true);
|
|
734
852
|
const v = event.currentTarget.value;
|
|
735
|
-
const parsed = parseValue(v, units, digit
|
|
853
|
+
const parsed = parseValue(v, units, digit);
|
|
736
854
|
if (selectWithFocus == 'all') {
|
|
737
855
|
event.currentTarget.setSelectionRange(0, v.length);
|
|
738
856
|
}
|
|
739
857
|
else if (selectWithFocus == 'number') {
|
|
740
858
|
event.currentTarget.setSelectionRange(0, parsed.formatValue.length - parsed.unit.length);
|
|
741
859
|
}
|
|
742
|
-
|
|
743
|
-
onFocus(parsed.rawValue, event);
|
|
860
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus(parsed.rawValue, parsed.formatValue, event);
|
|
744
861
|
}, onBlur: (event) => {
|
|
862
|
+
setEditing(false);
|
|
745
863
|
// update value
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
864
|
+
let v = parseValue(event.currentTarget.value, units, digit).rawValue;
|
|
865
|
+
if (clampValueOnBlur) {
|
|
866
|
+
v = safeClamp(v, min, max);
|
|
867
|
+
}
|
|
868
|
+
const parsed = parseValue(String(v), units, digit);
|
|
869
|
+
change(parsed.formatValue);
|
|
870
|
+
if (clampValueOnBlur) {
|
|
871
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(parsed.rawValue, parsed.formatValue);
|
|
872
|
+
}
|
|
873
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(parsed.rawValue, parsed.formatValue, event);
|
|
751
874
|
}, onKeyDown: (event) => {
|
|
752
|
-
if (
|
|
875
|
+
if (blurOnEnter && event.key == 'Enter') {
|
|
753
876
|
event.currentTarget.blur();
|
|
754
877
|
}
|
|
755
878
|
} }, props)));
|
|
756
879
|
}
|
|
880
|
+
/**
|
|
881
|
+
* Input with some useful functions for entering numerical values.
|
|
882
|
+
* @category NumberInput
|
|
883
|
+
*/
|
|
884
|
+
function NumberInput(_a) {
|
|
885
|
+
var { value, min, max, step = 1, defaultValue, units, disabled = false, digit, selectWithFocus = 'none', blurOnEnter = true, keepWithinRange = true, clampValueOnBlur = true, wheel = ['raw', 1], keyboard = ['raw', 1], wrapperClassName, className, onChange, onFocus, onBlur, children } = _a, props = __rest(_a, ["value", "min", "max", "step", "defaultValue", "units", "disabled", "digit", "selectWithFocus", "blurOnEnter", "keepWithinRange", "clampValueOnBlur", "wheel", "keyboard", "wrapperClassName", "className", "onChange", "onFocus", "onBlur", "children"]);
|
|
886
|
+
return (jsxRuntime.jsx(NumberInputProvider, { value: String(value), min: min, max: max, step: step, units: units, digit: digit, keepWithinRange: keepWithinRange, onChange: onChange, children: jsxRuntime.jsxs("div", { className: clsx('tremolo-number-input-wrapper', wrapperClassName),
|
|
887
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
888
|
+
tabIndex: 0, "data-stepper": !!children, children: [jsxRuntime.jsx(InternalInput, Object.assign({ min: min, max: max, step: step, defaultValue: defaultValue, units: units, disabled: disabled, digit: digit, selectWithFocus: selectWithFocus, blurOnEnter: blurOnEnter, keepWithinRange: keepWithinRange, clampValueOnBlur: clampValueOnBlur, wheel: wheel, keyboard: keyboard, wrapperClassName: wrapperClassName, className: className, onChange: onChange, onFocus: onFocus, onBlur: onBlur }, props)), children] }) }));
|
|
889
|
+
}
|
|
757
890
|
|
|
891
|
+
/** @category Piano */
|
|
758
892
|
function KeyLabel(_a) {
|
|
759
893
|
var { label, className, wrapperClassName, wrapperStyle, __note, __index, __label } = _a, props = __rest(_a, ["label", "className", "wrapperClassName", "wrapperStyle", "__note", "__index", "__label"]);
|
|
760
894
|
const content = label
|
|
@@ -763,8 +897,11 @@ function KeyLabel(_a) {
|
|
|
763
897
|
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 })) })));
|
|
764
898
|
}
|
|
765
899
|
|
|
766
|
-
|
|
767
|
-
|
|
900
|
+
/** @category Piano */
|
|
901
|
+
const defaultWhiteKeyWidth = 40;
|
|
902
|
+
/** @category Piano */
|
|
903
|
+
const WhiteKey = React.forwardRef((_a, ref) => {
|
|
904
|
+
var { width = defaultWhiteKeyWidth, height = '100%', className, style, children, __glissando, __position, __note, __disabled, __index, __fill, __width, __onPlayNote, __onStopNote, __label } = _a, props = __rest(_a, ["width", "height", "className", "style", "children", "__glissando", "__position", "__note", "__disabled", "__index", "__fill", "__width", "__onPlayNote", "__onStopNote", "__label"]);
|
|
768
905
|
const [played, setPlayed] = React.useState(false);
|
|
769
906
|
React.useImperativeHandle(ref, () => {
|
|
770
907
|
return {
|
|
@@ -772,19 +909,19 @@ const BlackKey = React.forwardRef((_a, ref) => {
|
|
|
772
909
|
if (__disabled)
|
|
773
910
|
return;
|
|
774
911
|
setPlayed(true);
|
|
775
|
-
if (
|
|
776
|
-
|
|
912
|
+
if (__onPlayNote)
|
|
913
|
+
__onPlayNote(__note);
|
|
777
914
|
},
|
|
778
915
|
stop() {
|
|
779
916
|
setPlayed(false);
|
|
780
|
-
if (
|
|
781
|
-
|
|
917
|
+
if (__onStopNote)
|
|
918
|
+
__onStopNote(__note);
|
|
782
919
|
},
|
|
783
920
|
played() {
|
|
784
921
|
return played;
|
|
785
922
|
},
|
|
786
923
|
};
|
|
787
|
-
}, [__disabled, __note,
|
|
924
|
+
}, [__disabled, __note, __onPlayNote, __onStopNote, played]);
|
|
788
925
|
let keyLabelProps = {};
|
|
789
926
|
if (children != undefined) {
|
|
790
927
|
React.Children.forEach(children, (child) => {
|
|
@@ -801,37 +938,40 @@ const BlackKey = React.forwardRef((_a, ref) => {
|
|
|
801
938
|
}
|
|
802
939
|
});
|
|
803
940
|
}
|
|
804
|
-
return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-
|
|
941
|
+
return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-white-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: () => {
|
|
805
942
|
if (__disabled)
|
|
806
943
|
return;
|
|
807
944
|
setPlayed(true);
|
|
808
|
-
if (
|
|
809
|
-
|
|
945
|
+
if (__onPlayNote)
|
|
946
|
+
__onPlayNote(__note);
|
|
810
947
|
}, onPointerEnter: () => {
|
|
811
948
|
if (__disabled)
|
|
812
949
|
return;
|
|
813
950
|
if (__glissando) {
|
|
814
951
|
setPlayed(true);
|
|
815
|
-
if (
|
|
816
|
-
|
|
952
|
+
if (__onPlayNote)
|
|
953
|
+
__onPlayNote(__note);
|
|
817
954
|
}
|
|
818
955
|
}, onPointerUp: () => {
|
|
819
956
|
if (__disabled)
|
|
820
957
|
return;
|
|
821
958
|
setPlayed(false);
|
|
822
|
-
if (
|
|
823
|
-
|
|
959
|
+
if (__onStopNote)
|
|
960
|
+
__onStopNote(__note);
|
|
824
961
|
}, onPointerLeave: () => {
|
|
825
962
|
if (__disabled)
|
|
826
963
|
return;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
964
|
+
if (__glissando) {
|
|
965
|
+
setPlayed(false);
|
|
966
|
+
if (__onStopNote)
|
|
967
|
+
__onStopNote(__note);
|
|
968
|
+
}
|
|
830
969
|
} }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
|
|
831
970
|
});
|
|
832
971
|
|
|
833
|
-
|
|
834
|
-
|
|
972
|
+
/** @category Piano */
|
|
973
|
+
const BlackKey = React.forwardRef((_a, ref) => {
|
|
974
|
+
var { width = defaultWhiteKeyWidth * 0.65, height = '60%', className, style, children, __glissando, __position, __note, __disabled, __index, __fill, __width, __onPlayNote, __onStopNote, __label } = _a, props = __rest(_a, ["width", "height", "className", "style", "children", "__glissando", "__position", "__note", "__disabled", "__index", "__fill", "__width", "__onPlayNote", "__onStopNote", "__label"]);
|
|
835
975
|
const [played, setPlayed] = React.useState(false);
|
|
836
976
|
React.useImperativeHandle(ref, () => {
|
|
837
977
|
return {
|
|
@@ -839,19 +979,19 @@ const WhiteKey = React.forwardRef((_a, ref) => {
|
|
|
839
979
|
if (__disabled)
|
|
840
980
|
return;
|
|
841
981
|
setPlayed(true);
|
|
842
|
-
if (
|
|
843
|
-
|
|
982
|
+
if (__onPlayNote)
|
|
983
|
+
__onPlayNote(__note);
|
|
844
984
|
},
|
|
845
985
|
stop() {
|
|
846
986
|
setPlayed(false);
|
|
847
|
-
if (
|
|
848
|
-
|
|
987
|
+
if (__onStopNote)
|
|
988
|
+
__onStopNote(__note);
|
|
849
989
|
},
|
|
850
990
|
played() {
|
|
851
991
|
return played;
|
|
852
992
|
},
|
|
853
993
|
};
|
|
854
|
-
}, [__disabled, __note,
|
|
994
|
+
}, [__disabled, __note, __onPlayNote, __onStopNote, played]);
|
|
855
995
|
let keyLabelProps = {};
|
|
856
996
|
if (children != undefined) {
|
|
857
997
|
React.Children.forEach(children, (child) => {
|
|
@@ -868,35 +1008,38 @@ const WhiteKey = React.forwardRef((_a, ref) => {
|
|
|
868
1008
|
}
|
|
869
1009
|
});
|
|
870
1010
|
}
|
|
871
|
-
return (jsxRuntime.jsx("div", Object.assign({ className: clsx(`tremolo-piano-
|
|
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: () => {
|
|
872
1012
|
if (__disabled)
|
|
873
1013
|
return;
|
|
874
1014
|
setPlayed(true);
|
|
875
|
-
if (
|
|
876
|
-
|
|
1015
|
+
if (__onPlayNote)
|
|
1016
|
+
__onPlayNote(__note);
|
|
877
1017
|
}, onPointerEnter: () => {
|
|
878
1018
|
if (__disabled)
|
|
879
1019
|
return;
|
|
880
1020
|
if (__glissando) {
|
|
881
1021
|
setPlayed(true);
|
|
882
|
-
if (
|
|
883
|
-
|
|
1022
|
+
if (__onPlayNote)
|
|
1023
|
+
__onPlayNote(__note);
|
|
884
1024
|
}
|
|
885
1025
|
}, onPointerUp: () => {
|
|
886
1026
|
if (__disabled)
|
|
887
1027
|
return;
|
|
888
1028
|
setPlayed(false);
|
|
889
|
-
if (
|
|
890
|
-
|
|
1029
|
+
if (__onStopNote)
|
|
1030
|
+
__onStopNote(__note);
|
|
891
1031
|
}, onPointerLeave: () => {
|
|
892
1032
|
if (__disabled)
|
|
893
1033
|
return;
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1034
|
+
if (__glissando) {
|
|
1035
|
+
setPlayed(false);
|
|
1036
|
+
if (__onStopNote)
|
|
1037
|
+
__onStopNote(__note);
|
|
1038
|
+
}
|
|
897
1039
|
} }, props, { children: jsxRuntime.jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
|
|
898
1040
|
});
|
|
899
1041
|
|
|
1042
|
+
/** @category Piano */
|
|
900
1043
|
const Shortcuts = {
|
|
901
1044
|
HOME_ROW: {
|
|
902
1045
|
keys: [
|
|
@@ -921,8 +1064,9 @@ const Shortcuts = {
|
|
|
921
1064
|
},
|
|
922
1065
|
};
|
|
923
1066
|
|
|
1067
|
+
/** @category Piano */
|
|
924
1068
|
function Piano(_a) {
|
|
925
|
-
var { noteRange, glissando = true, midiMax = 127, keyboardShortcuts, fill = false, height = fill ? '100%' : 160, style, className,
|
|
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"]);
|
|
926
1070
|
// -- state and ref ---
|
|
927
1071
|
const [pressed, setPressed] = React.useState(false);
|
|
928
1072
|
const [whiteNoteWidth, setWhiteNoteWidth] = React.useState(-1);
|
|
@@ -994,10 +1138,10 @@ function Piano(_a) {
|
|
|
994
1138
|
resizeObserver.observe(parent);
|
|
995
1139
|
}
|
|
996
1140
|
else {
|
|
997
|
-
setWhiteNoteWidth((whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width) ||
|
|
1141
|
+
setWhiteNoteWidth((whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width) || defaultWhiteKeyWidth);
|
|
998
1142
|
}
|
|
999
1143
|
}, [fill, whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width, whiteNoteCount]);
|
|
1000
|
-
useEventListener(window, 'keydown', (e) => {
|
|
1144
|
+
useEventListener(globalThis.window, 'keydown', (e) => {
|
|
1001
1145
|
var _a, _b, _c, _d;
|
|
1002
1146
|
if (e.repeat)
|
|
1003
1147
|
return;
|
|
@@ -1010,7 +1154,7 @@ function Piano(_a) {
|
|
|
1010
1154
|
}
|
|
1011
1155
|
}
|
|
1012
1156
|
});
|
|
1013
|
-
useEventListener(window, 'keyup', (e) => {
|
|
1157
|
+
useEventListener(globalThis.window, 'keyup', (e) => {
|
|
1014
1158
|
var _a, _b;
|
|
1015
1159
|
if (e.repeat)
|
|
1016
1160
|
return;
|
|
@@ -1021,7 +1165,7 @@ function Piano(_a) {
|
|
|
1021
1165
|
(_b = (_a = keyRefs.current[index]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.stop();
|
|
1022
1166
|
}
|
|
1023
1167
|
});
|
|
1024
|
-
return (jsxRuntime.jsx("div", Object.assign({ ref: pianoRef, className: clsx('tremolo-piano', className), style: Object.assign({ width: fill ? '100%' :
|
|
1168
|
+
return (jsxRuntime.jsx("div", Object.assign({ ref: pianoRef, className: clsx('tremolo-piano', className), style: Object.assign({ width: fill ? '100%' : (whiteNoteWidth + 3) * whiteNoteCount, height: height }, style), onPointerDown: (e) => {
|
|
1025
1169
|
if (props.onPointerDown)
|
|
1026
1170
|
props.onPointerDown(e);
|
|
1027
1171
|
setPressed(true);
|
|
@@ -1030,35 +1174,46 @@ function Piano(_a) {
|
|
|
1030
1174
|
props.onPointerUp(e);
|
|
1031
1175
|
setPressed(false);
|
|
1032
1176
|
} }, props, { children: noteRangeArray.map((note, index) => {
|
|
1033
|
-
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,
|
|
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));
|
|
1034
1178
|
}) })));
|
|
1035
1179
|
}
|
|
1036
1180
|
|
|
1037
|
-
const
|
|
1038
|
-
const
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1181
|
+
const createSliderStore = (initProps) => {
|
|
1182
|
+
const DEFAULT_PROPS = {
|
|
1183
|
+
min: 0,
|
|
1184
|
+
max: 0,
|
|
1185
|
+
step: 0,
|
|
1186
|
+
skew: 0,
|
|
1187
|
+
vertical: false,
|
|
1188
|
+
reverse: false,
|
|
1189
|
+
disabled: false,
|
|
1190
|
+
};
|
|
1191
|
+
return createStore()((set) => (Object.assign(Object.assign(Object.assign({}, DEFAULT_PROPS), initProps), { updateMin: (min) => set(() => ({ min: min })), updateMax: (max) => set(() => ({ max: max })), updateStep: (step) => set(() => ({ step: step })), updateSkew: (skew) => set(() => ({ skew: skew })), updateVertical: (vertical) => set(() => ({ vertical: vertical })), updateReverse: (reverse) => set(() => ({ reverse: reverse })), updateDisabled: (disabled) => set(() => ({ disabled: disabled })) })));
|
|
1192
|
+
};
|
|
1193
|
+
const SliderContext = React.createContext(null);
|
|
1194
|
+
function SliderProvider(_a) {
|
|
1195
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
|
1196
|
+
const storeRef = React.useRef();
|
|
1197
|
+
if (!storeRef.current) {
|
|
1198
|
+
storeRef.current = createSliderStore(props);
|
|
1199
|
+
}
|
|
1200
|
+
React.useEffect(() => {
|
|
1201
|
+
if (storeRef.current) {
|
|
1202
|
+
storeRef.current.setState(props);
|
|
1203
|
+
}
|
|
1204
|
+
else {
|
|
1205
|
+
storeRef.current = createSliderStore(props);
|
|
1206
|
+
}
|
|
1207
|
+
}, [props]);
|
|
1208
|
+
return (jsxRuntime.jsx(SliderContext.Provider, { value: storeRef.current, children: children }));
|
|
1209
|
+
}
|
|
1210
|
+
/** @category Slider */
|
|
1211
|
+
function useSliderContext(selector) {
|
|
1212
|
+
const store = React.useContext(SliderContext);
|
|
1213
|
+
if (!store)
|
|
1214
|
+
throw new Error('Missing SliderContext.Provider in the tree');
|
|
1215
|
+
return useStore(store, selector);
|
|
1053
1216
|
}
|
|
1054
|
-
const useMin = () => React.useContext(minContext);
|
|
1055
|
-
const useMax = () => React.useContext(maxContext);
|
|
1056
|
-
const useStep = () => React.useContext(stepContext);
|
|
1057
|
-
const useSkew = () => React.useContext(skewContext);
|
|
1058
|
-
const useVertical = () => React.useContext(verticalContext);
|
|
1059
|
-
// export const useSetVertical = () => useContext(setVerticalContext)
|
|
1060
|
-
const useReverse = () => React.useContext(reverseContext);
|
|
1061
|
-
const useDisabled = () => React.useContext(disabledContext);
|
|
1062
1217
|
|
|
1063
1218
|
/**
|
|
1064
1219
|
* clamp value between min and max
|
|
@@ -1094,28 +1249,30 @@ function generateOptionsList(options, min, max, step) {
|
|
|
1094
1249
|
return optionsList;
|
|
1095
1250
|
}
|
|
1096
1251
|
|
|
1252
|
+
/** @category Slider */
|
|
1097
1253
|
function ScaleOption(_a) {
|
|
1098
1254
|
var { value, type = 'mark-number', label, thickness = 1, length = '0.5rem', gap = 2, labelWidth, classes, styles, className, style } = _a, props = __rest(_a, ["value", "type", "label", "thickness", "length", "gap", "labelWidth", "classes", "styles", "className", "style"]);
|
|
1099
|
-
const min =
|
|
1100
|
-
const max =
|
|
1101
|
-
const skew =
|
|
1102
|
-
const vertical =
|
|
1103
|
-
const reverse =
|
|
1255
|
+
const min = useSliderContext((s) => s.min);
|
|
1256
|
+
const max = useSliderContext((s) => s.max);
|
|
1257
|
+
const skew = useSliderContext((s) => s.skew);
|
|
1258
|
+
const vertical = useSliderContext((s) => s.vertical);
|
|
1259
|
+
const reverse = useSliderContext((s) => s.reverse);
|
|
1104
1260
|
const calcPercent = React.useCallback((rawValue) => {
|
|
1105
|
-
return toFixed$
|
|
1261
|
+
return toFixed$1(xor(vertical, reverse)
|
|
1106
1262
|
? 100 - normalizeValue(rawValue, min, max, skew) * 100
|
|
1107
1263
|
: normalizeValue(rawValue, min, max, skew) * 100);
|
|
1108
1264
|
}, [vertical, reverse, max, min, skew]);
|
|
1109
1265
|
return (jsxRuntime.jsxs("div", Object.assign({ className: clsx('tremolo-slider-scale-option', className), style: Object.assign({ left: !vertical ? `${calcPercent(value)}%` : undefined, top: vertical ? `${calcPercent(value)}%` : undefined }, style), "data-vertical": vertical }, props, { children: [type != 'number' && (jsxRuntime.jsx("div", { className: clsx('tremolo-slider-scale-option-mark', classes === null || classes === void 0 ? void 0 : classes.mark), style: Object.assign({ width: !vertical ? thickness : length, height: vertical ? thickness : length, marginBottom: !vertical ? gap : undefined, marginRight: vertical ? gap : undefined }, styles === null || styles === void 0 ? void 0 : styles.mark), "data-vertical": vertical })), type != 'mark' && (jsxRuntime.jsx("div", { className: clsx('tremolo-slider-scale-option-label', classes === null || classes === void 0 ? void 0 : classes.label), style: Object.assign({ width: labelWidth }, styles === null || styles === void 0 ? void 0 : styles.label), children: label || value }))] })));
|
|
1110
1266
|
}
|
|
1111
1267
|
|
|
1268
|
+
/** @category Slider */
|
|
1112
1269
|
function Scale(_a) {
|
|
1113
1270
|
var { gap = 6, options, children, className, style } = _a, props = __rest(_a, ["gap", "options", "children", "className", "style"]);
|
|
1114
|
-
const min =
|
|
1115
|
-
const max =
|
|
1116
|
-
const step =
|
|
1117
|
-
const vertical =
|
|
1118
|
-
const reverse =
|
|
1271
|
+
const min = useSliderContext((s) => s.min);
|
|
1272
|
+
const max = useSliderContext((s) => s.max);
|
|
1273
|
+
const step = useSliderContext((s) => s.step);
|
|
1274
|
+
const vertical = useSliderContext((s) => s.vertical);
|
|
1275
|
+
const reverse = useSliderContext((s) => s.reverse);
|
|
1119
1276
|
const optionsList = options
|
|
1120
1277
|
? generateOptionsList(options, min, max, step)
|
|
1121
1278
|
: [];
|
|
@@ -1128,11 +1285,13 @@ function Scale(_a) {
|
|
|
1128
1285
|
: children })));
|
|
1129
1286
|
}
|
|
1130
1287
|
|
|
1288
|
+
/** @category Slider */
|
|
1131
1289
|
const defaultThumbSize = 22;
|
|
1290
|
+
/** @category Slider */
|
|
1132
1291
|
const SliderThumb = React.forwardRef(({ size, width = defaultThumbSize, height = defaultThumbSize, children, className, style, __percent, }, ref) => {
|
|
1133
1292
|
const wrapperRef = React.useRef(null);
|
|
1134
|
-
const vertical =
|
|
1135
|
-
const disabled =
|
|
1293
|
+
const vertical = useSliderContext((s) => s.vertical);
|
|
1294
|
+
const disabled = useSliderContext((s) => s.disabled);
|
|
1136
1295
|
React.useImperativeHandle(ref, () => {
|
|
1137
1296
|
return {
|
|
1138
1297
|
focus() {
|
|
@@ -1155,24 +1314,30 @@ const SliderThumb = React.forwardRef(({ size, width = defaultThumbSize, height =
|
|
|
1155
1314
|
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) })) }));
|
|
1156
1315
|
});
|
|
1157
1316
|
|
|
1317
|
+
/** @category Slider */
|
|
1158
1318
|
const defaultLength = 140;
|
|
1319
|
+
/** @category Slider */
|
|
1159
1320
|
const defaultThickness = 10;
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
const
|
|
1163
|
-
const
|
|
1321
|
+
/** @category Slider */
|
|
1322
|
+
function SliderTrack({ length = defaultLength, thickness = defaultThickness, active, inactive, children, className, style, defaultStyle = true, __thumb, __percent = 0, }) {
|
|
1323
|
+
const vertical = useSliderContext((s) => s.vertical);
|
|
1324
|
+
const reverse = useSliderContext((s) => s.reverse);
|
|
1325
|
+
const disabled = useSliderContext((s) => s.disabled);
|
|
1164
1326
|
const direction = vertical ? 'bottom' : 'right';
|
|
1165
1327
|
const colors = {
|
|
1166
1328
|
'--active': active,
|
|
1167
1329
|
'--inactive': inactive,
|
|
1168
1330
|
};
|
|
1169
|
-
return (jsxRuntime.jsxs("div", { className: clsx('tremolo-slider-track', className), "aria-disabled": disabled,
|
|
1170
|
-
|
|
1171
|
-
|
|
1331
|
+
return (jsxRuntime.jsxs("div", { className: clsx('tremolo-slider-track', className), "aria-disabled": disabled, "data-vertical": vertical, style: !defaultStyle
|
|
1332
|
+
? style
|
|
1333
|
+
: Object.assign(Object.assign(Object.assign({}, colors), { background: xor(vertical, reverse)
|
|
1334
|
+
? `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] }));
|
|
1172
1336
|
}
|
|
1173
1337
|
|
|
1174
1338
|
/**
|
|
1175
1339
|
* Customizable slider
|
|
1340
|
+
* @category Slider
|
|
1176
1341
|
*/
|
|
1177
1342
|
const Slider = React.forwardRef((_a, ref) => {
|
|
1178
1343
|
var _b, _c, _d;
|
|
@@ -1182,8 +1347,8 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1182
1347
|
const thumbRef = React.useRef(null);
|
|
1183
1348
|
const thumbDragged = React.useRef(false);
|
|
1184
1349
|
// --- interpret props ---
|
|
1185
|
-
const p = toFixed$
|
|
1186
|
-
const rev = toFixed$
|
|
1350
|
+
const p = toFixed$1(normalizeValue(value, min, max, skew) * 100);
|
|
1351
|
+
const rev = toFixed$1(100 - p);
|
|
1187
1352
|
// NOTE
|
|
1188
1353
|
// normal -> normal (right)
|
|
1189
1354
|
// vertical -> rev (up)
|
|
@@ -1286,10 +1451,10 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1286
1451
|
}, {
|
|
1287
1452
|
passive: false,
|
|
1288
1453
|
}, [wheel, value, min, max, skew, step]);
|
|
1289
|
-
useEventListener(window, 'mousemove', (event) => {
|
|
1454
|
+
useEventListener(globalThis.window, 'mousemove', (event) => {
|
|
1290
1455
|
handleValue(event);
|
|
1291
1456
|
});
|
|
1292
|
-
useEventListener(window, 'mouseup', () => {
|
|
1457
|
+
useEventListener(globalThis.window, 'mouseup', () => {
|
|
1293
1458
|
thumbDragged.current = false;
|
|
1294
1459
|
if (bodyNoSelect)
|
|
1295
1460
|
removeNoSelect();
|
|
@@ -1306,7 +1471,7 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1306
1471
|
},
|
|
1307
1472
|
};
|
|
1308
1473
|
}, []);
|
|
1309
|
-
return (jsxRuntime.jsx(
|
|
1474
|
+
return (jsxRuntime.jsx(SliderProvider, { min: min, max: max, step: step, skew: skew, vertical: vertical, reverse: reverse, disabled: disabled, children: jsxRuntime.jsx("div", Object.assign({ className: clsx('tremolo-slider', className), ref: (div) => {
|
|
1310
1475
|
wheelRefCallback(div);
|
|
1311
1476
|
touchMoveRefCallback(div);
|
|
1312
1477
|
}, 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) => {
|
|
@@ -1315,9 +1480,12 @@ const Slider = React.forwardRef((_a, ref) => {
|
|
|
1315
1480
|
}, onKeyDown: handleKeyDown, onFocus: (_c = thumbRef.current) === null || _c === void 0 ? void 0 : _c.focus, onBlur: (_d = thumbRef.current) === null || _d === void 0 ? void 0 : _d.blur }, props, { children: jsxRuntime.jsxs("div", { style: {
|
|
1316
1481
|
display: 'flex',
|
|
1317
1482
|
flexDirection: vertical ? 'row' : 'column',
|
|
1483
|
+
width: !vertical ? '100%' : undefined,
|
|
1484
|
+
height: vertical ? '100%' : undefined,
|
|
1318
1485
|
}, children: [jsxRuntime.jsx("div", { className: "tremolo-slider-track-wrapper", ref: trackElementRef, children: jsxRuntime.jsx(SliderTrack, Object.assign({ __percent: percent, __thumb: jsxRuntime.jsx(SliderThumb, Object.assign({ ref: thumbRef, __percent: percent }, thumbProps)) }, trackProps)) }), scaleComponent] }) })) }));
|
|
1319
1486
|
});
|
|
1320
1487
|
|
|
1488
|
+
/** @category WheelObserver */
|
|
1321
1489
|
function WheelObserver(props) {
|
|
1322
1490
|
const { children, onWheel, as: Component = 'div' } = props, attributes = __rest(props, ["children", "onWheel", "as"]);
|
|
1323
1491
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
@@ -1327,10 +1495,12 @@ function WheelObserver(props) {
|
|
|
1327
1495
|
return (jsxRuntime.jsx(Component, Object.assign({ ref: wheelRefCallback }, attributes, { children: children })));
|
|
1328
1496
|
}
|
|
1329
1497
|
|
|
1498
|
+
/** @category XYPad */
|
|
1330
1499
|
function XYPadArea({ width = 120, height = 120, bg = '#eee', children, className, style, __thumb, }) {
|
|
1331
1500
|
return (jsxRuntime.jsxs("div", { className: clsx('tremolo-xy-pad-area', className), style: Object.assign({ position: 'relative', width: width, height: height, background: bg }, style), children: [children, __thumb] }));
|
|
1332
1501
|
}
|
|
1333
1502
|
|
|
1503
|
+
/** @category XYPad */
|
|
1334
1504
|
const XYPadThumb = React.forwardRef(({ size, width = 22, height = 22, children, wrapperClassName, wrapperStyle, className, style, __disabled, __css, }, ref) => {
|
|
1335
1505
|
const wrapperRef = React.useRef(null);
|
|
1336
1506
|
React.useImperativeHandle(ref, () => {
|
|
@@ -1361,6 +1531,7 @@ const defaultValueOptions = {
|
|
|
1361
1531
|
};
|
|
1362
1532
|
/**
|
|
1363
1533
|
* Simple XYPad
|
|
1534
|
+
* @category XYPad
|
|
1364
1535
|
*/
|
|
1365
1536
|
const XYPad = React.forwardRef((_a, ref) => {
|
|
1366
1537
|
var _b, _c, _d;
|
|
@@ -1378,8 +1549,8 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1378
1549
|
// --- interpret props ---
|
|
1379
1550
|
const nx = normalizeValue(x.value, x.min, x.max, x.skew);
|
|
1380
1551
|
const ny = normalizeValue(y.value, y.min, y.max, y.skew);
|
|
1381
|
-
const percentX = toFixed$
|
|
1382
|
-
const percentY = toFixed$
|
|
1552
|
+
const percentX = toFixed$1((x.reverse ? 1 - nx : nx) * 100);
|
|
1553
|
+
const percentY = toFixed$1((y.reverse ? 1 - ny : ny) * 100);
|
|
1383
1554
|
let areaProps = {}, thumbProps = {};
|
|
1384
1555
|
if (children != undefined) {
|
|
1385
1556
|
React.Children.forEach(children, (child) => {
|
|
@@ -1486,10 +1657,10 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1486
1657
|
}, {
|
|
1487
1658
|
passive: false,
|
|
1488
1659
|
}, [x, y]);
|
|
1489
|
-
useEventListener(window, 'mousemove', (event) => {
|
|
1660
|
+
useEventListener(globalThis.window, 'mousemove', (event) => {
|
|
1490
1661
|
handleValue(event);
|
|
1491
1662
|
});
|
|
1492
|
-
useEventListener(window, 'mouseup', () => {
|
|
1663
|
+
useEventListener(globalThis.window, 'mouseup', () => {
|
|
1493
1664
|
thumbDragged.current = false;
|
|
1494
1665
|
if (bodyNoSelect)
|
|
1495
1666
|
removeNoSelect();
|
|
@@ -1523,7 +1694,9 @@ const XYPad = React.forwardRef((_a, ref) => {
|
|
|
1523
1694
|
exports.AnimationCanvas = AnimationCanvas;
|
|
1524
1695
|
exports.AnimationKnob = AnimationKnob;
|
|
1525
1696
|
exports.BlackKey = BlackKey;
|
|
1697
|
+
exports.DecrementStepper = DecrementStepper;
|
|
1526
1698
|
exports.DragObserver = DragObserver;
|
|
1699
|
+
exports.IncrementStepper = IncrementStepper;
|
|
1527
1700
|
exports.KeyLabel = KeyLabel;
|
|
1528
1701
|
exports.Knob = Knob;
|
|
1529
1702
|
exports.NumberInput = NumberInput;
|
|
@@ -1534,20 +1707,11 @@ exports.Shortcuts = Shortcuts;
|
|
|
1534
1707
|
exports.Slider = Slider;
|
|
1535
1708
|
exports.SliderThumb = SliderThumb;
|
|
1536
1709
|
exports.SliderTrack = SliderTrack;
|
|
1537
|
-
exports.
|
|
1710
|
+
exports.Stepper = Stepper;
|
|
1538
1711
|
exports.WheelObserver = WheelObserver;
|
|
1539
1712
|
exports.WhiteKey = WhiteKey;
|
|
1540
1713
|
exports.XYPad = XYPad;
|
|
1541
1714
|
exports.XYPadArea = XYPadArea;
|
|
1542
1715
|
exports.XYPadThumb = XYPadThumb;
|
|
1543
|
-
exports.
|
|
1544
|
-
exports.defaultThickness = defaultThickness;
|
|
1545
|
-
exports.defaultThumbSize = defaultThumbSize;
|
|
1546
|
-
exports.useDisabled = useDisabled;
|
|
1547
|
-
exports.useMax = useMax;
|
|
1548
|
-
exports.useMin = useMin;
|
|
1549
|
-
exports.useReverse = useReverse;
|
|
1550
|
-
exports.useSkew = useSkew;
|
|
1551
|
-
exports.useStep = useStep;
|
|
1552
|
-
exports.useVertical = useVertical;
|
|
1716
|
+
exports.useSliderContext = useSliderContext;
|
|
1553
1717
|
//# sourceMappingURL=index.js.map
|