@tremolo-ui/react 0.0.9 → 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 +432 -269
  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 +2 -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 +430 -260
  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 +2 -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 -14
  118. package/package.json +5 -2
  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 -14
  128. package/src/components/NumberInput/index.tsx +164 -55
  129. package/src/components/Piano/BlackKey.tsx +13 -10
  130. package/src/components/Piano/KeyLabel.tsx +2 -0
  131. package/src/components/Piano/WhiteKey.tsx +14 -10
  132. package/src/components/Piano/index.tsx +13 -11
  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,9 +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
 
898
+ /** @category Piano */
764
899
  const defaultWhiteKeyWidth = 40;
900
+ /** @category Piano */
765
901
  const WhiteKey = forwardRef((_a, ref) => {
766
- var { width = defaultWhiteKeyWidth, 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"]);
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"]);
767
903
  const [played, setPlayed] = useState(false);
768
904
  useImperativeHandle(ref, () => {
769
905
  return {
@@ -771,19 +907,19 @@ const WhiteKey = forwardRef((_a, ref) => {
771
907
  if (__disabled)
772
908
  return;
773
909
  setPlayed(true);
774
- if (__playNote)
775
- __playNote(__note);
910
+ if (__onPlayNote)
911
+ __onPlayNote(__note);
776
912
  },
777
913
  stop() {
778
914
  setPlayed(false);
779
- if (__stopNote)
780
- __stopNote(__note);
915
+ if (__onStopNote)
916
+ __onStopNote(__note);
781
917
  },
782
918
  played() {
783
919
  return played;
784
920
  },
785
921
  };
786
- }, [__disabled, __note, __playNote, __stopNote, played]);
922
+ }, [__disabled, __note, __onPlayNote, __onStopNote, played]);
787
923
  let keyLabelProps = {};
788
924
  if (children != undefined) {
789
925
  React.Children.forEach(children, (child) => {
@@ -804,33 +940,36 @@ const WhiteKey = forwardRef((_a, ref) => {
804
940
  if (__disabled)
805
941
  return;
806
942
  setPlayed(true);
807
- if (__playNote)
808
- __playNote(__note);
943
+ if (__onPlayNote)
944
+ __onPlayNote(__note);
809
945
  }, onPointerEnter: () => {
810
946
  if (__disabled)
811
947
  return;
812
948
  if (__glissando) {
813
949
  setPlayed(true);
814
- if (__playNote)
815
- __playNote(__note);
950
+ if (__onPlayNote)
951
+ __onPlayNote(__note);
816
952
  }
817
953
  }, onPointerUp: () => {
818
954
  if (__disabled)
819
955
  return;
820
956
  setPlayed(false);
821
- if (__stopNote)
822
- __stopNote(__note);
957
+ if (__onStopNote)
958
+ __onStopNote(__note);
823
959
  }, onPointerLeave: () => {
824
960
  if (__disabled)
825
961
  return;
826
- setPlayed(false);
827
- if (__stopNote)
828
- __stopNote(__note);
962
+ if (__glissando) {
963
+ setPlayed(false);
964
+ if (__onStopNote)
965
+ __onStopNote(__note);
966
+ }
829
967
  } }, props, { children: jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
830
968
  });
831
969
 
970
+ /** @category Piano */
832
971
  const BlackKey = forwardRef((_a, ref) => {
833
- var { width = defaultWhiteKeyWidth * 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"]);
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"]);
834
973
  const [played, setPlayed] = useState(false);
835
974
  useImperativeHandle(ref, () => {
836
975
  return {
@@ -838,19 +977,19 @@ const BlackKey = forwardRef((_a, ref) => {
838
977
  if (__disabled)
839
978
  return;
840
979
  setPlayed(true);
841
- if (__playNote)
842
- __playNote(__note);
980
+ if (__onPlayNote)
981
+ __onPlayNote(__note);
843
982
  },
844
983
  stop() {
845
984
  setPlayed(false);
846
- if (__stopNote)
847
- __stopNote(__note);
985
+ if (__onStopNote)
986
+ __onStopNote(__note);
848
987
  },
849
988
  played() {
850
989
  return played;
851
990
  },
852
991
  };
853
- }, [__disabled, __note, __playNote, __stopNote, played]);
992
+ }, [__disabled, __note, __onPlayNote, __onStopNote, played]);
854
993
  let keyLabelProps = {};
855
994
  if (children != undefined) {
856
995
  React.Children.forEach(children, (child) => {
@@ -871,31 +1010,34 @@ const BlackKey = forwardRef((_a, ref) => {
871
1010
  if (__disabled)
872
1011
  return;
873
1012
  setPlayed(true);
874
- if (__playNote)
875
- __playNote(__note);
1013
+ if (__onPlayNote)
1014
+ __onPlayNote(__note);
876
1015
  }, onPointerEnter: () => {
877
1016
  if (__disabled)
878
1017
  return;
879
1018
  if (__glissando) {
880
1019
  setPlayed(true);
881
- if (__playNote)
882
- __playNote(__note);
1020
+ if (__onPlayNote)
1021
+ __onPlayNote(__note);
883
1022
  }
884
1023
  }, onPointerUp: () => {
885
1024
  if (__disabled)
886
1025
  return;
887
1026
  setPlayed(false);
888
- if (__stopNote)
889
- __stopNote(__note);
1027
+ if (__onStopNote)
1028
+ __onStopNote(__note);
890
1029
  }, onPointerLeave: () => {
891
1030
  if (__disabled)
892
1031
  return;
893
- setPlayed(false);
894
- if (__stopNote)
895
- __stopNote(__note);
1032
+ if (__glissando) {
1033
+ setPlayed(false);
1034
+ if (__onStopNote)
1035
+ __onStopNote(__note);
1036
+ }
896
1037
  } }, props, { children: jsx(KeyLabel, Object.assign({ __note: __note, __label: __label, __index: __index }, keyLabelProps)) })));
897
1038
  });
898
1039
 
1040
+ /** @category Piano */
899
1041
  const Shortcuts = {
900
1042
  HOME_ROW: {
901
1043
  keys: [
@@ -920,8 +1062,9 @@ const Shortcuts = {
920
1062
  },
921
1063
  };
922
1064
 
1065
+ /** @category Piano */
923
1066
  function Piano(_a) {
924
- 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"]);
925
1068
  // -- state and ref ---
926
1069
  const [pressed, setPressed] = useState(false);
927
1070
  const [whiteNoteWidth, setWhiteNoteWidth] = useState(-1);
@@ -996,7 +1139,7 @@ function Piano(_a) {
996
1139
  setWhiteNoteWidth((whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width) || defaultWhiteKeyWidth);
997
1140
  }
998
1141
  }, [fill, whiteKeyProps === null || whiteKeyProps === void 0 ? void 0 : whiteKeyProps.width, whiteNoteCount]);
999
- useEventListener(window, 'keydown', (e) => {
1142
+ useEventListener(globalThis.window, 'keydown', (e) => {
1000
1143
  var _a, _b, _c, _d;
1001
1144
  if (e.repeat)
1002
1145
  return;
@@ -1009,7 +1152,7 @@ function Piano(_a) {
1009
1152
  }
1010
1153
  }
1011
1154
  });
1012
- useEventListener(window, 'keyup', (e) => {
1155
+ useEventListener(globalThis.window, 'keyup', (e) => {
1013
1156
  var _a, _b;
1014
1157
  if (e.repeat)
1015
1158
  return;
@@ -1029,35 +1172,46 @@ function Piano(_a) {
1029
1172
  props.onPointerUp(e);
1030
1173
  setPressed(false);
1031
1174
  } }, props, { children: noteRangeArray.map((note, index) => {
1032
- 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));
1033
1176
  }) })));
1034
1177
  }
1035
1178
 
1036
- const minContext = createContext(0);
1037
- const maxContext = createContext(0);
1038
- const stepContext = createContext(0);
1039
- const skewContext = createContext(0);
1040
- const verticalContext = createContext(false);
1041
- const reverseContext = createContext(false);
1042
- const disabledContext = createContext(false);
1043
- function SliderValuesProvider({ min: _min, max: _max, step: _step, skew: _skew, vertical: _vertical, reverse: _reverse, disabled: _disabled, children, }) {
1044
- const [min] = useState(_min);
1045
- const [max] = useState(_max);
1046
- const [step] = useState(_step);
1047
- const [skew] = useState(_skew);
1048
- const [vertical] = useState(_vertical);
1049
- const [reverse] = useState(_reverse);
1050
- const [disabled] = useState(_disabled);
1051
- 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);
1052
1214
  }
1053
- const useMin = () => useContext(minContext);
1054
- const useMax = () => useContext(maxContext);
1055
- const useStep = () => useContext(stepContext);
1056
- const useSkew = () => useContext(skewContext);
1057
- const useVertical = () => useContext(verticalContext);
1058
- // export const useSetVertical = () => useContext(setVerticalContext)
1059
- const useReverse = () => useContext(reverseContext);
1060
- const useDisabled = () => useContext(disabledContext);
1061
1215
 
1062
1216
  /**
1063
1217
  * clamp value between min and max
@@ -1093,28 +1247,30 @@ function generateOptionsList(options, min, max, step) {
1093
1247
  return optionsList;
1094
1248
  }
1095
1249
 
1250
+ /** @category Slider */
1096
1251
  function ScaleOption(_a) {
1097
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"]);
1098
- const min = useMin();
1099
- const max = useMax();
1100
- const skew = useSkew();
1101
- const vertical = useVertical();
1102
- 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);
1103
1258
  const calcPercent = useCallback((rawValue) => {
1104
- return toFixed$2(xor(vertical, reverse)
1259
+ return toFixed$1(xor(vertical, reverse)
1105
1260
  ? 100 - normalizeValue(rawValue, min, max, skew) * 100
1106
1261
  : normalizeValue(rawValue, min, max, skew) * 100);
1107
1262
  }, [vertical, reverse, max, min, skew]);
1108
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 }))] })));
1109
1264
  }
1110
1265
 
1266
+ /** @category Slider */
1111
1267
  function Scale(_a) {
1112
1268
  var { gap = 6, options, children, className, style } = _a, props = __rest(_a, ["gap", "options", "children", "className", "style"]);
1113
- const min = useMin();
1114
- const max = useMax();
1115
- const step = useStep();
1116
- const vertical = useVertical();
1117
- 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);
1118
1274
  const optionsList = options
1119
1275
  ? generateOptionsList(options, min, max, step)
1120
1276
  : [];
@@ -1127,11 +1283,13 @@ function Scale(_a) {
1127
1283
  : children })));
1128
1284
  }
1129
1285
 
1286
+ /** @category Slider */
1130
1287
  const defaultThumbSize = 22;
1288
+ /** @category Slider */
1131
1289
  const SliderThumb = forwardRef(({ size, width = defaultThumbSize, height = defaultThumbSize, children, className, style, __percent, }, ref) => {
1132
1290
  const wrapperRef = useRef(null);
1133
- const vertical = useVertical();
1134
- const disabled = useDisabled();
1291
+ const vertical = useSliderContext((s) => s.vertical);
1292
+ const disabled = useSliderContext((s) => s.disabled);
1135
1293
  useImperativeHandle(ref, () => {
1136
1294
  return {
1137
1295
  focus() {
@@ -1154,24 +1312,30 @@ const SliderThumb = forwardRef(({ size, width = defaultThumbSize, height = defau
1154
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) })) }));
1155
1313
  });
1156
1314
 
1315
+ /** @category Slider */
1157
1316
  const defaultLength = 140;
1317
+ /** @category Slider */
1158
1318
  const defaultThickness = 10;
1159
- function SliderTrack({ length = defaultLength, thickness = defaultThickness, active, inactive, children, className, style, __thumb, __percent, }) {
1160
- const vertical = useVertical();
1161
- const reverse = useReverse();
1162
- 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);
1163
1324
  const direction = vertical ? 'bottom' : 'right';
1164
1325
  const colors = {
1165
1326
  '--active': active,
1166
1327
  '--inactive': inactive,
1167
1328
  };
1168
- return (jsxs("div", { className: clsx('tremolo-slider-track', className), "aria-disabled": disabled, style: Object.assign(Object.assign(Object.assign({}, colors), { background: xor(vertical, reverse)
1169
- ? `linear-gradient(to ${direction}, var(--inactive, #eee) ${__percent}%, var(--active, #7998ec) ${__percent}%)`
1170
- : `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] }));
1171
1334
  }
1172
1335
 
1173
1336
  /**
1174
1337
  * Customizable slider
1338
+ * @category Slider
1175
1339
  */
1176
1340
  const Slider = forwardRef((_a, ref) => {
1177
1341
  var _b, _c, _d;
@@ -1181,8 +1345,8 @@ const Slider = forwardRef((_a, ref) => {
1181
1345
  const thumbRef = useRef(null);
1182
1346
  const thumbDragged = useRef(false);
1183
1347
  // --- interpret props ---
1184
- const p = toFixed$2(normalizeValue(value, min, max, skew) * 100);
1185
- const rev = toFixed$2(100 - p);
1348
+ const p = toFixed$1(normalizeValue(value, min, max, skew) * 100);
1349
+ const rev = toFixed$1(100 - p);
1186
1350
  // NOTE
1187
1351
  // normal -> normal (right)
1188
1352
  // vertical -> rev (up)
@@ -1285,10 +1449,10 @@ const Slider = forwardRef((_a, ref) => {
1285
1449
  }, {
1286
1450
  passive: false,
1287
1451
  }, [wheel, value, min, max, skew, step]);
1288
- useEventListener(window, 'mousemove', (event) => {
1452
+ useEventListener(globalThis.window, 'mousemove', (event) => {
1289
1453
  handleValue(event);
1290
1454
  });
1291
- useEventListener(window, 'mouseup', () => {
1455
+ useEventListener(globalThis.window, 'mouseup', () => {
1292
1456
  thumbDragged.current = false;
1293
1457
  if (bodyNoSelect)
1294
1458
  removeNoSelect();
@@ -1305,7 +1469,7 @@ const Slider = forwardRef((_a, ref) => {
1305
1469
  },
1306
1470
  };
1307
1471
  }, []);
1308
- 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) => {
1309
1473
  wheelRefCallback(div);
1310
1474
  touchMoveRefCallback(div);
1311
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) => {
@@ -1314,9 +1478,12 @@ const Slider = forwardRef((_a, ref) => {
1314
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: {
1315
1479
  display: 'flex',
1316
1480
  flexDirection: vertical ? 'row' : 'column',
1481
+ width: !vertical ? '100%' : undefined,
1482
+ height: vertical ? '100%' : undefined,
1317
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] }) })) }));
1318
1484
  });
1319
1485
 
1486
+ /** @category WheelObserver */
1320
1487
  function WheelObserver(props) {
1321
1488
  const { children, onWheel, as: Component = 'div' } = props, attributes = __rest(props, ["children", "onWheel", "as"]);
1322
1489
  const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
@@ -1326,10 +1493,12 @@ function WheelObserver(props) {
1326
1493
  return (jsx(Component, Object.assign({ ref: wheelRefCallback }, attributes, { children: children })));
1327
1494
  }
1328
1495
 
1496
+ /** @category XYPad */
1329
1497
  function XYPadArea({ width = 120, height = 120, bg = '#eee', children, className, style, __thumb, }) {
1330
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] }));
1331
1499
  }
1332
1500
 
1501
+ /** @category XYPad */
1333
1502
  const XYPadThumb = forwardRef(({ size, width = 22, height = 22, children, wrapperClassName, wrapperStyle, className, style, __disabled, __css, }, ref) => {
1334
1503
  const wrapperRef = useRef(null);
1335
1504
  useImperativeHandle(ref, () => {
@@ -1360,6 +1529,7 @@ const defaultValueOptions = {
1360
1529
  };
1361
1530
  /**
1362
1531
  * Simple XYPad
1532
+ * @category XYPad
1363
1533
  */
1364
1534
  const XYPad = forwardRef((_a, ref) => {
1365
1535
  var _b, _c, _d;
@@ -1377,8 +1547,8 @@ const XYPad = forwardRef((_a, ref) => {
1377
1547
  // --- interpret props ---
1378
1548
  const nx = normalizeValue(x.value, x.min, x.max, x.skew);
1379
1549
  const ny = normalizeValue(y.value, y.min, y.max, y.skew);
1380
- const percentX = toFixed$2((x.reverse ? 1 - nx : nx) * 100);
1381
- 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);
1382
1552
  let areaProps = {}, thumbProps = {};
1383
1553
  if (children != undefined) {
1384
1554
  React.Children.forEach(children, (child) => {
@@ -1485,10 +1655,10 @@ const XYPad = forwardRef((_a, ref) => {
1485
1655
  }, {
1486
1656
  passive: false,
1487
1657
  }, [x, y]);
1488
- useEventListener(window, 'mousemove', (event) => {
1658
+ useEventListener(globalThis.window, 'mousemove', (event) => {
1489
1659
  handleValue(event);
1490
1660
  });
1491
- useEventListener(window, 'mouseup', () => {
1661
+ useEventListener(globalThis.window, 'mouseup', () => {
1492
1662
  thumbDragged.current = false;
1493
1663
  if (bodyNoSelect)
1494
1664
  removeNoSelect();
@@ -1519,5 +1689,5 @@ const XYPad = forwardRef((_a, ref) => {
1519
1689
  } }, thumbProps)) }, areaProps)) }) })));
1520
1690
  });
1521
1691
 
1522
- 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 };
1523
1693
  //# sourceMappingURL=index.js.map