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