@tremolo-ui/react 0.0.4 → 0.0.6
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/LICENSE +21 -0
- package/dist/cjs/index.js +196 -93
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts +3 -4
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Knob/index.d.ts +6 -7
- package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/index.d.ts +10 -7
- package/dist/cjs/types/components/NumberInput/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/BlackKey.d.ts +4 -0
- package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +1 -0
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts +20 -0
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +1 -0
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts +4 -0
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +1 -0
- package/dist/cjs/types/components/Piano/index.d.ts +35 -0
- package/dist/cjs/types/components/Piano/index.d.ts.map +1 -0
- package/dist/cjs/types/components/Piano/key.d.ts +39 -0
- package/dist/cjs/types/components/Piano/key.d.ts.map +1 -0
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +12 -0
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts.map +1 -0
- package/dist/cjs/types/components/Slider/Thumb.d.ts +17 -2
- package/dist/cjs/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Track.d.ts +21 -2
- package/dist/cjs/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/index.d.ts +18 -10
- package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
- package/dist/cjs/types/components/_util/index.d.ts +4 -0
- package/dist/cjs/types/components/_util/index.d.ts.map +1 -0
- package/dist/esm/index.js +197 -94
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/AnimationCanvas/index.d.ts +3 -4
- package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/esm/types/components/Knob/index.d.ts +6 -7
- package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/index.d.ts +10 -7
- package/dist/esm/types/components/NumberInput/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/BlackKey.d.ts +4 -0
- package/dist/esm/types/components/Piano/BlackKey.d.ts.map +1 -0
- package/dist/esm/types/components/Piano/KeyLabel.d.ts +20 -0
- package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +1 -0
- package/dist/esm/types/components/Piano/WhiteKey.d.ts +4 -0
- package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +1 -0
- package/dist/esm/types/components/Piano/index.d.ts +35 -0
- package/dist/esm/types/components/Piano/index.d.ts.map +1 -0
- package/dist/esm/types/components/Piano/key.d.ts +39 -0
- package/dist/esm/types/components/Piano/key.d.ts.map +1 -0
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +12 -0
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts.map +1 -0
- package/dist/esm/types/components/Slider/Thumb.d.ts +17 -2
- package/dist/esm/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Track.d.ts +21 -2
- package/dist/esm/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/index.d.ts +18 -10
- package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
- package/dist/esm/types/components/_util/index.d.ts +4 -0
- package/dist/esm/types/components/_util/index.d.ts.map +1 -0
- package/dist/styles/{variables.css → index.css} +4 -0
- package/package.json +12 -16
- package/src/components/AnimationCanvas/index.tsx +3 -7
- package/src/components/Knob/index.tsx +16 -20
- package/src/components/NumberInput/index.tsx +19 -12
- package/src/components/Piano/BlackKey.tsx +108 -0
- package/src/components/Piano/KeyLabel.tsx +69 -0
- package/src/components/Piano/WhiteKey.tsx +109 -0
- package/src/components/Piano/index.tsx +222 -0
- package/src/components/Piano/key.ts +43 -0
- package/src/components/Piano/keyboardShortcuts.ts +12 -0
- package/src/components/Slider/Thumb.tsx +56 -15
- package/src/components/Slider/Track.tsx +62 -3
- package/src/components/Slider/index.tsx +125 -89
- package/src/components/_util/index.ts +11 -0
- package/src/styles/{variables.css → index.css} +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 mimoz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/cjs/index.js
CHANGED
|
@@ -96,7 +96,7 @@ function AnimationCanvas(_a) {
|
|
|
96
96
|
if (!parent)
|
|
97
97
|
throw new Error("Canvas doesn't have a parent element.");
|
|
98
98
|
const memoCanvas = memoCanvasRef.current;
|
|
99
|
-
const memoContext = memoCanvas === null || memoCanvas ===
|
|
99
|
+
const memoContext = memoCanvas === null || memoCanvas === undefined ? undefined : memoCanvas.getContext('2d', options);
|
|
100
100
|
const resizeObserver = new ResizeObserver(() => {
|
|
101
101
|
// console.log('resize')
|
|
102
102
|
// Prevents loss of some context when the canvas is resized
|
|
@@ -152,15 +152,27 @@ function AnimationCanvas(_a) {
|
|
|
152
152
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("canvas", Object.assign({ className: clsx('tremolo-animation-canvas', className), width: relativeSize ? 0 : width, height: relativeSize ? 0 : height, css: react.css(style), ref: canvasRef }, props)), relativeSize && reduceFlickering && (jsxRuntime.jsx("canvas", { style: { display: 'none' }, width: relativeSize ? 0 : width, height: relativeSize ? 0 : height, ref: memoCanvasRef }))] }));
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* clamp value between min and max
|
|
157
|
+
* @category Math
|
|
158
|
+
*/
|
|
155
159
|
function clamp(value, min, max) {
|
|
156
160
|
return Math.max(min, Math.min(value, max));
|
|
157
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Normalize the value from 0 to 1
|
|
164
|
+
* @category Math
|
|
165
|
+
*/
|
|
158
166
|
function normalizeValue(rawValue, min, max, skew = 1) {
|
|
159
167
|
if (min >= max)
|
|
160
168
|
throw new RangeError('requirements: min < max');
|
|
161
169
|
const v = clamp((rawValue - min) / (max - min), 0, 1);
|
|
162
170
|
return Math.pow(v, skew);
|
|
163
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Convert normalized values back to raw values.
|
|
174
|
+
* @category Math
|
|
175
|
+
*/
|
|
164
176
|
function rawValue(normalizedValue, min, max, skew = 1) {
|
|
165
177
|
if (min >= max)
|
|
166
178
|
throw new RangeError('requirements: min < max');
|
|
@@ -169,22 +181,38 @@ function rawValue(normalizedValue, min, max, skew = 1) {
|
|
|
169
181
|
: Math.exp(Math.log(clamp(normalizedValue, 0, 1)) / skew);
|
|
170
182
|
return min + v * (max - min);
|
|
171
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
*
|
|
186
|
+
* @category Math
|
|
187
|
+
*/
|
|
172
188
|
function stepValue(value, step) {
|
|
173
189
|
var _a;
|
|
174
190
|
if (step <= 0)
|
|
175
191
|
throw new RangeError('requirements: step > 0');
|
|
176
192
|
const quotient = Math.floor(value / step);
|
|
177
|
-
const decimalDigits = (_a = decimalPart$1(step)) === null || _a ===
|
|
193
|
+
const decimalDigits = (_a = decimalPart$1(step)) === null || _a === undefined ? undefined : _a.length;
|
|
178
194
|
const v = toFixed$2(quotient * step, decimalDigits);
|
|
179
195
|
const next = toFixed$2((quotient + 1) * step, decimalDigits);
|
|
180
196
|
return Math.abs(value - v) < Math.abs(value - next) ? v : next;
|
|
181
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
*
|
|
200
|
+
* @category Math
|
|
201
|
+
*/
|
|
182
202
|
function toFixed$2(x, fractionDigits) {
|
|
183
203
|
return Number(x.toFixed(fractionDigits));
|
|
184
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
*
|
|
207
|
+
* @category Math
|
|
208
|
+
*/
|
|
185
209
|
function decimalPart$1(x) {
|
|
186
210
|
return String(x).split('.')[1];
|
|
187
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
*
|
|
214
|
+
* @category Math
|
|
215
|
+
*/
|
|
188
216
|
function radian(degree) {
|
|
189
217
|
return (Math.PI * degree) / 180;
|
|
190
218
|
}
|
|
@@ -226,13 +254,13 @@ function useCallbackRef(callback, deps = []) {
|
|
|
226
254
|
React.useInsertionEffect(() => {
|
|
227
255
|
callbackRef.current = callback;
|
|
228
256
|
});
|
|
229
|
-
return React.useCallback((...args) => { var _a; return (_a = callbackRef.current) === null || _a ===
|
|
257
|
+
return React.useCallback((...args) => { var _a; return (_a = callbackRef.current) === null || _a === undefined ? undefined : _a.call(callbackRef, ...args); }, deps);
|
|
230
258
|
}
|
|
231
259
|
|
|
232
260
|
function useEventListener(target, event, handler, options) {
|
|
233
261
|
const listener = useCallbackRef(handler);
|
|
234
262
|
React.useEffect(() => {
|
|
235
|
-
const node = typeof target === 'function' ? target() : (target !== null && target !==
|
|
263
|
+
const node = typeof target === 'function' ? target() : (target !== null && target !== undefined ? target : document);
|
|
236
264
|
if (!handler || !node)
|
|
237
265
|
return;
|
|
238
266
|
node.addEventListener(event, listener, options);
|
|
@@ -241,8 +269,8 @@ function useEventListener(target, event, handler, options) {
|
|
|
241
269
|
};
|
|
242
270
|
}, [event, target, options, listener, handler]);
|
|
243
271
|
return () => {
|
|
244
|
-
const node = typeof target === 'function' ? target() : (target !== null && target !==
|
|
245
|
-
node === null || node ===
|
|
272
|
+
const node = typeof target === 'function' ? target() : (target !== null && target !== undefined ? target : document);
|
|
273
|
+
node === null || node === undefined ? undefined : node.removeEventListener(event, listener, options);
|
|
246
274
|
};
|
|
247
275
|
}
|
|
248
276
|
|
|
@@ -251,7 +279,7 @@ function useRefCallbackEvent(event, handler, options, deps = []) {
|
|
|
251
279
|
let cleanup;
|
|
252
280
|
return (node) => {
|
|
253
281
|
if (!node) {
|
|
254
|
-
cleanup === null || cleanup ===
|
|
282
|
+
cleanup === null || cleanup === undefined ? undefined : cleanup();
|
|
255
283
|
return;
|
|
256
284
|
}
|
|
257
285
|
node.addEventListener(event, handler, options);
|
|
@@ -262,6 +290,13 @@ function useRefCallbackEvent(event, handler, options, deps = []) {
|
|
|
262
290
|
}, deps);
|
|
263
291
|
}
|
|
264
292
|
|
|
293
|
+
function addNoSelect() {
|
|
294
|
+
document.body.classList.add('tremolo-no-select');
|
|
295
|
+
}
|
|
296
|
+
function removeNoSelect() {
|
|
297
|
+
document.body.classList.remove('tremolo-no-select');
|
|
298
|
+
}
|
|
299
|
+
|
|
265
300
|
const defaultOptions = {
|
|
266
301
|
active: '#7998ec',
|
|
267
302
|
inactive: '#eee',
|
|
@@ -274,14 +309,14 @@ const defaultOptions = {
|
|
|
274
309
|
* simple rotary Knob.
|
|
275
310
|
*/
|
|
276
311
|
function Knob(_a) {
|
|
277
|
-
var { value, min, max, defaultValue = min, startValue = min, step = 1, skew = 1, size, width = 50, height = 50, options = defaultOptions, draw, bodyNoSelect = true,
|
|
312
|
+
var { value, min, max, defaultValue = min, startValue = min, step = 1, skew = 1, size, width = 50, height = 50, options = defaultOptions, draw, bodyNoSelect = true, wheel, enableDoubleClickDefault = true, style, className, onChange, _active, _focus, _hover } = _a, props = __rest(_a, ["value", "min", "max", "defaultValue", "startValue", "step", "skew", "size", "width", "height", "options", "draw", "bodyNoSelect", "wheel", "enableDoubleClickDefault", "style", "className", "onChange", "_active", "_focus", "_hover"]);
|
|
278
313
|
// -- state and ref ---
|
|
279
314
|
// const [privateValue, setPrivateValue] = useState(value);
|
|
280
315
|
const dragOffsetY = React.useRef(undefined);
|
|
281
316
|
// --- interpret props ---
|
|
282
317
|
const opts = Object.assign(Object.assign({}, defaultOptions), options);
|
|
283
318
|
// const percent = normalizeValue(value, min, max, skew)
|
|
284
|
-
const isRelativeSize = typeof (size !== null && size !==
|
|
319
|
+
const isRelativeSize = typeof (size !== null && size !== undefined ? size : width) == 'string';
|
|
285
320
|
const adaptSize = (size) => {
|
|
286
321
|
if (typeof size == 'string') {
|
|
287
322
|
return Number(size.slice(0, -1));
|
|
@@ -296,7 +331,7 @@ function Knob(_a) {
|
|
|
296
331
|
event.preventDefault();
|
|
297
332
|
if (dragOffsetY.current) {
|
|
298
333
|
if (bodyNoSelect)
|
|
299
|
-
|
|
334
|
+
addNoSelect();
|
|
300
335
|
const screenY = isTouch ? event.touches[0].screenY : event.screenY;
|
|
301
336
|
const delta = dragOffsetY.current - screenY;
|
|
302
337
|
dragOffsetY.current = screenY;
|
|
@@ -309,12 +344,12 @@ function Knob(_a) {
|
|
|
309
344
|
};
|
|
310
345
|
// --- hooks ---
|
|
311
346
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
312
|
-
if (!
|
|
347
|
+
if (!wheel)
|
|
313
348
|
return;
|
|
314
349
|
event.preventDefault();
|
|
315
|
-
const x = event.deltaY > 0 ? -
|
|
350
|
+
const x = event.deltaY > 0 ? -wheel[1] : wheel[1];
|
|
316
351
|
let v;
|
|
317
|
-
if (
|
|
352
|
+
if (wheel[0] == 'normalized') {
|
|
318
353
|
const n = normalizeValue(value, min, max, skew);
|
|
319
354
|
v = rawValue(n + x, min, max, skew);
|
|
320
355
|
}
|
|
@@ -323,18 +358,18 @@ function Knob(_a) {
|
|
|
323
358
|
}
|
|
324
359
|
if (onChange)
|
|
325
360
|
onChange(clamp(stepValue(v, step), min, max));
|
|
326
|
-
}, { passive: false }, [
|
|
361
|
+
}, { passive: false }, [wheel, value, min, max, skew, step, onChange]);
|
|
327
362
|
const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleEvent, { passive: false }, [value, min, max, skew, step, onChange, bodyNoSelect]);
|
|
328
363
|
useEventListener(window, 'mousemove', handleEvent);
|
|
329
364
|
useEventListener(window, 'pointerup', () => {
|
|
330
365
|
dragOffsetY.current = undefined;
|
|
331
366
|
if (bodyNoSelect)
|
|
332
|
-
|
|
367
|
+
removeNoSelect();
|
|
333
368
|
});
|
|
334
369
|
return (jsxRuntime.jsxs("div", Object.assign({ className: clsx('tremolo-knob', className), ref: (div) => {
|
|
335
370
|
wheelRefCallback(div);
|
|
336
371
|
touchMoveRefCallback(div);
|
|
337
|
-
}, role: "slider", tabIndex: 0, "aria-valuenow": value, "aria-valuemax": max, "aria-valuemin": min, css: react.css(Object.assign(Object.assign({ display: 'block', width: size !== null && size !==
|
|
372
|
+
}, role: "slider", tabIndex: 0, "aria-valuenow": value, "aria-valuemax": max, "aria-valuemin": min, css: react.css(Object.assign(Object.assign({ display: 'inline-block', width: size !== null && size !== undefined ? size : width, height: size !== null && size !== undefined ? size : height, cursor: 'pointer' }, style), { ':active': Object.assign({}, _active), ':focus': Object.assign({}, _focus), ':hover': Object.assign({}, _hover) })), onPointerDown: (event) => {
|
|
338
373
|
dragOffsetY.current = event.screenY;
|
|
339
374
|
handleEvent(event);
|
|
340
375
|
}, onDoubleClick: () => {
|
|
@@ -345,7 +380,7 @@ function Knob(_a) {
|
|
|
345
380
|
'.no-select': {
|
|
346
381
|
userSelect: 'none',
|
|
347
382
|
},
|
|
348
|
-
} }), jsxRuntime.jsx(AnimationCanvas, { width: adaptSize(size !== null && size !==
|
|
383
|
+
} }), jsxRuntime.jsx(AnimationCanvas, { width: adaptSize(size !== null && size !== undefined ? size : width), height: adaptSize(size !== null && size !== undefined ? size : height), relativeSize: isRelativeSize,
|
|
349
384
|
// TODO
|
|
350
385
|
// reduceFlickering={false}
|
|
351
386
|
draw: draw ? draw : (ctx, width, height) => {
|
|
@@ -390,10 +425,21 @@ function Knob(_a) {
|
|
|
390
425
|
} })] })));
|
|
391
426
|
}
|
|
392
427
|
|
|
428
|
+
/**
|
|
429
|
+
* clamp value between min and max
|
|
430
|
+
* @category Math
|
|
431
|
+
*/
|
|
432
|
+
/**
|
|
433
|
+
*
|
|
434
|
+
* @category Math
|
|
435
|
+
*/
|
|
393
436
|
function toFixed$1(x, fractionDigits) {
|
|
394
437
|
return Number(x.toFixed(fractionDigits));
|
|
395
438
|
}
|
|
396
439
|
|
|
440
|
+
/**
|
|
441
|
+
* @module NumberInput
|
|
442
|
+
*/
|
|
397
443
|
function selectUnit(units, value) {
|
|
398
444
|
if (typeof units == 'string')
|
|
399
445
|
return [units, 1];
|
|
@@ -456,14 +502,14 @@ function parseValue(inputString, units, digit, defaultValue = 0) {
|
|
|
456
502
|
* Input with some useful functions for entering numerical values.
|
|
457
503
|
*/
|
|
458
504
|
function NumberInput(_a) {
|
|
459
|
-
var { value, min, max, step, defaultValue = min, units, disabled = false, placeholder, readOnly, tabIndex,
|
|
505
|
+
var { value, min, max, step, defaultValue = min, units, disabled = false, placeholder, readOnly, tabIndex, typeNumber = false, digit, selectWithFocus = 'none', blurWithEnter = true, className, style, onChange, onFocus, onBlur } = _a, props = __rest(_a, ["value", "min", "max", "step", "defaultValue", "units", "disabled", "placeholder", "readOnly", "tabIndex", "typeNumber", "digit", "selectWithFocus", "blurWithEnter", "className", "style", "onChange", "onFocus", "onBlur"]);
|
|
460
506
|
const [showValue, setShowValue] = React.useState(parseValue(String(value), units, digit, defaultValue).formatValue);
|
|
461
|
-
const
|
|
462
|
-
const { _active, _focus, _hover } =
|
|
463
|
-
return (jsxRuntime.jsx("input", { className: clsx('tremolo-number-input', className), value: showValue, min: min, max: max, step: step, type:
|
|
507
|
+
const calculatedTypeNumber = units ? false : typeNumber;
|
|
508
|
+
const { _active, _focus, _hover } = props, rest = __rest(props, ["_active", "_focus", "_hover"]);
|
|
509
|
+
return (jsxRuntime.jsx("input", Object.assign({ className: clsx('tremolo-number-input', className), value: showValue, min: min, max: max, step: step, type: calculatedTypeNumber ? 'number' : 'text', spellCheck: 'false', disabled: disabled, placeholder: placeholder, readOnly: readOnly, tabIndex: tabIndex, css: react.css(Object.assign(Object.assign({ display: 'inline-block', font: 'inherit', margin: 0, paddingTop: 6, paddingBottom: 6, paddingLeft: 10, paddingRight: 10, borderStyle: 'solid', borderWidth: 1, borderColor: '#bbb', borderRadius: 4, outline: 0, transition: 'all 0.1s linear', appearance: 'textfield', '&:hover': Object.assign({ borderColor: 'var(--tremolo-theme-color)' }, _hover), '&:focus': Object.assign({ borderColor: 'var(--tremolo-theme-color)', boxShadow: '0px 0px 0px 2px rgba(var(--tremolo-theme-color-rgb), 0.1)' }, _focus) }, (_active && { '&:active': Object.assign({}, _active) })), style)), onChange: (event) => {
|
|
464
510
|
const v = event.currentTarget.value;
|
|
465
511
|
setShowValue(v);
|
|
466
|
-
const newValue = clamp(parseValue(v, units, digit, defaultValue).rawValue, min !== null && min !==
|
|
512
|
+
const newValue = clamp(parseValue(v, units, digit, defaultValue).rawValue, min !== null && min !== undefined ? min : -Infinity, max !== null && max !== undefined ? max : Infinity);
|
|
467
513
|
if (onChange)
|
|
468
514
|
onChange(newValue, event);
|
|
469
515
|
}, onFocus: (event) => {
|
|
@@ -488,16 +534,31 @@ function NumberInput(_a) {
|
|
|
488
534
|
if (blurWithEnter && event.key == 'Enter') {
|
|
489
535
|
event.currentTarget.blur();
|
|
490
536
|
}
|
|
491
|
-
} }));
|
|
537
|
+
} }, rest)));
|
|
492
538
|
}
|
|
493
539
|
|
|
540
|
+
/**
|
|
541
|
+
* clamp value between min and max
|
|
542
|
+
* @category Math
|
|
543
|
+
*/
|
|
544
|
+
/**
|
|
545
|
+
*
|
|
546
|
+
* @category Math
|
|
547
|
+
*/
|
|
494
548
|
function toFixed(x, fractionDigits) {
|
|
495
549
|
return Number(x.toFixed(fractionDigits));
|
|
496
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
*
|
|
553
|
+
* @category Math
|
|
554
|
+
*/
|
|
497
555
|
function decimalPart(x) {
|
|
498
556
|
return String(x).split('.')[1];
|
|
499
557
|
}
|
|
500
558
|
|
|
559
|
+
/**
|
|
560
|
+
* @module Slider
|
|
561
|
+
*/
|
|
501
562
|
function isHorizontal(d) {
|
|
502
563
|
return d == 'right' || d == 'left';
|
|
503
564
|
}
|
|
@@ -526,46 +587,76 @@ function parseScaleOrderList(scale, min, max, step) {
|
|
|
526
587
|
const per = scale[0] == 'step' ? step : scale[0];
|
|
527
588
|
const count = Math.floor(max / per) - Math.ceil(min / per) + 1;
|
|
528
589
|
for (let i = 0; i < count; i++) {
|
|
529
|
-
const at = toFixed(per * (Math.ceil(min / per) + i), (_a = decimalPart(per)) === null || _a ===
|
|
590
|
+
const at = toFixed(per * (Math.ceil(min / per) + i), (_a = decimalPart(per)) === null || _a === undefined ? undefined : _a.length);
|
|
530
591
|
scalesList.push({ at: at, type: scale[1] });
|
|
531
592
|
}
|
|
532
593
|
}
|
|
533
594
|
return scalesList;
|
|
534
595
|
}
|
|
535
596
|
|
|
536
|
-
|
|
537
|
-
|
|
597
|
+
const SliderThumb = React.forwardRef(({ size, width = 22, height = 22, color = '#4e76e6', hoverColor = color, disabledColor = '#5d6478', disabledHoverColor = disabledColor, zIndex = 100, children, className, style, __disabled, __css, }, ref) => {
|
|
598
|
+
const wrapperRef = React.useRef(null);
|
|
599
|
+
React.useImperativeHandle(ref, () => {
|
|
600
|
+
return {
|
|
601
|
+
focus() {
|
|
602
|
+
var _a;
|
|
603
|
+
(_a = wrapperRef.current) === null || _a === undefined ? undefined : _a.focus();
|
|
604
|
+
},
|
|
605
|
+
blur() {
|
|
606
|
+
var _a;
|
|
607
|
+
(_a = wrapperRef.current) === null || _a === undefined ? undefined : _a.blur();
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
}, []);
|
|
611
|
+
return (jsxRuntime.jsx("div", { className: "tremolo-slider-thumb-wrapper", css: react.css(Object.assign({ position: 'absolute', translate: '-50% -50%', zIndex: zIndex }, __css)), children: children ? (children) : (
|
|
538
612
|
// default slider thumb
|
|
539
|
-
jsxRuntime.jsx("div", { className:
|
|
613
|
+
jsxRuntime.jsx("div", { ref: wrapperRef, className: clsx('tremolo-slider-thumb', className),
|
|
540
614
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
541
|
-
tabIndex: 0, css: react.css(Object.assign({ background: color, width:
|
|
542
|
-
background:
|
|
543
|
-
}, '&:
|
|
615
|
+
tabIndex: 0, css: react.css(Object.assign({ background: __disabled ? disabledColor : color, width: size !== null && size !== undefined ? size : width, height: size !== null && size !== undefined ? size : height, borderRadius: '50%', outline: 'none', '&:hover': {
|
|
616
|
+
background: __disabled ? disabledHoverColor : hoverColor
|
|
617
|
+
}, '&:focus': !__disabled && {
|
|
544
618
|
boxShadow: '0px 0px 0px 3px rgba(var(--tremolo-theme-color-rgb), 0.2)',
|
|
545
619
|
} }, style)) })) }));
|
|
546
|
-
}
|
|
620
|
+
});
|
|
547
621
|
|
|
548
|
-
function SliderTrack({ children, style,
|
|
549
|
-
|
|
622
|
+
function SliderTrack({ length = 140, thickness = 10, activeBg = '#7998ec', inactiveBg = '#eee', activeHoverBg = '#6387e9', inactiveHoverBg = '#e0e0e0', disabledActiveBg = '#858890', disabledInactiveBg = '#ddd', disabledActiveHoverBg = disabledActiveBg, disabledInactiveHoverBg = disabledInactiveBg, children, className, style, __thumb, __direction, __disabled, __percent, }) {
|
|
623
|
+
const active = __disabled ? disabledActiveBg : activeBg;
|
|
624
|
+
const inactive = __disabled ? disabledInactiveBg : inactiveBg;
|
|
625
|
+
const activeHover = __disabled ? disabledActiveHoverBg : activeHoverBg;
|
|
626
|
+
const inactiveHover = __disabled ? disabledInactiveHoverBg : inactiveHoverBg;
|
|
627
|
+
return (jsxRuntime.jsxs("div", { className: clsx('tremolo-slider-track', className), css: react.css(Object.assign({ position: 'relative', background: `linear-gradient(to ${gradientDirection(__direction)}, ${active} ${__percent}%, ${inactive} ${__percent}%)`, borderRadius: styleHelper(thickness, '/', 2), width: isHorizontal(__direction) ? length : thickness, height: isHorizontal(__direction) ? thickness : length, ':hover': {
|
|
628
|
+
background: `linear-gradient(to ${gradientDirection(__direction)}, ${activeHover} ${__percent}%, ${inactiveHover} ${__percent}%)`
|
|
629
|
+
} }, style)), children: [children, __thumb] }));
|
|
550
630
|
}
|
|
551
631
|
|
|
552
632
|
/**
|
|
553
633
|
* Customizable slider
|
|
554
634
|
*/
|
|
555
|
-
|
|
556
|
-
var _b, _c;
|
|
557
|
-
var { value, min, max, step = 1, skew = 1,
|
|
635
|
+
const Slider = React.forwardRef((_a, ref) => {
|
|
636
|
+
var _b, _c, _d, _e, _f, _g, _h;
|
|
637
|
+
var { value, min, max, step = 1, skew = 1, direction = 'right', scale, scaleOption, className, style, bodyNoSelect = true, wheel = ['raw', 1], keyboard = ['raw', 1], disabled = false, readonly = false, onChange, children } = _a; __rest(_a, ["value", "min", "max", "step", "skew", "direction", "scale", "scaleOption", "className", "style", "bodyNoSelect", "wheel", "keyboard", "disabled", "readonly", "onChange", "children"]);
|
|
558
638
|
// -- state and ref ---
|
|
559
639
|
const trackElementRef = React.useRef(null);
|
|
560
|
-
const
|
|
561
|
-
const
|
|
640
|
+
const thumbRef = React.useRef(null);
|
|
641
|
+
const thumbDragged = React.useRef(false);
|
|
642
|
+
const percent = toFixed$2(normalizeValue(value, min, max, skew) * 100);
|
|
643
|
+
const percentRev = isReversed(direction) ? toFixed$2(100 - percent) : percent;
|
|
644
|
+
const calcPercent = (v) => {
|
|
645
|
+
return toFixed$2(isReversed(direction)
|
|
646
|
+
? 100 - normalizeValue(v, min, max, skew) * 100
|
|
647
|
+
: normalizeValue(v, min, max, skew) * 100);
|
|
648
|
+
};
|
|
649
|
+
if (wheel.length != 2) {
|
|
650
|
+
throw new Error(`Slider.wheel expect ['normalized' | 'raw', number]`);
|
|
651
|
+
}
|
|
652
|
+
if (keyboard.length != 2) {
|
|
653
|
+
throw new Error(`Slider.keyboard expect ['normalized' | 'raw', number]`);
|
|
654
|
+
}
|
|
562
655
|
const scalesList = parseScaleOrderList(scale, min, max, step);
|
|
563
656
|
if (isReversed(direction))
|
|
564
657
|
scalesList.reverse();
|
|
565
658
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
566
|
-
let trackProps;
|
|
567
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
568
|
-
let thumbProps;
|
|
659
|
+
let trackProps, thumbProps;
|
|
569
660
|
if (children != undefined) {
|
|
570
661
|
React.Children.forEach(children, (child) => {
|
|
571
662
|
if (React.isValidElement(child)) {
|
|
@@ -584,15 +675,15 @@ function Slider(_a) {
|
|
|
584
675
|
}
|
|
585
676
|
});
|
|
586
677
|
}
|
|
587
|
-
|
|
678
|
+
// --- internal functions ---
|
|
588
679
|
const handleValue = (event) => {
|
|
589
|
-
if (!trackElementRef.current || !thumbDragged.current)
|
|
680
|
+
if (!trackElementRef.current || !thumbDragged.current || !onChange || readonly)
|
|
590
681
|
return;
|
|
591
682
|
const isTouch = event instanceof TouchEvent;
|
|
592
683
|
if (isTouch && event.cancelable)
|
|
593
684
|
event.preventDefault();
|
|
594
685
|
if (bodyNoSelect)
|
|
595
|
-
|
|
686
|
+
addNoSelect();
|
|
596
687
|
const { left: x1, top: y1, right: x2, bottom: y2, } = trackElementRef.current.getBoundingClientRect();
|
|
597
688
|
const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
|
|
598
689
|
const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
|
|
@@ -600,70 +691,90 @@ function Slider(_a) {
|
|
|
600
691
|
? normalizeValue(mouseX, x1, x2)
|
|
601
692
|
: normalizeValue(mouseY, y1, y2);
|
|
602
693
|
const v = rawValue(isReversed(direction) ? 1 - n : n, min, max, skew);
|
|
603
|
-
|
|
604
|
-
if (onChange)
|
|
605
|
-
onChange(v2);
|
|
694
|
+
onChange(clamp(stepValue(v, step), min, max));
|
|
606
695
|
};
|
|
696
|
+
const handleKeyDown = React.useCallback((event) => {
|
|
697
|
+
if (!keyboard || !onChange || readonly)
|
|
698
|
+
return;
|
|
699
|
+
const key = event.key;
|
|
700
|
+
if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {
|
|
701
|
+
event.preventDefault();
|
|
702
|
+
let x = (key == 'ArrowRight' || key == 'ArrowUp') ? keyboard[1] : -keyboard[1];
|
|
703
|
+
if (direction == 'down' || direction == 'left')
|
|
704
|
+
x *= -1;
|
|
705
|
+
let v;
|
|
706
|
+
if (keyboard[0] == 'normalized') {
|
|
707
|
+
const n = normalizeValue(value, min, max, skew);
|
|
708
|
+
v = rawValue(n + x, min, max, skew);
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
v = value + x;
|
|
712
|
+
}
|
|
713
|
+
onChange(clamp(stepValue(v, step), min, max));
|
|
714
|
+
}
|
|
715
|
+
}, [value, min, max, step, skew, direction, keyboard, onChange, readonly]);
|
|
607
716
|
// --- hooks ---
|
|
608
|
-
const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleValue, { passive: false }, [min, max, skew, step, direction, onChange]);
|
|
717
|
+
const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleValue, { passive: false }, [min, max, skew, step, direction, onChange, readonly]);
|
|
609
718
|
const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
|
|
610
|
-
if (!
|
|
719
|
+
if (!wheel || !onChange || readonly)
|
|
611
720
|
return;
|
|
612
721
|
event.preventDefault();
|
|
613
|
-
let x = event.deltaY > 0 ?
|
|
722
|
+
let x = event.deltaY > 0 ? wheel[1] : -wheel[1];
|
|
614
723
|
if (isReversed(direction) || isHorizontal(direction))
|
|
615
724
|
x *= -1;
|
|
616
725
|
let v;
|
|
617
|
-
if (
|
|
726
|
+
if (wheel[0] == 'normalized') {
|
|
618
727
|
const n = normalizeValue(value, min, max, skew);
|
|
619
728
|
v = rawValue(n + x, min, max, skew);
|
|
620
729
|
}
|
|
621
730
|
else {
|
|
622
731
|
v = value + x;
|
|
623
732
|
}
|
|
624
|
-
|
|
625
|
-
onChange(clamp(stepValue(v, step), min, max));
|
|
733
|
+
onChange(clamp(stepValue(v, step), min, max));
|
|
626
734
|
}, {
|
|
627
735
|
passive: false,
|
|
628
|
-
}, [
|
|
736
|
+
}, [wheel, value, min, max, skew, step]);
|
|
629
737
|
useEventListener(window, 'mousemove', (event) => {
|
|
630
738
|
handleValue(event);
|
|
631
739
|
});
|
|
632
740
|
useEventListener(window, 'mouseup', () => {
|
|
633
741
|
thumbDragged.current = false;
|
|
634
742
|
if (bodyNoSelect)
|
|
635
|
-
|
|
743
|
+
removeNoSelect();
|
|
636
744
|
});
|
|
745
|
+
React.useImperativeHandle(ref, () => {
|
|
746
|
+
return {
|
|
747
|
+
focus() {
|
|
748
|
+
var _a;
|
|
749
|
+
(_a = thumbRef.current) === null || _a === undefined ? undefined : _a.focus();
|
|
750
|
+
},
|
|
751
|
+
blur() {
|
|
752
|
+
var _a;
|
|
753
|
+
(_a = thumbRef.current) === null || _a === undefined ? undefined : _a.blur();
|
|
754
|
+
},
|
|
755
|
+
};
|
|
756
|
+
}, []);
|
|
637
757
|
return (jsxRuntime.jsxs("div", { className: clsx('tremolo-slider', className), ref: (div) => {
|
|
638
758
|
wheelRefCallback(div);
|
|
639
759
|
touchMoveRefCallback(div);
|
|
640
|
-
}, tabIndex: -1, role: "slider", "aria-valuenow": value, "aria-
|
|
760
|
+
}, tabIndex: -1, role: "slider", "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-orientation": isHorizontal(direction) ? 'horizontal' : 'vertical', "aria-disabled": disabled, "aria-readonly": readonly, css: react.css(Object.assign({ display: 'inline-block', margin: `calc(${styleHelper((_b = thumbProps === null || thumbProps === undefined ? undefined : thumbProps.size) !== null && _b !== undefined ? _b : 22)} / 2)`, cursor: readonly ? 'not-allowed' : 'pointer', outline: 0 }, style)), onPointerDown: (event) => {
|
|
641
761
|
thumbDragged.current = true;
|
|
642
762
|
handleValue(event);
|
|
643
|
-
}, children: [jsxRuntime.jsx(react.Global, { styles: {
|
|
763
|
+
}, onKeyDown: handleKeyDown, onFocus: (_c = thumbRef.current) === null || _c === undefined ? undefined : _c.focus, onBlur: (_d = thumbRef.current) === null || _d === undefined ? undefined : _d.blur, children: [jsxRuntime.jsx(react.Global, { styles: {
|
|
644
764
|
'.no-select': {
|
|
645
765
|
userSelect: 'none',
|
|
646
766
|
},
|
|
647
767
|
} }), jsxRuntime.jsxs("div", { css: react.css({
|
|
648
768
|
display: 'flex',
|
|
649
769
|
flexDirection: isHorizontal(direction) ? 'column' : 'row',
|
|
650
|
-
}), children: [jsxRuntime.
|
|
651
|
-
background: `linear-gradient(to ${gradientDirection(direction)}, ${color} ${percent}%, ${bg} ${percent}%)`,
|
|
652
|
-
borderRadius: styleHelper(thickness, '/', 2),
|
|
653
|
-
borderStyle: 'solid',
|
|
654
|
-
borderColor: '#ccc',
|
|
655
|
-
borderWidth: 2,
|
|
656
|
-
width: isHorizontal(direction) ? length : thickness,
|
|
657
|
-
height: isHorizontal(direction) ? thickness : length,
|
|
658
|
-
zIndex: 1,
|
|
659
|
-
} }, trackProps)), jsxRuntime.jsx(SliderThumb, Object.assign({ color: color, __css: {
|
|
770
|
+
}), children: [jsxRuntime.jsx("div", { className: "tremolo-slider-track-wrapper", ref: trackElementRef, children: jsxRuntime.jsx(SliderTrack, Object.assign({ __direction: direction, __disabled: disabled, __percent: percent, __thumb: jsxRuntime.jsx(SliderThumb, Object.assign({ ref: thumbRef, __disabled: disabled, __css: {
|
|
660
771
|
top: isHorizontal(direction) ? '50%' : `${percentRev}%`,
|
|
661
772
|
left: isHorizontal(direction) ? `${percentRev}%` : '50%',
|
|
662
|
-
} }, thumbProps))
|
|
663
|
-
? 2
|
|
664
|
-
:
|
|
665
|
-
? 2
|
|
666
|
-
:
|
|
773
|
+
} }, thumbProps)) }, trackProps)) }), scale && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-wrapper", css: react.css(Object.assign({ display: 'block', position: 'relative', marginLeft: isVertical(direction)
|
|
774
|
+
? ((_e = scaleOption === null || scaleOption === undefined ? undefined : scaleOption.gap) !== null && _e !== undefined ? _e : `calc((22px - ${styleHelper((_f = trackProps === null || trackProps === undefined ? undefined : trackProps.thickness) !== null && _f !== undefined ? _f : 10)}) / 2)`)
|
|
775
|
+
: undefined, marginTop: isHorizontal(direction)
|
|
776
|
+
? ((_g = scaleOption === null || scaleOption === undefined ? undefined : scaleOption.gap) !== null && _g !== undefined ? _g : `calc((22px - ${styleHelper((_h = trackProps === null || trackProps === undefined ? undefined : trackProps.thickness) !== null && _h !== undefined ? _h : 10)}) / 2)`)
|
|
777
|
+
: undefined }, scaleOption === null || scaleOption === undefined ? undefined : scaleOption.style)), children: scalesList.map((item, index) => {
|
|
667
778
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
668
779
|
return (jsxRuntime.jsxs("div", { css: react.css({
|
|
669
780
|
display: 'flex',
|
|
@@ -671,37 +782,29 @@ function Slider(_a) {
|
|
|
671
782
|
justifyContent: 'center',
|
|
672
783
|
alignItems: 'center',
|
|
673
784
|
position: 'absolute',
|
|
674
|
-
left: isHorizontal(direction)
|
|
675
|
-
|
|
676
|
-
? 100 - normalizeValue(item.at, min, max, skew) * 100
|
|
677
|
-
: normalizeValue(item.at, min, max, skew) * 100}%`
|
|
678
|
-
: undefined,
|
|
679
|
-
top: isVertical(direction)
|
|
680
|
-
? `${isReversed(direction)
|
|
681
|
-
? 100 - normalizeValue(item.at, min, max, skew) * 100
|
|
682
|
-
: normalizeValue(item.at, min, max, skew) * 100}%`
|
|
683
|
-
: undefined,
|
|
785
|
+
left: isHorizontal(direction) ? `${calcPercent(item.at)}%` : undefined,
|
|
786
|
+
top: isVertical(direction) ? `${calcPercent(item.at)}%` : undefined,
|
|
684
787
|
translate: isHorizontal(direction) ? '-50% 0' : '0 -50%',
|
|
685
788
|
zIndex: 10,
|
|
686
|
-
}), children: [((_b = (_a = item.type) !== null && _a !==
|
|
789
|
+
}), children: [((_b = (_a = item.type) !== null && _a !== undefined ? _a : scaleOption === null || scaleOption === undefined ? undefined : scaleOption.defaultType) !== null && _b !== undefined ? _b : 'mark-number') !=
|
|
687
790
|
'number' && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-mark", css: react.css({
|
|
688
791
|
width: isHorizontal(direction)
|
|
689
|
-
? ((_d = (_c = item.style) === null || _c ===
|
|
690
|
-
: ((_f = (_e = item.style) === null || _e ===
|
|
792
|
+
? ((_d = (_c = item.style) === null || _c === undefined ? undefined : _c.thickness) !== null && _d !== undefined ? _d : 1)
|
|
793
|
+
: ((_f = (_e = item.style) === null || _e === undefined ? undefined : _e.length) !== null && _f !== undefined ? _f : '0.5rem'),
|
|
691
794
|
height: isVertical(direction)
|
|
692
|
-
? ((_h = (_g = item.style) === null || _g ===
|
|
693
|
-
: ((_k = (_j = item.style) === null || _j ===
|
|
694
|
-
backgroundColor: (_o = (_m = (_l = item.style) === null || _l ===
|
|
795
|
+
? ((_h = (_g = item.style) === null || _g === undefined ? undefined : _g.thickness) !== null && _h !== undefined ? _h : 1)
|
|
796
|
+
: ((_k = (_j = item.style) === null || _j === undefined ? undefined : _j.length) !== null && _k !== undefined ? _k : '0.5rem'),
|
|
797
|
+
backgroundColor: (_o = (_m = (_l = item.style) === null || _l === undefined ? undefined : _l.markColor) !== null && _m !== undefined ? _m : scaleOption === null || scaleOption === undefined ? undefined : scaleOption.markColor) !== null && _o !== undefined ? _o : '#222',
|
|
695
798
|
marginBottom: isHorizontal(direction) ? 2 : undefined,
|
|
696
799
|
marginRight: isVertical(direction) ? 2 : undefined,
|
|
697
|
-
}) })), ((_q = (_p = item.type) !== null && _p !==
|
|
800
|
+
}) })), ((_q = (_p = item.type) !== null && _p !== undefined ? _p : scaleOption === null || scaleOption === undefined ? undefined : scaleOption.defaultType) !== null && _q !== undefined ? _q : 'mark-number') !=
|
|
698
801
|
'mark' && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-number", css: react.css({
|
|
699
|
-
color: (_s = (_r = item.style) === null || _r ===
|
|
700
|
-
width: scaleOption === null || scaleOption ===
|
|
802
|
+
color: (_s = (_r = item.style) === null || _r === undefined ? undefined : _r.labelColor) !== null && _s !== undefined ? _s : scaleOption === null || scaleOption === undefined ? undefined : scaleOption.labelColor,
|
|
803
|
+
width: scaleOption === null || scaleOption === undefined ? undefined : scaleOption.labelWidth,
|
|
701
804
|
textAlign: 'right',
|
|
702
|
-
}), children: (_t = item.text) !== null && _t !==
|
|
805
|
+
}), children: (_t = item.text) !== null && _t !== undefined ? _t : item.at }))] }, index));
|
|
703
806
|
}) }))] })] }));
|
|
704
|
-
}
|
|
807
|
+
});
|
|
705
808
|
|
|
706
809
|
exports.AnimationCanvas = AnimationCanvas;
|
|
707
810
|
exports.Knob = Knob;
|