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