@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.
Files changed (148) hide show
  1. package/dist/cjs/index.js +439 -275
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/AnimationCanvas/index.d.ts +9 -4
  4. package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +1 -1
  5. package/dist/cjs/types/components/AnimationKnob/index.d.ts +2 -0
  6. package/dist/cjs/types/components/AnimationKnob/index.d.ts.map +1 -1
  7. package/dist/cjs/types/components/DragObserver/index.d.ts +3 -1
  8. package/dist/cjs/types/components/DragObserver/index.d.ts.map +1 -1
  9. package/dist/cjs/types/components/Knob/index.d.ts +2 -0
  10. package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
  11. package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts +7 -0
  12. package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts.map +1 -0
  13. package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts +7 -0
  14. package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts.map +1 -0
  15. package/dist/cjs/types/components/NumberInput/Stepper.d.ts +8 -0
  16. package/dist/cjs/types/components/NumberInput/Stepper.d.ts.map +1 -0
  17. package/dist/cjs/types/components/NumberInput/context.d.ts +27 -0
  18. package/dist/cjs/types/components/NumberInput/context.d.ts.map +1 -0
  19. package/dist/cjs/types/components/NumberInput/index.d.ts +31 -16
  20. package/dist/cjs/types/components/NumberInput/index.d.ts.map +1 -1
  21. package/dist/cjs/types/components/Piano/BlackKey.d.ts +1 -0
  22. package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +1 -1
  23. package/dist/cjs/types/components/Piano/KeyLabel.d.ts +2 -0
  24. package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +1 -1
  25. package/dist/cjs/types/components/Piano/WhiteKey.d.ts +3 -0
  26. package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +1 -1
  27. package/dist/cjs/types/components/Piano/index.d.ts +6 -4
  28. package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
  29. package/dist/cjs/types/components/Piano/key.d.ts +8 -2
  30. package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
  31. package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +2 -0
  32. package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts.map +1 -1
  33. package/dist/cjs/types/components/Slider/Scale.d.ts +2 -0
  34. package/dist/cjs/types/components/Slider/Scale.d.ts.map +1 -1
  35. package/dist/cjs/types/components/Slider/ScaleOption.d.ts +2 -0
  36. package/dist/cjs/types/components/Slider/ScaleOption.d.ts.map +1 -1
  37. package/dist/cjs/types/components/Slider/Thumb.d.ts +4 -0
  38. package/dist/cjs/types/components/Slider/Thumb.d.ts.map +1 -1
  39. package/dist/cjs/types/components/Slider/Track.d.ts +6 -1
  40. package/dist/cjs/types/components/Slider/Track.d.ts.map +1 -1
  41. package/dist/cjs/types/components/Slider/context.d.ts +15 -12
  42. package/dist/cjs/types/components/Slider/context.d.ts.map +1 -1
  43. package/dist/cjs/types/components/Slider/index.d.ts +8 -5
  44. package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
  45. package/dist/cjs/types/components/WheelObserver/index.d.ts +1 -0
  46. package/dist/cjs/types/components/WheelObserver/index.d.ts.map +1 -1
  47. package/dist/cjs/types/components/XYPad/Area.d.ts +2 -0
  48. package/dist/cjs/types/components/XYPad/Area.d.ts.map +1 -1
  49. package/dist/cjs/types/components/XYPad/Thumb.d.ts +3 -0
  50. package/dist/cjs/types/components/XYPad/Thumb.d.ts.map +1 -1
  51. package/dist/cjs/types/components/XYPad/index.d.ts +4 -0
  52. package/dist/cjs/types/components/XYPad/index.d.ts.map +1 -1
  53. package/dist/cjs/types/hooks/useAnimationFrame.d.ts +3 -0
  54. package/dist/cjs/types/hooks/useAnimationFrame.d.ts.map +1 -0
  55. package/dist/cjs/types/hooks/useDrag.d.ts +15 -0
  56. package/dist/cjs/types/hooks/useDrag.d.ts.map +1 -0
  57. package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts +1 -4
  58. package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts.map +1 -1
  59. package/dist/esm/index.js +437 -266
  60. package/dist/esm/index.js.map +1 -1
  61. package/dist/esm/types/components/AnimationCanvas/index.d.ts +9 -4
  62. package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +1 -1
  63. package/dist/esm/types/components/AnimationKnob/index.d.ts +2 -0
  64. package/dist/esm/types/components/AnimationKnob/index.d.ts.map +1 -1
  65. package/dist/esm/types/components/DragObserver/index.d.ts +3 -1
  66. package/dist/esm/types/components/DragObserver/index.d.ts.map +1 -1
  67. package/dist/esm/types/components/Knob/index.d.ts +2 -0
  68. package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
  69. package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts +7 -0
  70. package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts.map +1 -0
  71. package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts +7 -0
  72. package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts.map +1 -0
  73. package/dist/esm/types/components/NumberInput/Stepper.d.ts +8 -0
  74. package/dist/esm/types/components/NumberInput/Stepper.d.ts.map +1 -0
  75. package/dist/esm/types/components/NumberInput/context.d.ts +27 -0
  76. package/dist/esm/types/components/NumberInput/context.d.ts.map +1 -0
  77. package/dist/esm/types/components/NumberInput/index.d.ts +31 -16
  78. package/dist/esm/types/components/NumberInput/index.d.ts.map +1 -1
  79. package/dist/esm/types/components/Piano/BlackKey.d.ts +1 -0
  80. package/dist/esm/types/components/Piano/BlackKey.d.ts.map +1 -1
  81. package/dist/esm/types/components/Piano/KeyLabel.d.ts +2 -0
  82. package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +1 -1
  83. package/dist/esm/types/components/Piano/WhiteKey.d.ts +3 -0
  84. package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +1 -1
  85. package/dist/esm/types/components/Piano/index.d.ts +6 -4
  86. package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
  87. package/dist/esm/types/components/Piano/key.d.ts +8 -2
  88. package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
  89. package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +2 -0
  90. package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts.map +1 -1
  91. package/dist/esm/types/components/Slider/Scale.d.ts +2 -0
  92. package/dist/esm/types/components/Slider/Scale.d.ts.map +1 -1
  93. package/dist/esm/types/components/Slider/ScaleOption.d.ts +2 -0
  94. package/dist/esm/types/components/Slider/ScaleOption.d.ts.map +1 -1
  95. package/dist/esm/types/components/Slider/Thumb.d.ts +4 -0
  96. package/dist/esm/types/components/Slider/Thumb.d.ts.map +1 -1
  97. package/dist/esm/types/components/Slider/Track.d.ts +6 -1
  98. package/dist/esm/types/components/Slider/Track.d.ts.map +1 -1
  99. package/dist/esm/types/components/Slider/context.d.ts +15 -12
  100. package/dist/esm/types/components/Slider/context.d.ts.map +1 -1
  101. package/dist/esm/types/components/Slider/index.d.ts +8 -5
  102. package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
  103. package/dist/esm/types/components/WheelObserver/index.d.ts +1 -0
  104. package/dist/esm/types/components/WheelObserver/index.d.ts.map +1 -1
  105. package/dist/esm/types/components/XYPad/Area.d.ts +2 -0
  106. package/dist/esm/types/components/XYPad/Area.d.ts.map +1 -1
  107. package/dist/esm/types/components/XYPad/Thumb.d.ts +3 -0
  108. package/dist/esm/types/components/XYPad/Thumb.d.ts.map +1 -1
  109. package/dist/esm/types/components/XYPad/index.d.ts +4 -0
  110. package/dist/esm/types/components/XYPad/index.d.ts.map +1 -1
  111. package/dist/esm/types/hooks/useAnimationFrame.d.ts +3 -0
  112. package/dist/esm/types/hooks/useAnimationFrame.d.ts.map +1 -0
  113. package/dist/esm/types/hooks/useDrag.d.ts +15 -0
  114. package/dist/esm/types/hooks/useDrag.d.ts.map +1 -0
  115. package/dist/esm/types/hooks/useRefCallbackEvent.d.ts +1 -4
  116. package/dist/esm/types/hooks/useRefCallbackEvent.d.ts.map +1 -1
  117. package/dist/styles/index.css +110 -13
  118. package/package.json +8 -5
  119. package/src/components/AnimationCanvas/index.tsx +13 -4
  120. package/src/components/AnimationKnob/index.tsx +24 -42
  121. package/src/components/DragObserver/index.tsx +14 -52
  122. package/src/components/Knob/index.tsx +23 -40
  123. package/src/components/NumberInput/DecrementStepper.tsx +52 -0
  124. package/src/components/NumberInput/IncrementStepper.tsx +52 -0
  125. package/src/components/NumberInput/Stepper.tsx +25 -0
  126. package/src/components/NumberInput/context.tsx +150 -0
  127. package/src/components/NumberInput/index.css +102 -13
  128. package/src/components/NumberInput/index.tsx +164 -55
  129. package/src/components/Piano/BlackKey.tsx +15 -11
  130. package/src/components/Piano/KeyLabel.tsx +2 -0
  131. package/src/components/Piano/WhiteKey.tsx +17 -11
  132. package/src/components/Piano/index.tsx +16 -14
  133. package/src/components/Piano/key.ts +8 -2
  134. package/src/components/Piano/keyboardShortcuts.ts +2 -0
  135. package/src/components/Slider/Scale.tsx +8 -6
  136. package/src/components/Slider/ScaleOption.tsx +8 -6
  137. package/src/components/Slider/Thumb.tsx +7 -3
  138. package/src/components/Slider/Track.tsx +27 -15
  139. package/src/components/Slider/context.tsx +65 -51
  140. package/src/components/Slider/index.css +8 -0
  141. package/src/components/Slider/index.tsx +19 -10
  142. package/src/components/WheelObserver/index.tsx +1 -0
  143. package/src/components/XYPad/Area.tsx +2 -0
  144. package/src/components/XYPad/Thumb.tsx +3 -0
  145. package/src/components/XYPad/index.tsx +6 -2
  146. package/src/hooks/useAnimationFrame.ts +18 -0
  147. package/src/hooks/useDrag.ts +92 -0
  148. 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, createContext, useContext } from 'react';
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$2(quotient * step, decimalDigits);
193
- const next = toFixed$2((quotient + 1) * step, decimalDigits);
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$2(x, fractionDigits) {
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
- // const [privateValue, setPrivateValue] = useState(value);
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 handleEvent = (event) => {
387
- const isTouch = event instanceof TouchEvent;
388
- if (isTouch && event.cancelable)
389
- event.preventDefault();
390
- if (dragOffsetY.current) {
391
- if (bodyNoSelect)
392
- addNoSelect();
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: (event) => {
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, as: Component = 'div' } = props, attributes = __rest(props, ["children", "onDrag", "onDragStart", "onDragEnd", "as"]);
508
- const dragOffsetX = useRef(undefined);
509
- const dragOffsetY = useRef(undefined);
510
- const handleEvent = (event) => {
511
- const isTouch = event instanceof TouchEvent;
512
- if (isTouch && event.cancelable)
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: touchMoveRefCallback, onPointerDown: (event) => {
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
- // -- state and ref ---
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 handleEvent = (event) => {
570
+ const onDrag = useCallback((_x, y) => {
558
571
  if (!onChange || readonly)
559
572
  return;
560
- const isTouch = event instanceof TouchEvent;
561
- if (isTouch && event.cancelable)
562
- event.preventDefault();
563
- if (dragOffsetY.current) {
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: (event) => {
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, defaultValue = 0) {
671
- let str = inputString.trim();
672
- if (str == '')
673
- str = String(defaultValue);
674
- if (!units) {
675
- return {
676
- rawValue: Number(str) || defaultValue,
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: Number(str) || defaultValue,
684
- formatValue: `${str}${units}`,
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 = defaultValue;
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 inputUnit = m[3];
697
- if (inputUnit != '' && unitList.indexOf(inputUnit) != -1) {
698
- rawValue *= scaleList[unitList.indexOf(inputUnit)];
699
- const s = selectUnit(units, rawValue);
700
- const v = rawValue / s[1];
701
- formatValue = `${digit != undefined ? toFixed$1(v, digit) : v}${s[0]}`;
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
- * Input with some useful functions for entering numerical values.
720
- */
721
- function NumberInput(_a) {
722
- var { value, min, max, step, defaultValue = min, units, disabled = false, placeholder, readOnly, tabIndex, typeNumber = false, digit, selectWithFocus = 'none', blurWithEnter = true, className, onChange, onFocus, onBlur } = _a, props = __rest(_a, ["value", "min", "max", "step", "defaultValue", "units", "disabled", "placeholder", "readOnly", "tabIndex", "typeNumber", "digit", "selectWithFocus", "blurWithEnter", "className", "onChange", "onFocus", "onBlur"]);
723
- const [showValue, setShowValue] = useState(parseValue(String(value), units, digit, defaultValue).formatValue);
724
- const calculatedTypeNumber = units ? false : typeNumber;
725
- return (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, onChange: (event) => {
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
- setShowValue(v);
728
- const newValue = clamp(parseValue(v, units, digit, defaultValue).rawValue, min !== null && min !== void 0 ? min : -Infinity, max !== null && max !== void 0 ? max : Infinity);
729
- if (onChange)
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, defaultValue);
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
- if (onFocus)
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
- const v = event.currentTarget.value;
745
- const parsed = parseValue(v, units, digit, defaultValue);
746
- setShowValue(parsed.formatValue);
747
- if (onBlur)
748
- onBlur(parsed.rawValue, event);
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 (blurWithEnter && event.key == 'Enter') {
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
- const BlackKey = forwardRef((_a, ref) => {
765
- var { width = 40 * 0.65, height = '60%', className, style, children, __glissando, __position, __note, __disabled, __index, __fill, __width, __playNote, __stopNote, __label } = _a, props = __rest(_a, ["width", "height", "className", "style", "children", "__glissando", "__position", "__note", "__disabled", "__index", "__fill", "__width", "__playNote", "__stopNote", "__label"]);
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 (__playNote)
774
- __playNote(__note);
910
+ if (__onPlayNote)
911
+ __onPlayNote(__note);
775
912
  },
776
913
  stop() {
777
914
  setPlayed(false);
778
- if (__stopNote)
779
- __stopNote(__note);
915
+ if (__onStopNote)
916
+ __onStopNote(__note);
780
917
  },
781
918
  played() {
782
919
  return played;
783
920
  },
784
921
  };
785
- }, [__disabled, __note, __playNote, __stopNote, played]);
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-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: () => {
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 (__playNote)
807
- __playNote(__note);
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 (__playNote)
814
- __playNote(__note);
950
+ if (__onPlayNote)
951
+ __onPlayNote(__note);
815
952
  }
816
953
  }, onPointerUp: () => {
817
954
  if (__disabled)
818
955
  return;
819
956
  setPlayed(false);
820
- if (__stopNote)
821
- __stopNote(__note);
957
+ if (__onStopNote)
958
+ __onStopNote(__note);
822
959
  }, onPointerLeave: () => {
823
960
  if (__disabled)
824
961
  return;
825
- setPlayed(false);
826
- if (__stopNote)
827
- __stopNote(__note);
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
- const WhiteKey = forwardRef((_a, ref) => {
832
- var { width = 40, height = '100%', className, style, children, __glissando, __position, __note, __disabled, __index, __fill, __width, __playNote, __stopNote, __label } = _a, props = __rest(_a, ["width", "height", "className", "style", "children", "__glissando", "__position", "__note", "__disabled", "__index", "__fill", "__width", "__playNote", "__stopNote", "__label"]);
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 (__playNote)
841
- __playNote(__note);
980
+ if (__onPlayNote)
981
+ __onPlayNote(__note);
842
982
  },
843
983
  stop() {
844
984
  setPlayed(false);
845
- if (__stopNote)
846
- __stopNote(__note);
985
+ if (__onStopNote)
986
+ __onStopNote(__note);
847
987
  },
848
988
  played() {
849
989
  return played;
850
990
  },
851
991
  };
852
- }, [__disabled, __note, __playNote, __stopNote, played]);
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-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: () => {
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 (__playNote)
874
- __playNote(__note);
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 (__playNote)
881
- __playNote(__note);
1020
+ if (__onPlayNote)
1021
+ __onPlayNote(__note);
882
1022
  }
883
1023
  }, onPointerUp: () => {
884
1024
  if (__disabled)
885
1025
  return;
886
1026
  setPlayed(false);
887
- if (__stopNote)
888
- __stopNote(__note);
1027
+ if (__onStopNote)
1028
+ __onStopNote(__note);
889
1029
  }, onPointerLeave: () => {
890
1030
  if (__disabled)
891
1031
  return;
892
- setPlayed(false);
893
- if (__stopNote)
894
- __stopNote(__note);
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, playNote, stopNote, label, children } = _a, props = __rest(_a, ["noteRange", "glissando", "midiMax", "keyboardShortcuts", "fill", "height", "style", "className", "playNote", "stopNote", "label", "children"]);
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) || 40);
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%' : undefined, height: height }, style), onPointerDown: (e) => {
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, __playNote: playNote, __stopNote: stopNote, __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, __playNote: playNote, __stopNote: stopNote, __label: label }, blackKeyProps), note));
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 minContext = createContext(0);
1036
- const maxContext = createContext(0);
1037
- const stepContext = createContext(0);
1038
- const skewContext = createContext(0);
1039
- const verticalContext = createContext(false);
1040
- const reverseContext = createContext(false);
1041
- const disabledContext = createContext(false);
1042
- function SliderValuesProvider({ min: _min, max: _max, step: _step, skew: _skew, vertical: _vertical, reverse: _reverse, disabled: _disabled, children, }) {
1043
- const [min] = useState(_min);
1044
- const [max] = useState(_max);
1045
- const [step] = useState(_step);
1046
- const [skew] = useState(_skew);
1047
- const [vertical] = useState(_vertical);
1048
- const [reverse] = useState(_reverse);
1049
- const [disabled] = useState(_disabled);
1050
- return (jsx(minContext.Provider, { value: min, children: jsx(maxContext.Provider, { value: max, children: jsx(stepContext.Provider, { value: step, children: jsx(skewContext.Provider, { value: skew, children: jsx(verticalContext.Provider, { value: vertical, children: jsx(reverseContext.Provider, { value: reverse, children: jsx(disabledContext.Provider, { value: disabled, children: children }) }) }) }) }) }) }));
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 = useMin();
1098
- const max = useMax();
1099
- const skew = useSkew();
1100
- const vertical = useVertical();
1101
- const reverse = useReverse();
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$2(xor(vertical, reverse)
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 = useMin();
1113
- const max = useMax();
1114
- const step = useStep();
1115
- const vertical = useVertical();
1116
- const reverse = useReverse();
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 = useVertical();
1133
- const disabled = useDisabled();
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
- function SliderTrack({ length = defaultLength, thickness = defaultThickness, active, inactive, children, className, style, __thumb, __percent, }) {
1159
- const vertical = useVertical();
1160
- const reverse = useReverse();
1161
- const disabled = useDisabled();
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, style: Object.assign(Object.assign(Object.assign({}, colors), { background: xor(vertical, reverse)
1168
- ? `linear-gradient(to ${direction}, var(--inactive, #eee) ${__percent}%, var(--active, #7998ec) ${__percent}%)`
1169
- : `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] }));
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$2(normalizeValue(value, min, max, skew) * 100);
1184
- const rev = toFixed$2(100 - p);
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(SliderValuesProvider, { 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) => {
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$2((x.reverse ? 1 - nx : nx) * 100);
1380
- const percentY = toFixed$2((y.reverse ? 1 - ny : ny) * 100);
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, SliderValuesProvider, WheelObserver, WhiteKey, XYPad, XYPadArea, XYPadThumb, defaultLength, defaultThickness, defaultThumbSize, useDisabled, useMax, useMin, useReverse, useSkew, useStep, useVertical };
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