@tremolo-ui/react 0.1.1 → 0.1.3

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 (163) hide show
  1. package/dist/index.cjs +2082 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/{styles/index.css → index.css} +3 -0
  4. package/dist/index.css.map +1 -0
  5. package/dist/index.d.cts +827 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.ts +827 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +2030 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +14 -14
  12. package/src/hooks/useAnimationFrame.ts +2 -2
  13. package/src/hooks/useDrag.ts +2 -2
  14. package/src/hooks/useDragWithElement.ts +2 -2
  15. package/src/index.ts +79 -15
  16. package/dist/cjs/index.js +0 -2041
  17. package/dist/cjs/index.js.map +0 -1
  18. package/dist/cjs/types/components/AnimationCanvas/canvas.d.ts +0 -6
  19. package/dist/cjs/types/components/AnimationCanvas/canvas.d.ts.map +0 -1
  20. package/dist/cjs/types/components/AnimationCanvas/index.d.ts +0 -51
  21. package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +0 -1
  22. package/dist/cjs/types/components/AnimationKnob/index.d.ts +0 -62
  23. package/dist/cjs/types/components/AnimationKnob/index.d.ts.map +0 -1
  24. package/dist/cjs/types/components/DragObserver/index.d.ts +0 -21
  25. package/dist/cjs/types/components/DragObserver/index.d.ts.map +0 -1
  26. package/dist/cjs/types/components/Knob/index.d.ts +0 -71
  27. package/dist/cjs/types/components/Knob/index.d.ts.map +0 -1
  28. package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts +0 -9
  29. package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts.map +0 -1
  30. package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts +0 -9
  31. package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts.map +0 -1
  32. package/dist/cjs/types/components/NumberInput/InternalInput.d.ts +0 -18
  33. package/dist/cjs/types/components/NumberInput/InternalInput.d.ts.map +0 -1
  34. package/dist/cjs/types/components/NumberInput/Stepper.d.ts +0 -10
  35. package/dist/cjs/types/components/NumberInput/Stepper.d.ts.map +0 -1
  36. package/dist/cjs/types/components/NumberInput/context.d.ts +0 -28
  37. package/dist/cjs/types/components/NumberInput/context.d.ts.map +0 -1
  38. package/dist/cjs/types/components/NumberInput/index.d.ts +0 -69
  39. package/dist/cjs/types/components/NumberInput/index.d.ts.map +0 -1
  40. package/dist/cjs/types/components/Piano/KeyLabel.d.ts +0 -17
  41. package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +0 -1
  42. package/dist/cjs/types/components/Piano/context.d.ts +0 -24
  43. package/dist/cjs/types/components/Piano/context.d.ts.map +0 -1
  44. package/dist/cjs/types/components/Piano/index.d.ts +0 -39
  45. package/dist/cjs/types/components/Piano/index.d.ts.map +0 -1
  46. package/dist/cjs/types/components/Piano/key.d.ts +0 -37
  47. package/dist/cjs/types/components/Piano/key.d.ts.map +0 -1
  48. package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +0 -14
  49. package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts.map +0 -1
  50. package/dist/cjs/types/components/Slider/Scale.d.ts +0 -11
  51. package/dist/cjs/types/components/Slider/Scale.d.ts.map +0 -1
  52. package/dist/cjs/types/components/Slider/ScaleOption.d.ts +0 -27
  53. package/dist/cjs/types/components/Slider/ScaleOption.d.ts.map +0 -1
  54. package/dist/cjs/types/components/Slider/Thumb.d.ts +0 -23
  55. package/dist/cjs/types/components/Slider/Thumb.d.ts.map +0 -1
  56. package/dist/cjs/types/components/Slider/Track.d.ts +0 -21
  57. package/dist/cjs/types/components/Slider/Track.d.ts.map +0 -1
  58. package/dist/cjs/types/components/Slider/context.d.ts +0 -16
  59. package/dist/cjs/types/components/Slider/context.d.ts.map +0 -1
  60. package/dist/cjs/types/components/Slider/index.d.ts +0 -55
  61. package/dist/cjs/types/components/Slider/index.d.ts.map +0 -1
  62. package/dist/cjs/types/components/WheelObserver/index.d.ts +0 -25
  63. package/dist/cjs/types/components/WheelObserver/index.d.ts.map +0 -1
  64. package/dist/cjs/types/components/XYPad/Area.d.ts +0 -15
  65. package/dist/cjs/types/components/XYPad/Area.d.ts.map +0 -1
  66. package/dist/cjs/types/components/XYPad/Thumb.d.ts +0 -23
  67. package/dist/cjs/types/components/XYPad/Thumb.d.ts.map +0 -1
  68. package/dist/cjs/types/components/XYPad/index.d.ts +0 -48
  69. package/dist/cjs/types/components/XYPad/index.d.ts.map +0 -1
  70. package/dist/cjs/types/components/_util/index.d.ts +0 -4
  71. package/dist/cjs/types/components/_util/index.d.ts.map +0 -1
  72. package/dist/cjs/types/hooks/useAnimationFrame.d.ts +0 -3
  73. package/dist/cjs/types/hooks/useAnimationFrame.d.ts.map +0 -1
  74. package/dist/cjs/types/hooks/useCallbackRef.d.ts +0 -6
  75. package/dist/cjs/types/hooks/useCallbackRef.d.ts.map +0 -1
  76. package/dist/cjs/types/hooks/useDrag.d.ts +0 -15
  77. package/dist/cjs/types/hooks/useDrag.d.ts.map +0 -1
  78. package/dist/cjs/types/hooks/useDragWithElement.d.ts +0 -16
  79. package/dist/cjs/types/hooks/useDragWithElement.d.ts.map +0 -1
  80. package/dist/cjs/types/hooks/useEventListener.d.ts +0 -7
  81. package/dist/cjs/types/hooks/useEventListener.d.ts.map +0 -1
  82. package/dist/cjs/types/hooks/useInterval.d.ts +0 -2
  83. package/dist/cjs/types/hooks/useInterval.d.ts.map +0 -1
  84. package/dist/cjs/types/hooks/useLongPress.d.ts +0 -2
  85. package/dist/cjs/types/hooks/useLongPress.d.ts.map +0 -1
  86. package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts +0 -2
  87. package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts.map +0 -1
  88. package/dist/cjs/types/index.d.ts +0 -22
  89. package/dist/cjs/types/index.d.ts.map +0 -1
  90. package/dist/esm/index.js +0 -2010
  91. package/dist/esm/index.js.map +0 -1
  92. package/dist/esm/types/components/AnimationCanvas/canvas.d.ts +0 -6
  93. package/dist/esm/types/components/AnimationCanvas/canvas.d.ts.map +0 -1
  94. package/dist/esm/types/components/AnimationCanvas/index.d.ts +0 -51
  95. package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +0 -1
  96. package/dist/esm/types/components/AnimationKnob/index.d.ts +0 -62
  97. package/dist/esm/types/components/AnimationKnob/index.d.ts.map +0 -1
  98. package/dist/esm/types/components/DragObserver/index.d.ts +0 -21
  99. package/dist/esm/types/components/DragObserver/index.d.ts.map +0 -1
  100. package/dist/esm/types/components/Knob/index.d.ts +0 -71
  101. package/dist/esm/types/components/Knob/index.d.ts.map +0 -1
  102. package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts +0 -9
  103. package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts.map +0 -1
  104. package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts +0 -9
  105. package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts.map +0 -1
  106. package/dist/esm/types/components/NumberInput/InternalInput.d.ts +0 -18
  107. package/dist/esm/types/components/NumberInput/InternalInput.d.ts.map +0 -1
  108. package/dist/esm/types/components/NumberInput/Stepper.d.ts +0 -10
  109. package/dist/esm/types/components/NumberInput/Stepper.d.ts.map +0 -1
  110. package/dist/esm/types/components/NumberInput/context.d.ts +0 -28
  111. package/dist/esm/types/components/NumberInput/context.d.ts.map +0 -1
  112. package/dist/esm/types/components/NumberInput/index.d.ts +0 -69
  113. package/dist/esm/types/components/NumberInput/index.d.ts.map +0 -1
  114. package/dist/esm/types/components/Piano/KeyLabel.d.ts +0 -17
  115. package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +0 -1
  116. package/dist/esm/types/components/Piano/context.d.ts +0 -24
  117. package/dist/esm/types/components/Piano/context.d.ts.map +0 -1
  118. package/dist/esm/types/components/Piano/index.d.ts +0 -39
  119. package/dist/esm/types/components/Piano/index.d.ts.map +0 -1
  120. package/dist/esm/types/components/Piano/key.d.ts +0 -37
  121. package/dist/esm/types/components/Piano/key.d.ts.map +0 -1
  122. package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +0 -14
  123. package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts.map +0 -1
  124. package/dist/esm/types/components/Slider/Scale.d.ts +0 -11
  125. package/dist/esm/types/components/Slider/Scale.d.ts.map +0 -1
  126. package/dist/esm/types/components/Slider/ScaleOption.d.ts +0 -27
  127. package/dist/esm/types/components/Slider/ScaleOption.d.ts.map +0 -1
  128. package/dist/esm/types/components/Slider/Thumb.d.ts +0 -23
  129. package/dist/esm/types/components/Slider/Thumb.d.ts.map +0 -1
  130. package/dist/esm/types/components/Slider/Track.d.ts +0 -21
  131. package/dist/esm/types/components/Slider/Track.d.ts.map +0 -1
  132. package/dist/esm/types/components/Slider/context.d.ts +0 -16
  133. package/dist/esm/types/components/Slider/context.d.ts.map +0 -1
  134. package/dist/esm/types/components/Slider/index.d.ts +0 -55
  135. package/dist/esm/types/components/Slider/index.d.ts.map +0 -1
  136. package/dist/esm/types/components/WheelObserver/index.d.ts +0 -25
  137. package/dist/esm/types/components/WheelObserver/index.d.ts.map +0 -1
  138. package/dist/esm/types/components/XYPad/Area.d.ts +0 -15
  139. package/dist/esm/types/components/XYPad/Area.d.ts.map +0 -1
  140. package/dist/esm/types/components/XYPad/Thumb.d.ts +0 -23
  141. package/dist/esm/types/components/XYPad/Thumb.d.ts.map +0 -1
  142. package/dist/esm/types/components/XYPad/index.d.ts +0 -48
  143. package/dist/esm/types/components/XYPad/index.d.ts.map +0 -1
  144. package/dist/esm/types/components/_util/index.d.ts +0 -4
  145. package/dist/esm/types/components/_util/index.d.ts.map +0 -1
  146. package/dist/esm/types/hooks/useAnimationFrame.d.ts +0 -3
  147. package/dist/esm/types/hooks/useAnimationFrame.d.ts.map +0 -1
  148. package/dist/esm/types/hooks/useCallbackRef.d.ts +0 -6
  149. package/dist/esm/types/hooks/useCallbackRef.d.ts.map +0 -1
  150. package/dist/esm/types/hooks/useDrag.d.ts +0 -15
  151. package/dist/esm/types/hooks/useDrag.d.ts.map +0 -1
  152. package/dist/esm/types/hooks/useDragWithElement.d.ts +0 -16
  153. package/dist/esm/types/hooks/useDragWithElement.d.ts.map +0 -1
  154. package/dist/esm/types/hooks/useEventListener.d.ts +0 -7
  155. package/dist/esm/types/hooks/useEventListener.d.ts.map +0 -1
  156. package/dist/esm/types/hooks/useInterval.d.ts +0 -2
  157. package/dist/esm/types/hooks/useInterval.d.ts.map +0 -1
  158. package/dist/esm/types/hooks/useLongPress.d.ts +0 -2
  159. package/dist/esm/types/hooks/useLongPress.d.ts.map +0 -1
  160. package/dist/esm/types/hooks/useRefCallbackEvent.d.ts +0 -2
  161. package/dist/esm/types/hooks/useRefCallbackEvent.d.ts.map +0 -1
  162. package/dist/esm/types/index.d.ts +0 -22
  163. package/dist/esm/types/index.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["canvas: HTMLCanvasElement","context: CanvasRenderingContext2D","width: number","height: number","dpr: number","width: RefObject<number>","height: RefObject<number>","count: number","width","height","w","h","callback: ((...args: Args) => Return) | undefined","deps: React.DependencyList","target: Target","event: string","handler: ((event: Event) => void) | undefined","options?: Options","event: string","handler: (event: Event) => void","options?: boolean | AddEventListenerOptions","deps: React.DependencyList","cleanup: (() => void) | undefined","node: EventTarget | null","event: MouseEvent | React.MouseEvent<T, MouseEvent> | TouchEvent","event: React.PointerEvent<T>","_x: number","y: number","event: React.KeyboardEvent<HTMLDivElement>","width","height","props: DragObserverProps<T> &\n Omit<ComponentPropsWithoutRef<T>, keyof DragObserverProps<T>>","_x: number","y: number","eventType: InputEventOption[0]","x: number","event: React.KeyboardEvent<HTMLOrSVGElement>","value: number","initProps?: ProviderProps","DEFAULT_PROPS: State","_v: number","_t: string","selector: (state: State & Action) => T","eventType: InputEventOption[0]","x: number","event: React.KeyboardEvent<HTMLDivElement>","valueAsNumber","callback: () => void","delay: number | null","callback: () => void","colors: { [key: string]: string | undefined }","event: MouseEvent | React.PointerEvent<T> | TouchEvent","event: React.PointerEvent<T>","initProps: Partial<State> & Action","DEFAULT_PROPS: State","selector: (state: State & Action) => T","keyLabelProps: KeyLabelProps","noteRange: NoteRange","props","note: number","pitchPositions: Record<NoteKey, number>","padding","x: number","y: number","perX: number","perY: number","initProps?: Partial<State>","DEFAULT_PROPS: State","selector: (state: State) => T","rawValue: number","rawValue","trackProps: SliderTrackProps","thumbProps: SliderThumbProps","scaleComponent: ReactElement | undefined","nx: number","ny: number","eventType: InputEventOption[0]","x: number","event: React.KeyboardEvent<HTMLDivElement>","props: WheelObserverProps<T> &\n Omit<ComponentPropsWithoutRef<T>, keyof WheelObserverProps<T>>","areaProps: AreaProps","thumbProps: ThumbProps","nx: number","ny: number","nx","ny","eventType: InputEventOption[0]","target: Required<ValueOptions>","x: number","x","event: React.KeyboardEvent<HTMLDivElement>","deps: DependencyList"],"sources":["../src/components/AnimationCanvas/canvas.ts","../src/components/AnimationCanvas/index.tsx","../src/hooks/useCallbackRef.ts","../src/hooks/useEventListener.ts","../src/hooks/useRefCallbackEvent.ts","../src/hooks/useDrag.ts","../src/components/_util/index.ts","../src/components/AnimationKnob/index.tsx","../src/components/DragObserver/index.tsx","../src/components/Knob/index.tsx","../src/components/NumberInput/context.tsx","../src/components/NumberInput/InternalInput.tsx","../src/components/NumberInput/Stepper.tsx","../src/hooks/useInterval.ts","../src/hooks/useLongPress.ts","../src/components/NumberInput/IncrementStepper.tsx","../src/components/NumberInput/DecrementStepper.tsx","../src/components/NumberInput/index.tsx","../src/hooks/useDragWithElement.ts","../src/components/Piano/context.tsx","../src/components/Piano/KeyLabel.tsx","../src/components/Piano/key.tsx","../src/components/Piano/keyboardShortcuts.ts","../src/components/Piano/index.tsx","../src/components/Slider/context.tsx","../src/components/Slider/ScaleOption.tsx","../src/components/Slider/Scale.tsx","../src/components/Slider/Thumb.tsx","../src/components/Slider/Track.tsx","../src/components/Slider/index.tsx","../src/components/WheelObserver/index.tsx","../src/components/XYPad/Area.tsx","../src/components/XYPad/Thumb.tsx","../src/components/XYPad/index.tsx","../src/hooks/useAnimationFrame.ts"],"sourcesContent":["// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save\nexport const drawingState = [\n 'strokeStyle',\n 'fillStyle',\n 'globalAlpha',\n 'lineWidth',\n 'lineCap',\n 'lineJoin',\n 'miterLimit',\n 'lineDashOffset',\n 'shadowOffsetX',\n 'shadowOffsetY',\n 'shadowBlur',\n 'shadowColor',\n 'globalCompositeOperation',\n 'font',\n 'textAlign',\n 'textBaseline',\n 'direction',\n 'imageSmoothingEnabled',\n] as const\n\nexport type DrawingState = (typeof drawingState)[number]\nexport type DrawingStateValue = CanvasRenderingContext2D[DrawingState]\nexport type DrawingContext = Pick<CanvasRenderingContext2D, DrawingState>\n\nexport function isDrawingState(obj: unknown): obj is DrawingState {\n const d: string[] = [...drawingState]\n return typeof obj == 'string' && d.includes(obj)\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n ReactElement,\n RefObject,\n useCallback,\n useEffect,\n useRef,\n} from 'react'\n\nimport { DrawingContext, drawingState, DrawingStateValue } from './canvas'\n\n/*\nTODO\nAbsoluteSizingProps, RelativeSizingPropsの型付けを強くする\nAbsoluteSizingPropsの場合、width, heightは必須\nRelativeSizingPropsのの場合、relativeSizeは必須、reduceFlickeringはオプショナル\n*/\n\nfunction setDprConfig(\n canvas: HTMLCanvasElement,\n context: CanvasRenderingContext2D,\n width: number,\n height: number,\n dpr: number,\n) {\n canvas.width = width * dpr\n canvas.height = height * dpr\n // Reset current transformation matrix to the identity matrix\n context.setTransform(1, 0, 0, 1, 0, 0)\n context.scale(dpr, dpr)\n canvas.style.width = `${width}px`\n canvas.style.height = `${height}px`\n}\n\n/** @category AnimationCanvas */\nexport type InitFunction = (\n context: CanvasRenderingContext2D,\n option: {\n /** current canvas width */\n width: number\n /** current canvas height */\n height: number\n },\n) => void\n\n/** @category AnimationCanvas */\nexport type DrawFunction = (\n // TODO: saving scale and translate\n // context: Omit<CanvasRenderingContext2D, 'save' | 'restore' | 'scale'>,\n context: CanvasRenderingContext2D,\n option: {\n /** current canvas width */\n width: number\n /** current canvas height */\n height: number\n /** frame count */\n count: number\n /** delta time (ms) */\n deltaTime: number\n /** elapsed time (ms) */\n elapsedTime: number\n /** frame per second */\n fps: number\n },\n) => void\n\n/** @category AnimationCanvas */\nexport interface CommonProps {\n /**\n * @see https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext#contextattributes\n */\n options?: CanvasRenderingContext2DSettings\n init?: InitFunction\n draw: DrawFunction\n}\n\n/** @category AnimationCanvas */\nexport interface AbsoluteSizingProps {\n width?: number\n height?: number\n}\n\n/** @category AnimationCanvas */\nexport interface RelativeSizingProps {\n relativeSize?: boolean\n reduceFlickering?: boolean\n}\n\n/** @category AnimationCanvas */\nexport type AnimationCanvasProps = CommonProps &\n AbsoluteSizingProps &\n RelativeSizingProps\n\n/**\n * A simple animatable canvas with requestAnimationFrame()\n * @category AnimationCanvas\n */\nexport function AnimationCanvas(\n props: CommonProps &\n AbsoluteSizingProps &\n Omit<ComponentPropsWithoutRef<'canvas'>, keyof AnimationCanvasProps>,\n): ReactElement\nexport function AnimationCanvas(\n pros: CommonProps &\n RelativeSizingProps &\n Omit<ComponentPropsWithoutRef<'canvas'>, keyof AnimationCanvasProps>,\n): ReactElement\nexport function AnimationCanvas({\n // common\n options,\n init,\n draw,\n // absolute\n width = 100,\n height = 100,\n // relative\n relativeSize,\n reduceFlickering = true,\n // canvas props\n className,\n onContextMenu = (event) => event.preventDefault(),\n ...props\n}: AnimationCanvasProps &\n Omit<\n ComponentPropsWithoutRef<'canvas'>,\n keyof AnimationCanvasProps\n >): ReactElement {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const memoCanvasRef = useRef<HTMLCanvasElement>(null)\n const reqIdRef = useRef(-1)\n const widthRef = useRef(0)\n const heightRef = useRef(0)\n const deltaMemoRef = useRef(-1)\n const startTimeRef = useRef(-1)\n\n const loop = useCallback(\n (\n context: CanvasRenderingContext2D,\n width: RefObject<number>,\n height: RefObject<number>,\n count: number,\n ) => {\n const now = performance.now()\n const deltaTime = now - deltaMemoRef.current\n const elapsedTime = now - startTimeRef.current\n deltaMemoRef.current = now\n reqIdRef.current = requestAnimationFrame(() =>\n loop(context, width, height, count + 1),\n )\n draw(context, {\n width: width.current,\n height: height.current,\n count: count + 1,\n deltaTime,\n elapsedTime,\n fps: 1000 / deltaTime,\n })\n },\n [draw],\n )\n\n useEffect(() => {\n if (!canvasRef.current) return\n const canvas = canvasRef.current\n const context = canvas.getContext('2d', options)\n if (!context) throw new Error('Cannot get canvas context.')\n const dpr = globalThis.devicePixelRatio\n\n if (relativeSize) {\n const parent = canvas.parentElement\n if (!parent) throw new Error(\"Canvas doesn't have a parent element.\")\n const memoCanvas = memoCanvasRef.current\n const memoContext = memoCanvas?.getContext('2d', options)\n\n const ro = new ResizeObserver((entries) => {\n for (const entry of entries) {\n // Prevents loss of some context when the canvas is resized\n const contextMemo = {} as DrawingContext\n for (const prop of drawingState) {\n ;(contextMemo[prop] as DrawingStateValue) = context[prop]\n }\n\n const w = entry.contentRect.width\n const h = entry.contentRect.height\n\n if (reduceFlickering && memoCanvas && memoContext) {\n memoCanvas.width = w * dpr\n memoCanvas.height = h * dpr\n memoContext.scale(1 / dpr, 1 / dpr)\n if (canvas.width > 0 && canvas.height > 0) {\n memoContext.drawImage(canvas, 0, 0)\n }\n }\n\n setDprConfig(canvas, context, w, h, dpr)\n widthRef.current = w\n heightRef.current = h\n\n for (const prop of drawingState) {\n ;(context[prop] as DrawingStateValue) = contextMemo[prop]\n }\n\n if (\n reduceFlickering &&\n memoContext &&\n memoCanvas &&\n memoCanvas.width > 0 &&\n memoCanvas.height > 0\n ) {\n context.drawImage(memoContext.canvas, 0, 0)\n }\n }\n })\n ro.observe(parent)\n\n const w = parent.clientWidth\n const h = parent.clientHeight\n setDprConfig(canvas, context, w, h, dpr)\n\n if (init)\n init(context, { width: widthRef.current, height: heightRef.current })\n const now = performance.now()\n deltaMemoRef.current = now\n startTimeRef.current = now\n loop(context, widthRef, heightRef, -1)\n\n return () => {\n if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current)\n ro.disconnect()\n }\n } else {\n const rect = canvas.getBoundingClientRect()\n setDprConfig(canvas, context, rect.width, rect.height, dpr)\n widthRef.current = rect.width\n heightRef.current = rect.height\n\n if (init)\n init(context, { width: widthRef.current, height: heightRef.current })\n const now = performance.now()\n deltaMemoRef.current = now\n startTimeRef.current = now\n loop(context, widthRef, heightRef, -1)\n\n return () => {\n if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current)\n }\n }\n }, [loop, init, options, reduceFlickering, relativeSize])\n\n return (\n <>\n <canvas\n className={clsx('tremolo-animation-canvas', className)}\n width={relativeSize ? 0 : width}\n height={relativeSize ? 0 : height}\n ref={canvasRef}\n onContextMenu={onContextMenu}\n {...props}\n ></canvas>\n {relativeSize && reduceFlickering && (\n <canvas style={{ display: 'none' }} ref={memoCanvasRef}></canvas>\n )}\n </>\n )\n}\n","import { useCallback, useInsertionEffect, useRef } from 'react'\n\n/**\n * This hook is user-land implementation of the experimental `useEffectEvent` hook.\n * React docs: https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event\n */\nexport function useCallbackRef<Args extends unknown[], Return>(\n callback: ((...args: Args) => Return) | undefined,\n deps: React.DependencyList = [],\n) {\n const callbackRef = useRef<typeof callback>(() => {\n throw new Error('Cannot call an event handler while rendering.')\n })\n\n useInsertionEffect(() => {\n callbackRef.current = callback\n })\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback((...args: Args) => callbackRef.current?.(...args), deps)\n}\n","import { useEffect } from 'react'\n\nimport { useCallbackRef } from './useCallbackRef'\n\ntype Target = EventTarget | null | (() => EventTarget | null)\ntype Options = boolean | AddEventListenerOptions\n\nexport function useEventListener<K extends keyof DocumentEventMap>(\n target: Target,\n event: K,\n handler?: (event: DocumentEventMap[K]) => void,\n options?: Options,\n): VoidFunction\nexport function useEventListener<K extends keyof WindowEventMap>(\n target: Target,\n event: K,\n handler?: (event: WindowEventMap[K]) => void,\n options?: Options,\n): VoidFunction\nexport function useEventListener<K extends keyof GlobalEventHandlersEventMap>(\n target: Target,\n event: K,\n handler?: (event: GlobalEventHandlersEventMap[K]) => void,\n options?: Options,\n): VoidFunction\nexport function useEventListener(\n target: Target,\n event: string,\n handler: ((event: Event) => void) | undefined,\n options?: Options,\n) {\n const listener = useCallbackRef(handler)\n\n useEffect(() => {\n const node = typeof target === 'function' ? target() : (target ?? document)\n\n if (!handler || !node) return\n\n node.addEventListener(event, listener, options)\n return () => {\n node.removeEventListener(event, listener, options)\n }\n }, [event, target, options, listener, handler])\n\n return () => {\n const node = typeof target === 'function' ? target() : (target ?? document)\n node?.removeEventListener(event, listener, options)\n }\n}\n","import { useMemo } from 'react'\n\nexport function useRefCallbackEvent<K extends keyof DocumentEventMap>(\n event: K,\n handler: (event: DocumentEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n deps?: React.DependencyList,\n): (div: EventTarget | null) => void\nexport function useRefCallbackEvent(\n event: string,\n handler: (event: Event) => void,\n options?: boolean | AddEventListenerOptions,\n deps: React.DependencyList = [],\n): (div: EventTarget | null) => void {\n return useMemo(() => {\n let cleanup: (() => void) | undefined\n return (node: EventTarget | null) => {\n if (!node) {\n cleanup?.()\n return\n }\n node.addEventListener(event, handler, options)\n\n cleanup = () => {\n node.removeEventListener(event, handler, options)\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n","import { useRef, useCallback } from 'react'\n\nimport { useEventListener } from './useEventListener'\nimport { useRefCallbackEvent } from './useRefCallbackEvent'\n\nexport interface UseDragProps {\n threshold?: number\n\n onDrag: (x: number, y: number, deltaX: number, deltaY: number) => void\n onDragStart?: () => void\n onDragEnd?: () => void\n}\n\n/**\n * @returns [refCallback, pointerDownHandler]\n */\nexport function useDrag<T extends Element>({\n threshold = 1,\n onDrag,\n onDragStart,\n onDragEnd,\n}: UseDragProps): [\n (div: EventTarget | null) => void,\n (event: React.PointerEvent<T>) => void,\n] {\n const dragOffsetX = useRef<number | undefined>(undefined)\n const dragOffsetY = useRef<number | undefined>(undefined)\n const dragStartX = useRef(0)\n const dragStartY = useRef(0)\n\n const handleDrag = useCallback(\n (\n event: MouseEvent | React.MouseEvent<T, MouseEvent> | TouchEvent,\n first = false,\n ) => {\n const isTouch = event instanceof TouchEvent\n if (isTouch && event.cancelable) event.preventDefault()\n const screenX = isTouch ? event.touches[0].screenX : event.screenX\n const screenY = isTouch ? event.touches[0].screenY : event.screenY\n let deltaX = 0\n let deltaY = 0\n if (first) {\n dragStartX.current = screenX\n dragStartY.current = screenY\n }\n if (dragOffsetX.current) {\n deltaX = screenX - dragOffsetX.current\n dragOffsetX.current = screenX\n }\n if (dragOffsetY.current) {\n deltaY = screenY - dragOffsetY.current\n dragOffsetY.current = screenY\n }\n if (Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold) return\n onDrag(\n screenX - dragStartX.current,\n screenY - dragStartY.current,\n deltaX,\n deltaY,\n )\n },\n [threshold, onDrag],\n )\n\n const refHandler = useRefCallbackEvent(\n 'touchmove',\n handleDrag,\n { passive: false },\n [onDrag],\n )\n\n const pointerDownHandler = useCallback(\n (event: React.PointerEvent<T>) => {\n dragOffsetX.current = event.screenX\n dragOffsetY.current = event.screenY\n handleDrag(event, true)\n onDragStart?.()\n },\n [handleDrag, onDragStart],\n )\n\n useEventListener(globalThis.window, 'mousemove', handleDrag)\n\n useEventListener(globalThis.window, 'pointerup', () => {\n dragOffsetX.current = undefined\n dragOffsetY.current = undefined\n onDragEnd?.()\n })\n\n return [refHandler, pointerDownHandler]\n}\n","export function addNoSelect() {\n document.body.classList.add('tremolo-no-select')\n}\n\nexport function removeNoSelect() {\n document.body.classList.remove('tremolo-no-select')\n}\n\nexport function toggleNoSelect() {\n document.body.classList.toggle('tremolo-no-select')\n}\n","import clsx from 'clsx'\nimport React, {\n ComponentPropsWithoutRef,\n CSSProperties,\n forwardRef,\n useCallback,\n useImperativeHandle,\n useRef,\n} from 'react'\n\nimport {\n clamp,\n normalizeValue,\n radian,\n rawValue,\n stepValue,\n InputEventOption,\n} from '@tremolo-ui/functions'\n\nimport { useDrag } from '../../hooks/useDrag'\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\nimport { addNoSelect, removeNoSelect } from '../_util'\nimport { AnimationCanvas, DrawFunction } from '../AnimationCanvas'\n\n/** @category AnimationKnob */\nexport type AnimationKnobProps = {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n skew?: number // | SkewFunction\n /**\n * value set when double-clicking\n * @see enableDoubleClickDefault\n */\n defaultValue?: number\n\n /**\n * Value to be used as the starting point of the line when drawing.\n * @default min\n */\n startValue?: number\n\n /** Priority over width or height */\n size?: number | `${number}%`\n\n width?: number | `${number}%`\n height?: number | `${number}%`\n\n /** active line color */\n activeColor?: string\n /** inactive line color */\n inactiveColor?: string\n /** background color */\n bg?: string\n /** thumb color */\n thumb?: string\n lineWeight?: number\n thumbWeight?: number\n\n draw?: DrawFunction\n\n /** Whether to apply `{use-select: none}` when dragging */\n bodyNoSelect?: boolean\n /**\n * wheel control option\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n */\n keyboard?: InputEventOption | null\n enableDoubleClickDefault?: boolean\n style?: CSSProperties\n onChange?: (value: number) => void\n}\n\n/**\n * @category AnimationKnob\n */\nexport interface AnimationKnobMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = AnimationKnobProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof AnimationKnobProps>\n\n/**\n * Animatable rotary knob.\n * @category AnimationKnob\n */\nexport const AnimationKnob = forwardRef<AnimationKnobMethods, Props>(\n (\n {\n value,\n min,\n max,\n defaultValue = min,\n startValue = min,\n step = 1,\n skew = 1,\n size,\n width = 50,\n height = 50,\n activeColor = '#7998ec',\n inactiveColor = '#eee',\n bg = '#ccc',\n thumb = '#4e76e6',\n lineWeight = 6,\n thumbWeight = 4,\n draw,\n bodyNoSelect = true,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n enableDoubleClickDefault = true,\n style,\n className,\n onChange,\n ...props\n }: Props,\n ref,\n ) => {\n // -- state and ref ---\n const valueRef = useRef(0)\n const elmRef = useRef<HTMLDivElement>(null)\n\n // --- interpret props ---\n const isRelativeSize =\n typeof (size ?? width) == 'string' || typeof height == 'string'\n\n const onDrag = useCallback(\n (_x: number, y: number) => {\n if (!onChange) return\n const v = rawValue(valueRef.current - y / 100, min, max, skew)\n const v2 = clamp(stepValue(v, step), min, max)\n onChange(v2)\n },\n [max, min, onChange, skew, step],\n )\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!keyboard || !onChange) return\n const key = event.key\n if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {\n event.preventDefault()\n const x =\n key == 'ArrowRight' || key == 'ArrowUp' ? keyboard[1] : -keyboard[1]\n let v\n if (keyboard[0] == 'normalized') {\n const n = normalizeValue(value, min, max, skew)\n v = rawValue(n + x, min, max, skew)\n } else {\n v = value + x\n }\n onChange(clamp(stepValue(v, step), min, max))\n }\n },\n [value, min, max, step, skew, keyboard, onChange],\n )\n\n // --- hooks ---\n const [touchMoveRefCallback, pointerDownHandler] = useDrag<HTMLDivElement>({\n onDrag: onDrag,\n onDragStart: () => {\n valueRef.current = normalizeValue(value, min, max, skew)\n if (bodyNoSelect) addNoSelect()\n },\n onDragEnd: () => {\n if (bodyNoSelect) removeNoSelect()\n },\n })\n\n const wheelRefCallback = useRefCallbackEvent(\n 'wheel',\n (event) => {\n if (!wheel) return\n event.preventDefault()\n const x = event.deltaY > 0 ? -wheel[1] : wheel[1]\n let v\n if (wheel[0] == 'normalized') {\n const n = normalizeValue(value, min, max, skew)\n v = rawValue(n + x, min, max, skew)\n } else {\n v = value + x\n }\n if (onChange) onChange(clamp(stepValue(v, step), min, max))\n },\n { passive: false },\n [wheel, value, min, max, skew, step, onChange],\n )\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n elmRef.current?.focus()\n },\n blur() {\n elmRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <div\n className={clsx('tremolo-animation-knob', className)}\n ref={(div) => {\n elmRef.current = div\n wheelRefCallback(div)\n touchMoveRefCallback(div)\n }}\n role=\"slider\"\n tabIndex={0}\n aria-valuenow={value}\n aria-valuemax={max}\n aria-valuemin={min}\n style={{\n display: 'inline-block',\n width: size ?? width,\n height: size ?? height,\n cursor: 'pointer',\n WebkitTapHighlightColor: 'transparent',\n ...style,\n }}\n onPointerDown={pointerDownHandler}\n onDoubleClick={() => {\n if (enableDoubleClickDefault && onChange) {\n onChange(defaultValue)\n }\n }}\n onKeyDown={handleKeyDown}\n {...props}\n >\n <AnimationCanvas\n {...(isRelativeSize\n ? { relativeSize: true }\n : {\n width: size ?? width,\n height: size ?? height,\n })}\n draw={\n draw\n ? draw\n : (ctx, { width, height }) => {\n const p = normalizeValue(value, min, max, skew)\n const startP = normalizeValue(startValue, min, max, skew)\n const cx = width / 2\n const cy = height / 2\n const r = Math.min(cx, cy)\n if (r <= 0) return\n\n // reset\n ctx.clearRect(0, 0, width, height)\n ctx.lineCap = 'butt'\n\n // bg\n ctx.beginPath()\n ctx.fillStyle = bg\n ctx.arc(cx, cy, r - 0.5, 0, 2 * Math.PI)\n ctx.fill()\n\n ctx.lineWidth = lineWeight\n\n // inactive rotary\n ctx.beginPath()\n ctx.strokeStyle = inactiveColor\n ctx.arc(\n cx,\n cy,\n r - 0.5 - lineWeight / 2,\n radian(135),\n radian(45),\n )\n ctx.stroke()\n\n // active rotary\n ctx.beginPath()\n ctx.strokeStyle = activeColor\n ctx.arc(\n cx,\n cy,\n r - 0.5 - lineWeight / 2,\n radian(135 + 270 * startP),\n radian(135 + 270 * p),\n p < startP,\n )\n ctx.stroke()\n\n // thumb\n ctx.lineCap = 'round'\n ctx.beginPath()\n ctx.moveTo(cx, cy)\n ctx.lineTo(\n cx +\n Math.cos(radian(135 + 270 * p)) *\n (r - 0.5 - thumbWeight / 2),\n cy +\n Math.sin(radian(135 + 270 * p)) *\n (r - 0.5 - thumbWeight / 2),\n )\n ctx.strokeStyle = thumb\n ctx.lineWidth = thumbWeight\n ctx.stroke()\n }\n }\n />\n </div>\n )\n },\n)\n","import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react'\n\nimport { useDrag } from '../../hooks/useDrag'\n\n/** @category DragObserver */\nexport interface DragObserverProps<T extends ElementType> {\n /**\n * React.ElementType\n * @default div\n */\n as?: T\n\n /**\n * Threshold at which the onDrag event fires.\n * Prevents onDrag events from firing, for example, when double-clicking.\n */\n threshold?: number\n\n children?: ReactNode\n onDrag: (x: number, y: number, deltaX: number, deltaY: number) => void\n onDragStart?: () => void\n onDragEnd?: () => void\n}\n\n/** @category DragObserver */\nexport function DragObserver<T extends ElementType = 'div'>(\n props: DragObserverProps<T> &\n Omit<ComponentPropsWithoutRef<T>, keyof DragObserverProps<T>>,\n) {\n const {\n as: Component = 'div',\n threshold = 1,\n children,\n onDrag,\n onDragStart,\n onDragEnd,\n ...attributes\n } = props\n\n const [refCallback, pointerDownHandler] = useDrag({\n threshold: threshold,\n onDrag: onDrag,\n onDragStart: onDragStart,\n onDragEnd: onDragEnd,\n })\n\n return (\n <Component\n ref={refCallback}\n onPointerDown={pointerDownHandler}\n {...attributes}\n >\n {children}\n </Component>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n useCallback,\n useImperativeHandle,\n useRef,\n} from 'react'\n\nimport {\n clamp,\n InputEventOption,\n normalizeValue,\n radian,\n rawValue,\n stepValue,\n} from '@tremolo-ui/functions'\n\nimport { useDrag } from '../../hooks/useDrag'\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\nimport { addNoSelect, removeNoSelect } from '../_util'\n\n/** @category Knob */\nexport interface KnobProps {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n skew?: number // | SkewFunction\n /**\n * value set when double-clicking\n * @default min\n * @see enableDoubleClickDefault\n */\n defaultValue?: number\n\n /**\n * Value to be used as the starting point of the line when drawing.\n * @default min\n */\n startValue?: number\n\n // TODO: relative size (Lower priority)\n size?: number\n\n /** Whether to apply `{use-select: none}` when dragging */\n bodyNoSelect?: boolean\n /**\n * wheel control option\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n */\n keyboard?: InputEventOption | null\n enableDoubleClickDefault?: boolean\n\n disabled?: boolean\n readonly?: boolean\n\n /** color */\n activeLine?: string\n /** color */\n inactiveLine?: string\n /** color */\n thumb?: string\n /** color */\n thumbLine?: string\n\n /** percent (0-100) */\n thumbSize?: number\n /** percent (0-100) */\n thumbLineWeight?: number\n /** percent (0-100) */\n thumbLineLength?: number\n /** percent (0-100) */\n lineWeight?: number\n\n classes?: {\n activeLine?: string\n inactiveLine?: string\n thumb?: string\n thumbLine?: string\n }\n\n onChange?: (value: number) => void\n}\n\n/**\n * @category Knob\n */\nexport interface KnobMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = KnobProps & Omit<ComponentPropsWithoutRef<'svg'>, keyof KnobProps>\n\n/**\n * Interactive rotary knob component implemented in SVG.\n *\n * @category Knob\n */\nexport const Knob = forwardRef<KnobMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n skew = 1,\n defaultValue = min,\n startValue = min,\n size = 50,\n bodyNoSelect = true,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n enableDoubleClickDefault = true,\n disabled = false,\n readonly = false,\n activeLine,\n inactiveLine,\n thumb,\n thumbLine,\n onChange,\n onKeyDown,\n onPointerDown,\n onDoubleClick,\n className,\n classes,\n ...props\n }: Props,\n ref,\n ) => {\n const valueRef = useRef(0)\n const elmRef = useRef<HTMLOrSVGElement>(null)\n\n // --- interpret props ---\n const padding = 8 // %\n const thumbLineWeight = 6 // %\n const thumbLineLength = 35 // %\n const lineWeight = size * 0.06 // px\n const p = normalizeValue(value, min, max, skew)\n const s = normalizeValue(startValue, min, max, skew)\n\n // --- internal functions ---\n const onDrag = useCallback(\n (_x: number, y: number) => {\n if (!onChange || readonly) return\n const v = rawValue(valueRef.current - y / 100, min, max, skew)\n const v2 = clamp(stepValue(v, step), min, max)\n onChange(v2)\n },\n [max, min, onChange, readonly, skew, step],\n )\n\n const updateValueByEvent = useCallback(\n (eventType: InputEventOption[0], x: number) => {\n let newValue\n if (eventType == 'normalized') {\n const n = normalizeValue(value, min, max, skew)\n newValue = rawValue(n + x, min, max, skew)\n } else {\n newValue = value + x\n }\n return clamp(stepValue(newValue, step), min, max)\n },\n [max, min, skew, step, value],\n )\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLOrSVGElement>) => {\n if (!keyboard || !onChange || readonly) return\n const key = event.key\n if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {\n event.preventDefault()\n const x =\n key == 'ArrowRight' || key == 'ArrowUp' ? keyboard[1] : -keyboard[1]\n onChange(updateValueByEvent(keyboard[0], x))\n }\n },\n [keyboard, onChange, readonly, updateValueByEvent],\n )\n\n // --- hooks ---\n const [touchMoveRefCallback, pointerDownHandler] = useDrag<SVGElement>({\n onDrag: onDrag,\n onDragStart: () => {\n valueRef.current = normalizeValue(value, min, max, skew)\n if (bodyNoSelect) addNoSelect()\n },\n onDragEnd: () => {\n if (bodyNoSelect) removeNoSelect()\n },\n })\n\n const wheelRefCallback = useRefCallbackEvent(\n 'wheel',\n (event) => {\n if (!wheel || readonly) return\n event.preventDefault()\n if (!onChange || event.deltaY == 0) return\n const x = Math.sign(event.deltaY) * -wheel[1]\n onChange(updateValueByEvent(wheel[0], x))\n },\n { passive: false },\n [wheel, onChange, readonly, updateValueByEvent],\n )\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n elmRef.current?.focus()\n },\n blur() {\n elmRef.current?.blur()\n },\n }\n }, [])\n\n const center = size / 2\n const r1 = -135\n const r2 = -135 + Math.min(p, s) * 270\n const r3 = -135 + Math.max(p, s) * 270\n const r4 = 135\n const x1 = center + center * Math.cos(radian(r1 - 90))\n const y1 = center + center * Math.sin(radian(r1 - 90))\n const x2 = center + center * Math.cos(radian(r2 - 90))\n const y2 = center + center * Math.sin(radian(r2 - 90))\n const x3 = center + center * Math.cos(radian(r3 - 90))\n const y3 = center + center * Math.sin(radian(r3 - 90))\n const x4 = center + center * Math.cos(radian(r4 - 90))\n const y4 = center + center * Math.sin(radian(r4 - 90))\n\n return (\n <svg\n className={clsx('tremolo-knob', className)}\n ref={(div) => {\n elmRef.current = div\n wheelRefCallback(div)\n touchMoveRefCallback(div)\n }}\n width={size}\n height={size}\n tabIndex={0}\n role=\"slider\"\n aria-valuenow={value}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-disabled={disabled}\n aria-readonly={readonly}\n onPointerDown={(event) => {\n pointerDownHandler(event)\n onPointerDown?.(event)\n }}\n onDoubleClick={(event) => {\n if (enableDoubleClickDefault && onChange) {\n onChange(defaultValue)\n }\n onDoubleClick?.(event)\n }}\n onKeyDown={(event) => {\n handleKeyDown(event)\n onKeyDown?.(event)\n }}\n {...props}\n >\n {/* rotary meter */}\n {startValue > min && (\n <path\n className={clsx(\n 'tremolo-knob-inactive-line',\n classes?.inactiveLine,\n )}\n d={`M ${x1} ${y1} A ${center} ${center} -135 ${r2 - r1 > 180 ? 1 : 0} 1 ${x2}, ${y2}`}\n fill=\"none\"\n stroke={inactiveLine || 'currentColor'}\n strokeWidth={lineWeight}\n />\n )}\n <path\n className={clsx('tremolo-knob-active-line', classes?.activeLine)}\n d={`M ${x2} ${y2} A ${center} ${center} -135 ${r3 - r2 > 180 ? 1 : 0} 1 ${x3}, ${y3}`}\n fill=\"none\"\n stroke={activeLine || 'currentColor'}\n strokeWidth={lineWeight}\n />\n {startValue < max && (\n <path\n className={clsx(\n 'tremolo-knob-inactive-line',\n classes?.inactiveLine,\n )}\n d={`M ${x3} ${y3} A ${center} ${center} -135 ${r4 - r3 > 180 ? 1 : 0} 1 ${x4}, ${y4}`}\n fill=\"none\"\n stroke={inactiveLine || 'currentColor'}\n strokeWidth={lineWeight}\n />\n )}\n {/* thumb */}\n <svg className={clsx('tremolo-knob-thumb', classes?.thumb)}>\n <circle\n cx=\"50%\"\n cy=\"50%\"\n r={`${50 - padding}%`}\n fill={thumb || 'currentColor'}\n />\n <line\n className={clsx('tremolo-knob-thumb-line', classes?.thumbLine)}\n x1=\"50%\"\n y1={`${padding}%`}\n x2=\"50%\"\n y2={`${thumbLineLength}%`}\n stroke={thumbLine || 'currentColor'}\n strokeWidth={`${thumbLineWeight}%`}\n // NOTE\n // https://bugs.webkit.org/show_bug.cgi?id=201854\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/transform-origin#browser_compatibility\n style={{\n transform: `rotate(${-135 + p * 270}deg)`,\n transformOrigin: '50% 50%',\n }}\n />\n </svg>\n </svg>\n )\n },\n)\n","import { createContext, useContext, useEffect, useRef } from 'react'\nimport { createStore, useStore } from 'zustand'\n\nimport { clamp } from '@tremolo-ui/functions'\nimport { parseValue, Units } from '@tremolo-ui/functions/NumberInput'\n\ntype State = {\n value: string\n valueAsNumber: number\n step: number\n\n min?: number\n max?: number\n units?: string | Units\n digit?: number\n readonly?: boolean\n keepWithinRange?: boolean\n onChange?: (value: number, text: string) => void\n}\n\ntype Action = {\n increment: () => void\n decrement: () => void\n change: (value: string) => void\n}\n\ntype NumberInputStore = ReturnType<typeof createNumberInputStore>\n\ntype ProviderProps = Partial<Omit<State, 'value'> & { value: number | string }>\n\nexport function safeClamp(\n value: number,\n min = Number.MIN_SAFE_INTEGER,\n max = Number.MAX_SAFE_INTEGER,\n) {\n return clamp(value, min, max)\n}\n\nconst createNumberInputStore = (initProps?: ProviderProps) => {\n const DEFAULT_PROPS: State = {\n value: '',\n valueAsNumber: 0,\n min: 0,\n max: 0,\n step: 1,\n readonly: false,\n keepWithinRange: true,\n onChange: (_v: number, _t: string) => {},\n }\n\n return createStore<State & Action>()((set) => ({\n ...DEFAULT_PROPS,\n ...initProps,\n ...{\n value: parseValue(\n String(initProps?.value || ''),\n initProps?.units,\n initProps?.digit,\n ).formatValue,\n valueAsNumber: parseValue(\n String(initProps?.value || ''),\n initProps?.units,\n initProps?.digit,\n ).rawValue,\n },\n increment: () =>\n set((state) => {\n if (state.readonly) return {}\n const current = parseValue(\n state.value,\n state.units,\n state.digit,\n ).rawValue\n let next = current + (state.step ?? 1)\n if (state.keepWithinRange) {\n next = safeClamp(next, state.min, state.max)\n }\n const v = parseValue(String(next), state.units, state.digit).formatValue\n state?.onChange?.(next, v)\n return {\n value: v,\n valueAsNumber: next,\n }\n }),\n decrement: () =>\n set((state) => {\n if (state.readonly) return {}\n const current = parseValue(\n state.value,\n state.units,\n state.digit,\n ).rawValue\n let next = current - (state.step ?? 1)\n if (state.keepWithinRange) {\n next = safeClamp(next, state.min, state.max)\n }\n const v = parseValue(String(next), state.units, state.digit).formatValue\n state?.onChange?.(next, v)\n return {\n value: v,\n valueAsNumber: next,\n }\n }),\n change: (value) =>\n set((state) => {\n if (state.readonly) return {}\n const v = value ?? ''\n return {\n value: v,\n valueAsNumber: parseValue(v, state.units, state.digit).rawValue,\n }\n }),\n }))\n}\n\nconst NumberInputContext = createContext<NumberInputStore | null>(null)\n\ntype NumberInputProviderProps = React.PropsWithChildren<ProviderProps>\n\nexport function NumberInputProvider({\n children,\n ...props\n}: NumberInputProviderProps) {\n const storeRef = useRef<NumberInputStore>(null)\n if (!storeRef.current) {\n storeRef.current = createNumberInputStore(props)\n }\n\n useEffect(() => {\n if (storeRef.current) {\n const parsed = parseValue(\n String(props?.value || ''),\n props?.units,\n props?.digit,\n )\n storeRef.current.setState({\n ...props,\n ...{\n value: parsed.formatValue,\n valueAsNumber: parsed.rawValue,\n },\n })\n } else {\n storeRef.current = createNumberInputStore(props)\n }\n }, [props])\n\n return (\n <NumberInputContext.Provider value={storeRef.current}>\n {children}\n </NumberInputContext.Provider>\n )\n}\n\n/** @category NumberInput */\nexport function useNumberInputContext<T>(\n selector: (state: State & Action) => T,\n): T {\n const store = useContext(NumberInputContext)\n if (!store) throw new Error('Missing NumberInputContext.Provider in the tree')\n return useStore(store, selector)\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport {\n clamp,\n InputEventOption,\n normalizeValue,\n rawValue,\n stepValue,\n} from '@tremolo-ui/functions'\nimport { parseValue } from '@tremolo-ui/functions/NumberInput'\n\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\n\nimport { safeClamp, useNumberInputContext } from './context'\n\nimport { NumberInputMethods } from '.'\n\ninterface InternalProps {\n disabled: boolean\n readonly: boolean\n wheel: InputEventOption | null\n keyboard: InputEventOption | null\n\n selectWithFocus?: 'all' | 'number' | 'none'\n blurOnEnter?: boolean\n keepWithinRange?: boolean\n clampValueOnBlur?: boolean\n\n onChange?: (value: number, text: string) => void\n onFocus?: (\n value: number,\n text: string,\n event: React.FocusEvent<HTMLInputElement, Element>,\n ) => void\n onBlur?: (\n value: number,\n text: string,\n event: React.FocusEvent<HTMLInputElement, Element>,\n ) => void\n}\n\ntype InternalPropsWithAttributes = InternalProps &\n Omit<ComponentPropsWithoutRef<'input'>, keyof InternalProps>\n\nexport const InternalInput = forwardRef<\n NumberInputMethods,\n InternalPropsWithAttributes\n>(\n (\n {\n disabled,\n readonly,\n selectWithFocus,\n blurOnEnter,\n clampValueOnBlur,\n wheel,\n keyboard,\n className,\n onChange,\n onFocus,\n onBlur,\n onKeyDown,\n children: _children,\n ...props\n }: InternalPropsWithAttributes,\n ref,\n ) => {\n const elmRef = useRef<HTMLInputElement>(null)\n const [editing, setEditing] = useState(false)\n const value = useNumberInputContext((s) => s.value)\n const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber)\n const min = useNumberInputContext((s) => s.min)\n const max = useNumberInputContext((s) => s.max)\n const step = useNumberInputContext((s) => s.step)\n const units = useNumberInputContext((s) => s.units)\n const digit = useNumberInputContext((s) => s.digit)\n const change = useNumberInputContext((s) => s.change)\n\n const error = useMemo(() => {\n if (editing) return false\n const v = valueAsNumber\n return (min ?? -Infinity) > v || v > (max ?? Infinity)\n }, [editing, max, min, valueAsNumber])\n\n const updateValueByEvent = useCallback(\n (eventType: InputEventOption[0], x: number) => {\n let newValue\n if (eventType == 'normalized') {\n if (!min || !max) {\n throw new Error('required parameter: min, max') // TODO\n }\n const n = normalizeValue(valueAsNumber, min, max)\n newValue = rawValue(n + x, min, max)\n return clamp(stepValue(newValue, step), min, max)\n } else {\n newValue = valueAsNumber + x\n return stepValue(newValue, step)\n }\n },\n [max, min, step, valueAsNumber],\n )\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!keyboard || !onChange || readonly) return\n const key = event.key\n if (!['ArrowUp', 'ArrowDown'].includes(key)) return\n event.preventDefault()\n const x = key == 'ArrowUp' ? keyboard[1] : -keyboard[1]\n const parsed = parseValue(String(updateValueByEvent(keyboard[0], x)))\n // console.log('key control')\n onChange?.(parsed.rawValue, parsed.formatValue)\n },\n [keyboard, readonly, onChange, updateValueByEvent],\n )\n\n const wheelRefCallback = useRefCallbackEvent(\n 'wheel',\n (event) => {\n if (!wheel || readonly) return\n event.preventDefault()\n if (!onChange || event.deltaY == 0) return\n const x = Math.sign(event.deltaY) * -wheel[1]\n const parsed = parseValue(String(updateValueByEvent(wheel[0], x)))\n // console.log('wheel control')\n onChange?.(parsed.rawValue, parsed.formatValue)\n },\n { passive: false },\n [wheel, readonly, onChange, updateValueByEvent],\n )\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n elmRef.current?.focus()\n },\n blur() {\n elmRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <input\n ref={(input) => {\n elmRef.current = input\n wheelRefCallback(input)\n }}\n className={clsx('tremolo-number-input', className)}\n value={value}\n min={min}\n max={max}\n step={step}\n type=\"text\"\n aria-disabled={disabled}\n aria-readonly={readonly}\n tabIndex={-1}\n data-error={error}\n onChange={(event) => {\n if (readonly) return\n const v = event.currentTarget.value\n const cursorPos = event.target.selectionStart\n change(v)\n const valueAsNumber = parseValue(v, units, digit).rawValue\n onChange?.(valueAsNumber, v)\n if (cursorPos) {\n event.target.selectionStart = cursorPos\n event.target.selectionEnd = cursorPos\n }\n }}\n onFocus={(event) => {\n setEditing(true)\n const v = event.currentTarget.value\n const parsed = parseValue(v, units, digit)\n if (selectWithFocus == 'all') {\n event.currentTarget.setSelectionRange(0, v.length)\n } else if (selectWithFocus == 'number') {\n event.currentTarget.setSelectionRange(\n 0,\n parsed.formatValue.length - parsed.unit.length,\n )\n }\n onFocus?.(parsed.rawValue, parsed.formatValue, event)\n }}\n onBlur={(event) => {\n setEditing(false)\n // update value\n let v = parseValue(event.currentTarget.value, units, digit).rawValue\n if (clampValueOnBlur) {\n v = safeClamp(v, min, max)\n }\n const parsed = parseValue(String(v), units, digit)\n change(parsed.formatValue)\n if (clampValueOnBlur) {\n onChange?.(parsed.rawValue, parsed.formatValue)\n }\n onBlur?.(parsed.rawValue, parsed.formatValue, event)\n }}\n onKeyDown={(event) => {\n if (blurOnEnter && event.key == 'Enter') {\n event.currentTarget.blur()\n }\n handleKeyDown(event)\n onKeyDown?.(event)\n }}\n {...props}\n />\n )\n },\n)\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\n/** @category NumberInput */\nexport interface StepperProps {\n /** Display only when hovering. */\n dynamic?: boolean\n children?: ReactNode\n}\n\n/** @category NumberInput */\nexport function Stepper({\n dynamic = true,\n children,\n className,\n ...props\n}: StepperProps & Omit<ComponentPropsWithoutRef<'div'>, keyof StepperProps>) {\n return (\n <div\n className={clsx('tremolo-number-input-stepper', className)}\n data-dynamic={dynamic}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import { useEffect, useRef } from 'react'\n\nexport function useInterval(callback: () => void, delay: number | null) {\n const savedCallback = useRef(callback)\n\n // Remember the latest callback if it changes.\n useEffect(() => {\n savedCallback.current = callback\n }, [callback])\n\n // Set up the interval.\n useEffect(() => {\n // Don't schedule if no delay is specified.\n // Note: 0 is a valid value for delay.\n if (delay === null) {\n return\n }\n\n const id = setInterval(() => {\n savedCallback.current()\n }, delay)\n\n return () => {\n clearInterval(id)\n }\n }, [delay])\n}\n","import { useCallback, useState } from 'react'\n\nimport { useEventListener } from './useEventListener'\nimport { useInterval } from './useInterval'\n\nexport function useLongPress(\n callback: () => void,\n initialDelay = 500,\n interval = 40,\n) {\n const [pressed, setPressed] = useState(false)\n const [delay, setDelay] = useState(initialDelay)\n\n useInterval(\n () => {\n callback()\n setDelay(interval)\n },\n pressed ? delay : null,\n )\n\n useEventListener(globalThis.window, 'pointerup', () => {\n setPressed(false)\n setDelay(initialDelay)\n })\n\n return useCallback(() => {\n callback()\n setPressed(true)\n }, [callback])\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport { useLongPress } from '../../hooks/useLongPress'\n\nimport { useNumberInputContext } from './context'\n\n/** @category NumberInput */\nexport interface IncrementStepperProps {\n size?: number\n children?: ReactNode\n}\n\n/** @category NumberInput */\nexport function IncrementStepper({\n size = 12,\n children,\n className,\n ...props\n}: IncrementStepperProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof IncrementStepperProps>) {\n const max = useNumberInputContext((s) => s.max)\n const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber)\n const readonly = useNumberInputContext((s) => s.readonly)\n const keepWithinRange = useNumberInputContext((s) => s.keepWithinRange)\n const increment = useNumberInputContext((s) => s.increment)\n\n const press = useLongPress(increment)\n\n return (\n // eslint-disable-next-line jsx-a11y/role-supports-aria-props\n <div\n className={clsx('tremolo-number-input-increment-stepper', className)}\n role=\"button\"\n tabIndex={-1}\n aria-disabled={\n keepWithinRange && valueAsNumber >= (max ?? Number.MAX_SAFE_INTEGER)\n }\n aria-readonly={readonly}\n onPointerDown={press}\n {...props}\n >\n {children || (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"18 15 12 9 6 15\" />\n </svg>\n )}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport { useLongPress } from '../../hooks/useLongPress'\n\nimport { useNumberInputContext } from './context'\n\n/** @category NumberInput */\nexport interface DecrementStepperProps {\n size?: number\n children?: ReactNode\n}\n\n/** @category NumberInput */\nexport function DecrementStepper({\n size = 12,\n children,\n className,\n ...props\n}: DecrementStepperProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof DecrementStepperProps>) {\n const min = useNumberInputContext((s) => s.min)\n const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber)\n const readonly = useNumberInputContext((s) => s.readonly)\n const keepWithinRange = useNumberInputContext((s) => s.keepWithinRange)\n const decrement = useNumberInputContext((s) => s.decrement)\n\n const press = useLongPress(decrement)\n\n return (\n // eslint-disable-next-line jsx-a11y/role-supports-aria-props\n <div\n className={clsx('tremolo-number-input-decrement-stepper', className)}\n role=\"button\"\n tabIndex={-1}\n aria-disabled={\n keepWithinRange && valueAsNumber <= (min ?? Number.MIN_SAFE_INTEGER)\n }\n aria-readonly={readonly}\n onPointerDown={press}\n {...props}\n >\n {children || (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n )}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, forwardRef, ReactNode } from 'react'\n\nimport { InputEventOption } from '@tremolo-ui/functions'\nimport { Units } from '@tremolo-ui/functions/NumberInput'\n\nimport { NumberInputProvider } from './context'\nimport { InternalInput } from './InternalInput'\n\n/*\nTODO\n- numberMode: focusが当たった時だけ、parse + type=\"number\"にする\n- skew\n*/\n\n/** @category NumberInput */\nexport interface NumberInputProps {\n value: number | string\n\n /**\n * @default Number.MIN_SAFE_INTEGER\n */\n min?: number\n /**\n * @default Number.MAX_SAFE_INTEGER\n */\n max?: number\n step?: number\n\n /**\n * @example\n * units='Hz'\n * units={[['Hz', 1], ['kHz', 1000]]}\n * units={[['ms', 1], ['s', 1000]]}\n */\n units?: string | Units\n\n /**\n * Digits for rounding numbers.\n * @example\n * with:\n * units={[['Hz', 1], ['kHz', 1000]]}\n * digit={3}\n * results:\n * value=100 -> 100Hz, value=1600 -> 1.60Hz\n */\n digit?: number\n\n readonly?: boolean\n\n variant?: 'outline' | 'filled' | 'flushed' | 'unstyled'\n\n selectWithFocus?: 'all' | 'number' | 'none'\n blurOnEnter?: boolean\n keepWithinRange?: boolean\n clampValueOnBlur?: boolean\n\n // TODO\n /**\n * wheel control option\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n */\n keyboard?: InputEventOption | null\n\n activeColor?: string\n\n wrapperClassName?: string\n\n onChange?: (value: number, text: string) => void\n onFocus?: (\n value: number,\n text: string,\n event: React.FocusEvent<HTMLInputElement, Element>,\n ) => void\n onBlur?: (\n value: number,\n text: string,\n event: React.FocusEvent<HTMLInputElement, Element>,\n ) => void\n\n children?: ReactNode\n}\n\n/**\n * @category NumberInput\n */\nexport interface NumberInputMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = NumberInputProps &\n Omit<ComponentPropsWithoutRef<'input'>, keyof NumberInputProps | 'type'>\n\n/**\n * Input with some useful functions for entering numerical values.\n * @category NumberInput\n */\nexport const NumberInput = forwardRef<NumberInputMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n units,\n readonly = false,\n disabled = false,\n digit,\n variant = 'outline',\n selectWithFocus = 'none',\n blurOnEnter = true,\n keepWithinRange = true,\n clampValueOnBlur = true,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n activeColor,\n wrapperClassName,\n className,\n onChange,\n onFocus,\n onBlur,\n children,\n ...props\n }: Props,\n ref,\n ) => {\n const colors: { [key: string]: string | undefined } = {\n '--active-color': activeColor,\n }\n return (\n <NumberInputProvider\n value={String(value)}\n min={min}\n max={max}\n step={step}\n units={units}\n digit={digit}\n readonly={readonly}\n keepWithinRange={keepWithinRange}\n onChange={onChange}\n >\n <div\n className={clsx('tremolo-number-input-wrapper', wrapperClassName)}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n style={{\n ...colors,\n }}\n data-stepper={!!children}\n data-variant={variant}\n >\n <InternalInput\n ref={ref}\n readonly={readonly}\n disabled={disabled}\n selectWithFocus={selectWithFocus}\n blurOnEnter={blurOnEnter}\n clampValueOnBlur={clampValueOnBlur}\n wheel={wheel}\n keyboard={keyboard}\n className={className}\n onChange={onChange}\n onFocus={onFocus}\n onBlur={onBlur}\n {...props}\n />\n {children}\n </div>\n </NumberInputProvider>\n )\n },\n)\n\nexport * from './Stepper'\nexport * from './IncrementStepper'\nexport * from './DecrementStepper'\n","import { useRef, useCallback, RefObject } from 'react'\n\nimport { normalizeValue } from '@tremolo-ui/functions'\n\nimport { useEventListener } from './useEventListener'\nimport { useRefCallbackEvent } from './useRefCallbackEvent'\n\nexport interface UseDragWithElementProps<T extends Element> {\n baseElementRef: RefObject<T | null>\n onDrag: (normalizedX: number, normalizedY: number) => void\n onDragStart?: (normalizedX: number, normalizedY: number) => void\n onDragEnd?: (normalizedX: number, normalizedY: number) => void\n}\n\n/**\n * @returns [refCallback, pointerDownHandler]\n */\nexport function useDragWithElement<T extends Element>({\n baseElementRef,\n onDrag,\n onDragStart,\n onDragEnd,\n}: UseDragWithElementProps<T>): [\n (div: EventTarget | null) => void,\n (event: React.PointerEvent<T>) => void,\n] {\n const dragged = useRef(false)\n const normalizedX = useRef(0)\n const normalizedY = useRef(0)\n\n const handleDrag = useCallback(\n (event: MouseEvent | React.PointerEvent<T> | TouchEvent) => {\n if (!baseElementRef.current || !dragged.current) {\n return\n }\n const isTouch = event instanceof TouchEvent\n if (isTouch && event.cancelable) event.preventDefault()\n const { left, top, right, bottom } =\n baseElementRef.current.getBoundingClientRect()\n const mouseX = isTouch ? event.touches[0].clientX : event.clientX\n const mouseY = isTouch ? event.touches[0].clientY : event.clientY\n const nx = normalizeValue(mouseX, left, right)\n const ny = normalizeValue(mouseY, top, bottom)\n normalizedX.current = nx\n normalizedY.current = ny\n onDrag(nx, ny)\n },\n [onDrag, baseElementRef],\n )\n\n const refHandler = useRefCallbackEvent(\n 'touchmove',\n handleDrag,\n { passive: false },\n [onDrag],\n )\n\n const pointerDownHandler = useCallback(\n (event: React.PointerEvent<T>) => {\n dragged.current = true\n handleDrag(event)\n onDragStart?.(normalizedX.current, normalizedY.current)\n },\n [handleDrag, onDragStart],\n )\n\n useEventListener(globalThis.window, 'pointermove', handleDrag)\n\n useEventListener(globalThis.window, 'pointerup', () => {\n if (!dragged.current) return\n dragged.current = false\n onDragEnd?.(normalizedX.current, normalizedY.current)\n })\n\n return [refHandler, pointerDownHandler]\n}\n","import { createContext, ReactNode, useContext, useEffect, useRef } from 'react'\nimport { createStore, useStore } from 'zustand'\n\n/** @category Piano */\nexport type NoteRange = {\n first: number\n last: number\n}\n\ntype State = {\n noteRange: NoteRange\n glissando: boolean\n midiMax: number\n fill: boolean\n onPlayNote: (noteNumber: number) => void\n onStopNote: (noteNumber: number) => void\n label: (note: number, index: number) => ReactNode\n}\n\ntype Action = {\n notePosition: (note: number) => number\n}\n\ntype PianoStore = ReturnType<typeof createPianoStore>\n\nconst createPianoStore = (initProps: Partial<State> & Action) => {\n // const noteRange = initProps.noteRange || { first: 0, last: 127 }\n const DEFAULT_PROPS: State = {\n noteRange: { first: 0, last: 127 },\n glissando: true,\n midiMax: 127,\n fill: false,\n label: () => undefined,\n onPlayNote: () => {},\n onStopNote: () => {},\n }\n\n return createStore<State & Action>()(() => ({\n ...DEFAULT_PROPS,\n ...initProps,\n notePosition: initProps.notePosition,\n }))\n}\n\nconst PianoContext = createContext<PianoStore | null>(null)\n\ntype PianoProviderProps = React.PropsWithChildren<Partial<State> & Action>\n\nexport function PianoProvider({ children, ...props }: PianoProviderProps) {\n const storeRef = useRef<PianoStore>(null)\n if (!storeRef.current) {\n storeRef.current = createPianoStore(props)\n }\n\n useEffect(() => {\n if (storeRef.current) {\n storeRef.current.setState(props)\n } else {\n storeRef.current = createPianoStore(props)\n }\n }, [props])\n\n return (\n <PianoContext.Provider value={storeRef.current}>\n {children}\n </PianoContext.Provider>\n )\n}\n\n/** @category Piano */\nexport function usePianoContext<T>(selector: (state: State & Action) => T): T {\n const store = useContext(PianoContext)\n if (!store) throw new Error('Missing PianoContext.Provider in the tree')\n return useStore(store, selector)\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react'\n\nimport { usePianoContext } from './context'\n\nimport { getNoteRangeArray } from '.'\n\n/** @category Piano */\nexport interface KeyLabelProps {\n /**\n * override Piano.label\n */\n label?: (note: number, index: number) => ReactNode\n\n wrapperClassName?: string\n wrapperStyle?: CSSProperties\n\n /** @internal */\n __note?: number\n /** @internal */\n __label?: (note: number, index: number) => ReactNode\n}\n\n/** @category Piano */\nexport function KeyLabel({\n label,\n className,\n wrapperClassName,\n wrapperStyle,\n __note,\n __label,\n ...props\n}: KeyLabelProps & Omit<ComponentPropsWithoutRef<'div'>, keyof KeyLabelProps>) {\n const noteRange = usePianoContext((s) => s.noteRange)\n const noteRangeArray = getNoteRangeArray(noteRange)\n const index = noteRangeArray.indexOf(__note!)\n const content = label\n ? label(__note!, index)\n : __label && __label(__note!, index)\n\n return (\n (content != undefined || content != null) && (\n <div\n className={clsx('tremolo-piano-key-label-wrapper', wrapperClassName)}\n style={wrapperStyle}\n >\n <div className={clsx('tremolo-piano-key-label', className)} {...props}>\n {content}\n </div>\n </div>\n )\n )\n}\n","import clsx from 'clsx'\nimport React, {\n CSSProperties,\n ComponentPropsWithoutRef,\n forwardRef,\n useImperativeHandle,\n useState,\n ReactElement,\n} from 'react'\n\nimport { usePianoContext } from './context'\nimport { KeyLabel, KeyLabelProps } from './KeyLabel'\n\n/**\n * @category Piano\n */\nexport interface KeyProps {\n noteNumber: number\n\n width?: number\n height?: number | `${number}%`\n\n bg?: string\n color?: string\n activeBg?: string\n activeColor?: string\n\n style?: CSSProperties\n\n /**\n * \\<KeyLabel />\n */\n children?: ReactElement\n\n /** @internal */\n __width?: number\n}\n\n/**\n * @category Piano\n */\nexport interface KeyMethods {\n play: () => void\n stop: () => void\n played: () => boolean\n}\n\ntype Props = KeyProps & Omit<ComponentPropsWithoutRef<'div'>, keyof KeyProps>\ntype ImplProps = Props & { keyType: 'black' | 'white' }\n\n/** @category Piano */\nexport const defaultWhiteKeyWidth = 40\n/** @category Piano */\nexport const defaultBlackKeyWidth = 26\n\nconst KeyImpl = forwardRef<KeyMethods, ImplProps>(\n (\n {\n keyType,\n noteNumber,\n width,\n height,\n bg,\n color,\n activeBg,\n activeColor,\n className,\n style,\n children,\n __width,\n ...props\n }: ImplProps,\n ref,\n ) => {\n const [played, setPlayed] = useState(false)\n const midiMax = usePianoContext((s) => s.midiMax)\n const fill = usePianoContext((s) => s.fill)\n // const glissando = usePianoContext(s => s.glissando)\n const onPlayNote = usePianoContext((s) => s.onPlayNote)\n const onStopNote = usePianoContext((s) => s.onStopNote)\n const label = usePianoContext((s) => s.label)\n const notePosition = usePianoContext((s) => s.notePosition)\n const position = notePosition(noteNumber)\n\n const disabled = noteNumber > midiMax\n const colors = {\n '--bg': bg,\n '--color': color,\n '--active-bg': activeBg,\n '--active-color': activeColor,\n }\n\n useImperativeHandle(ref, () => {\n return {\n play() {\n if (disabled) return\n setPlayed(true)\n if (onPlayNote) onPlayNote(noteNumber)\n },\n stop() {\n setPlayed(false)\n if (onStopNote) onStopNote(noteNumber)\n },\n played() {\n return played\n },\n }\n }, [disabled, noteNumber, onPlayNote, onStopNote, played])\n\n let keyLabelProps: KeyLabelProps = {}\n if (children != undefined) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) {\n if (child.type == KeyLabel) {\n keyLabelProps = child.props as KeyLabelProps\n } else {\n throw new Error('only <KeyLabel>')\n }\n } else {\n throw new Error('children is an invalid element.')\n }\n })\n }\n\n return (\n <div\n className={clsx(`tremolo-piano-${keyType}-key`, className)}\n aria-disabled={disabled}\n data-active={played}\n style={{\n ...colors,\n left: position,\n width: fill ? __width : width,\n height: height,\n ...style,\n }}\n // onPointerDown={() => {\n // if (disabled) return\n // setPlayed(true)\n // if (onPlayNote) onPlayNote(noteNumber)\n // }}\n // onPointerEnter={() => {\n // if (disabled) return\n // if (glissando) {\n // setPlayed(true)\n // if (onPlayNote) onPlayNote(noteNumber)\n // }\n // }}\n // onPointerUp={() => {\n // if (disabled) return\n // setPlayed(false)\n // if (onStopNote) onStopNote(noteNumber)\n // }}\n // onPointerLeave={() => {\n // if (disabled) return\n // if (glissando) {\n // setPlayed(false)\n // if (onStopNote) onStopNote(noteNumber)\n // }\n // }}\n {...props}\n >\n <KeyLabel label={label} __note={noteNumber} {...keyLabelProps} />\n </div>\n )\n },\n)\n\n/** @category Piano */\nexport const WhiteKey = forwardRef<KeyMethods, Props>(\n (\n {\n width = defaultWhiteKeyWidth,\n height = '100%',\n onContextMenu = (e) => e.preventDefault(),\n ...props\n }: Props,\n ref,\n ) => {\n return (\n <KeyImpl\n ref={ref}\n keyType=\"white\"\n width={width}\n height={height}\n onContextMenu={onContextMenu}\n {...props}\n />\n )\n },\n)\n\n/** @category Piano */\nexport const BlackKey = forwardRef<KeyMethods, Props>(\n (\n {\n width = defaultBlackKeyWidth,\n height = '60%',\n onContextMenu = (e) => e.preventDefault(),\n ...props\n }: Props,\n ref,\n ) => {\n return (\n <KeyImpl\n ref={ref}\n keyType=\"black\"\n width={width}\n height={height}\n onContextMenu={onContextMenu}\n {...props}\n />\n )\n },\n)\n","/** @category Piano */\nexport type KeyboardShortcuts = {\n keys: string[]\n // TODO\n flags?: {\n naturalOnly?: boolean\n }\n}\n\n/** @category Piano */\nexport const SHORTCUTS = {\n HOME_ROW: {\n keys: [\n 'a',\n 'w',\n 's',\n 'e',\n 'd',\n 'f',\n 't',\n 'g',\n 'y',\n 'h',\n 'u',\n 'j',\n 'k',\n 'o',\n 'l',\n 'p',\n ';',\n ],\n },\n}\n","import clsx from 'clsx'\nimport React, {\n ComponentPropsWithoutRef,\n createRef,\n CSSProperties,\n ReactElement,\n ReactNode,\n RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport {\n isBlackKey,\n isWhiteKey,\n noteKey,\n NoteKey,\n noteKeys,\n} from '@tremolo-ui/functions'\n\nimport { useDragWithElement } from '../../hooks/useDragWithElement'\nimport { useEventListener } from '../../hooks/useEventListener'\n\nimport { NoteRange, PianoProvider } from './context'\nimport {\n BlackKey,\n defaultBlackKeyWidth,\n defaultWhiteKeyWidth,\n KeyMethods,\n WhiteKey,\n} from './key'\nimport { KeyboardShortcuts } from './keyboardShortcuts'\n\n/**\n * Piano component\n *\n * TODO:\n * - add scale highlight\n */\n\n/** @category Piano */\nexport function getNoteRangeArray(noteRange: NoteRange) {\n return Array.from(\n { length: noteRange.last - noteRange.first + 1 },\n (_, i) => i + noteRange.first,\n )\n}\n\n/** @category Piano */\nexport interface PianoProps {\n // required\n noteRange: NoteRange\n\n // optional\n glissando?: boolean\n midiMax?: number\n keyboardShortcuts?: KeyboardShortcuts\n fill?: boolean\n whiteNoteWidth?: number\n blackNoteWidth?: number\n height?: number | string\n\n style?: CSSProperties\n\n onPlayNote?: (noteNumber: number) => void\n onStopNote?: (noteNumber: number) => void\n\n label?: (note: number, index: number) => ReactNode\n\n /**\n * \\<WhiteKey /> | \\<BlackKey />\n */\n children?: ReactElement | ReactElement[]\n}\n\nconst blackPerWhiteWidth = defaultBlackKeyWidth / defaultWhiteKeyWidth // 0.65\n\n/**\n * Customizable piano component.\n * @category Piano\n */\nexport function Piano({\n noteRange,\n glissando = true,\n midiMax = 127,\n keyboardShortcuts,\n fill = false,\n height = fill ? '100%' : 160,\n whiteNoteWidth: _whiteNoteWidth = defaultWhiteKeyWidth,\n style,\n className,\n onPlayNote,\n onStopNote,\n label,\n children,\n onPointerDown,\n ...props\n}: PianoProps & Omit<ComponentPropsWithoutRef<'div'>, keyof PianoProps>) {\n // -- state and ref ---\n const [whiteNoteWidth, setWhiteNoteWidth] = useState(_whiteNoteWidth)\n const keyRefs = useRef<RefObject<KeyMethods | null>[]>([])\n for (let i = 0; i < noteRange.last - noteRange.first + 1; i++) {\n keyRefs.current[i] = createRef<KeyMethods>()\n }\n const pianoRef = useRef<HTMLDivElement>(null)\n const hitKeyIndex = useRef(-1)\n\n // --- interpret props ---\n const noteRangeArray = getNoteRangeArray(noteRange)\n const whiteNotes = noteRangeArray.filter((v) => isWhiteKey(v))\n const blackNotes = noteRangeArray.filter((v) => isBlackKey(v))\n const whiteNoteCount = whiteNotes.length\n const padding = 1\n const staticWidth = (whiteNoteWidth + padding) * whiteNoteCount\n // const blackNoteShiftPercent = 0.3\n\n const childrenWithProps = useMemo(() => {\n return (\n children &&\n React.Children.map(children, (child, index) => {\n if (React.isValidElement(child)) {\n const __width =\n child.type == WhiteKey ? whiteNoteWidth : whiteNoteWidth * 0.65\n const props = { ref: keyRefs.current[index], __width }\n return React.cloneElement(child, props)\n }\n return child\n })\n )\n }, [children, whiteNoteWidth])\n\n // --- internal functions ---\n const notePosition = useCallback(\n (note: number) => {\n const pitchPositions: Record<NoteKey, number> = {\n C: 0,\n 'C#': 1,\n D: 1,\n 'D#': 2,\n E: 2,\n F: 3,\n 'F#': 4,\n G: 4,\n 'G#': 5,\n A: 5,\n 'A#': 6,\n B: 6,\n }\n\n const blackNoteWidth = whiteNoteWidth * blackPerWhiteWidth\n const padding = 1\n const targetNoteKey = noteKey(note)\n const firstNoteKey = noteKey(noteRange.first)\n const octave = Math.floor((note - noteRange.first) / 12)\n const octaveOffset =\n noteKeys.indexOf(firstNoteKey) > noteKeys.indexOf(targetNoteKey) ? 1 : 0\n const w = whiteNoteWidth + padding\n const pos = pitchPositions[targetNoteKey] - pitchPositions[firstNoteKey]\n const blackKeyOffset = isBlackKey(note) ? blackNoteWidth / 2 : 0\n return pos * w + (octave + octaveOffset) * 7 * w - blackKeyOffset\n },\n [noteRange.first, whiteNoteWidth],\n )\n\n const getHitKeyIndex = useCallback(\n (x: number, y: number) => {\n if (!pianoRef.current) return -1\n const containerHeight = pianoRef.current.clientHeight\n const notes = [...blackNotes, ...whiteNotes]\n for (let i = 0; i < notes.length; i++) {\n const note = notes[i]\n const pos = notePosition(note)\n const w = isWhiteKey(note)\n ? whiteNoteWidth\n : whiteNoteWidth * blackPerWhiteWidth\n const h = isWhiteKey(note) ? containerHeight : containerHeight * 0.6\n if (pos <= x && x < pos + w && 0 <= y && y < h) {\n return note\n }\n }\n return -1\n },\n [blackNotes, notePosition, whiteNoteWidth, whiteNotes],\n )\n\n // TODO: 単一のポインターに対しては、useDragで対応可能だが、\n // マルチタッチに対しては、TouchEventを使う必要がありそう\n // 取り敢えず、シングルタッチだけ対応\n const onDrag = useCallback(\n (perX: number, perY: number) => {\n if (!pianoRef.current) return\n const x = perX * staticWidth\n const y = perY * pianoRef.current.clientHeight\n const note = getHitKeyIndex(x, y)\n const index = noteRangeArray.indexOf(note)\n if (index == -1) return\n if (hitKeyIndex.current != index) {\n keyRefs.current[hitKeyIndex.current]?.current?.stop()\n keyRefs.current[index]?.current?.play()\n hitKeyIndex.current = index\n }\n },\n [getHitKeyIndex, noteRangeArray, staticWidth],\n )\n\n const onDragEnd = useCallback(() => {\n if (keyRefs.current[hitKeyIndex.current]?.current?.played()) {\n keyRefs.current[hitKeyIndex.current]?.current?.stop()\n }\n hitKeyIndex.current = -1\n }, [keyRefs])\n\n // --- hooks ---\n useEffect(() => {\n if (fill && pianoRef.current) {\n const parent = pianoRef.current.parentElement\n if (!parent) throw new Error(\"doesn't have a parent element.\")\n const resizeObserver = new ResizeObserver(() => {\n const w = pianoRef.current!.clientWidth\n setWhiteNoteWidth(w / whiteNoteCount - padding)\n })\n resizeObserver.observe(parent)\n return () => {\n resizeObserver.unobserve(parent)\n }\n } else {\n setWhiteNoteWidth(_whiteNoteWidth)\n }\n }, [fill, _whiteNoteWidth, whiteNoteCount])\n\n const [touchMoveRefCallback, pointerDownHandler] =\n useDragWithElement<HTMLDivElement>({\n baseElementRef: pianoRef,\n onDrag: onDrag,\n onDragEnd: onDragEnd,\n })\n\n useEventListener(globalThis.window, 'keydown', (e) => {\n if (e.repeat) return\n if (!keyboardShortcuts) return\n const index = keyboardShortcuts.keys.indexOf(e.key)\n if (index != -1) {\n if (!keyRefs.current[index]?.current?.played()) {\n keyRefs.current[index]?.current?.play()\n }\n }\n })\n\n useEventListener(globalThis.window, 'keyup', (e) => {\n if (e.repeat) return\n if (!keyboardShortcuts) return\n const index = keyboardShortcuts.keys.indexOf(e.key)\n if (index != -1) {\n keyRefs.current[index]?.current?.stop()\n }\n })\n\n return (\n <PianoProvider\n notePosition={notePosition}\n noteRange={noteRange}\n glissando={glissando}\n midiMax={midiMax}\n fill={fill}\n onPlayNote={onPlayNote}\n onStopNote={onStopNote}\n label={label}\n >\n <div\n ref={(div) => {\n pianoRef.current = div\n touchMoveRefCallback(div)\n }}\n className={clsx('tremolo-piano', className)}\n style={{\n width: fill ? '100%' : staticWidth,\n height: height,\n ...style,\n }}\n onPointerDown={(event) => {\n pointerDownHandler(event)\n onPointerDown?.(event)\n }}\n {...props}\n >\n {childrenWithProps ||\n noteRangeArray.map((note, index) =>\n isWhiteKey(note) ? (\n <WhiteKey\n ref={keyRefs.current[index]}\n key={note}\n noteNumber={note}\n __width={whiteNoteWidth}\n />\n ) : (\n <BlackKey\n ref={keyRefs.current[index]}\n key={note}\n noteNumber={note}\n __width={whiteNoteWidth * blackPerWhiteWidth}\n />\n ),\n )}\n </div>\n </PianoProvider>\n )\n}\n\nexport * from './keyboardShortcuts'\n\nexport { WhiteKey, BlackKey, type KeyProps, type KeyMethods } from './key'\nexport { KeyLabel, type KeyLabelProps } from './KeyLabel'\n","import { createContext, useContext, useEffect, useRef } from 'react'\nimport { createStore, useStore } from 'zustand'\n\ntype State = {\n min: number\n max: number\n step: number\n skew: number\n vertical: boolean\n reverse: boolean\n disabled: boolean\n readonly: boolean\n}\n\ntype SliderStore = ReturnType<typeof createSliderStore>\n\nconst createSliderStore = (initProps?: Partial<State>) => {\n const DEFAULT_PROPS: State = {\n min: 0,\n max: 0,\n step: 0,\n skew: 0,\n vertical: false,\n reverse: false,\n disabled: false,\n readonly: false,\n }\n\n return createStore<State>()(() => ({\n ...DEFAULT_PROPS,\n ...initProps,\n }))\n}\n\nconst SliderContext = createContext<SliderStore | null>(null)\n\ntype SliderProviderProps = React.PropsWithChildren<Partial<State>>\n\nexport function SliderProvider({ children, ...props }: SliderProviderProps) {\n const storeRef = useRef<SliderStore>(null)\n if (!storeRef.current) {\n storeRef.current = createSliderStore(props)\n }\n\n useEffect(() => {\n if (storeRef.current) {\n storeRef.current.setState(props)\n } else {\n storeRef.current = createSliderStore(props)\n }\n }, [props])\n\n return (\n <SliderContext.Provider value={storeRef.current}>\n {children}\n </SliderContext.Provider>\n )\n}\n\n/** @category Slider */\nexport function useSliderContext<T>(selector: (state: State) => T): T {\n const store = useContext(SliderContext)\n if (!store) throw new Error('Missing SliderContext.Provider in the tree')\n return useStore(store, selector)\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, useCallback } from 'react'\n\nimport { toFixed, xor, normalizeValue } from '@tremolo-ui/functions'\nimport { ScaleType } from '@tremolo-ui/functions/Slider'\n\nimport { useSliderContext } from './context'\n\n/** @category Slider */\nexport interface ScaleOptionProps {\n // required\n value: number\n\n // optional\n type?: ScaleType\n /** Display text instead of value. */\n label?: string\n /** mark thickness */\n thickness?: number | string\n /** mark length */\n length?: number | string\n /** Gap between mark and label. */\n gap?: number | string\n labelWidth?: number | string\n classes?: {\n mark?: string\n label?: string\n }\n styles?: {\n mark?: CSSProperties\n label?: CSSProperties\n }\n}\n\n/** @category Slider */\nexport function ScaleOption({\n value,\n type = 'mark-number',\n label,\n thickness = 1,\n length = '0.5rem',\n gap = 2,\n labelWidth,\n classes,\n styles,\n className,\n style,\n ...props\n}: ScaleOptionProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof ScaleOptionProps>) {\n const min = useSliderContext((s) => s.min)\n const max = useSliderContext((s) => s.max)\n const skew = useSliderContext((s) => s.skew)\n const vertical = useSliderContext((s) => s.vertical)\n const reverse = useSliderContext((s) => s.reverse)\n\n const calcPercent = useCallback(\n (rawValue: number) => {\n return toFixed(\n xor(vertical, reverse)\n ? 100 - normalizeValue(rawValue, min, max, skew) * 100\n : normalizeValue(rawValue, min, max, skew) * 100,\n )\n },\n [vertical, reverse, max, min, skew],\n )\n\n return (\n <div\n className={clsx('tremolo-slider-scale-option', className)}\n style={{\n left: !vertical ? `${calcPercent(value)}%` : undefined,\n top: vertical ? `${calcPercent(value)}%` : undefined,\n ...style,\n }}\n data-vertical={vertical}\n {...props}\n >\n {type != 'number' && (\n <div\n className={clsx('tremolo-slider-scale-option-mark', classes?.mark)}\n style={{\n width: !vertical ? thickness : length,\n height: vertical ? thickness : length,\n marginBottom: !vertical ? gap : undefined,\n marginRight: vertical ? gap : undefined,\n ...styles?.mark,\n }}\n data-vertical={vertical}\n ></div>\n )}\n {type != 'mark' && (\n <div\n className={clsx('tremolo-slider-scale-option-label', classes?.label)}\n style={{\n width: labelWidth,\n ...styles?.label,\n }}\n >\n {label || value}\n </div>\n )}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport { xor } from '@tremolo-ui/functions'\nimport { generateOptionsList, ScaleOptions } from '@tremolo-ui/functions/Slider'\n\nimport { useSliderContext } from './context'\nimport { ScaleOption } from './ScaleOption'\n\n/** @category Slider */\nexport interface ScaleProps {\n gap?: number | string\n options?: ScaleOptions\n children?: ReactNode\n}\n\n/** @category Slider */\nexport function Scale({\n gap = 6,\n options,\n children,\n className,\n style,\n ...props\n}: ScaleProps & Omit<ComponentPropsWithoutRef<'div'>, keyof ScaleProps>) {\n const min = useSliderContext((s) => s.min)\n const max = useSliderContext((s) => s.max)\n const step = useSliderContext((s) => s.step)\n const vertical = useSliderContext((s) => s.vertical)\n const reverse = useSliderContext((s) => s.reverse)\n\n const optionsList = options\n ? generateOptionsList(options, min, max, step)\n : []\n if (xor(vertical, reverse)) optionsList.reverse()\n\n return (\n <div\n className={clsx('tremolo-slider-scale', className)}\n style={{\n marginLeft: vertical ? gap : undefined,\n marginTop: !vertical ? gap : undefined,\n ...style,\n }}\n {...props}\n >\n {options\n ? optionsList.map(({ value, type }, index) => {\n return <ScaleOption key={index} value={value} type={type} />\n })\n : children}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport {\n CSSProperties,\n forwardRef,\n ReactNode,\n useImperativeHandle,\n useRef,\n} from 'react'\n\nimport { useSliderContext } from './context'\n\n/** @category Slider */\nexport interface SliderThumbProps {\n size?: number | string\n width?: number | string\n height?: number | string\n\n color?: string\n\n className?: string\n style?: CSSProperties\n children?: ReactNode\n\n /** @internal */\n __percent?: number\n}\n\n/** @category Slider */\nexport interface SliderThumbMethods {\n focus: () => void\n blur: () => void\n}\n\n/** @category Slider */\nexport const defaultThumbSize = 22\n\n/** @category Slider */\nexport const SliderThumb = forwardRef<SliderThumbMethods, SliderThumbProps>(\n (\n {\n size,\n width = defaultThumbSize,\n height = defaultThumbSize,\n color,\n children,\n className,\n style,\n __percent,\n }: SliderThumbProps,\n ref,\n ) => {\n const wrapperRef = useRef<HTMLDivElement>(null)\n const vertical = useSliderContext((s) => s.vertical)\n const disabled = useSliderContext((s) => s.disabled)\n const readonly = useSliderContext((s) => s.readonly)\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n wrapperRef.current?.focus()\n },\n blur() {\n wrapperRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <div\n className=\"tremolo-slider-thumb-wrapper\"\n style={{\n top: vertical ? `${__percent}%` : '50%',\n left: !vertical ? `${__percent}%` : '50%',\n }}\n >\n {children ? (\n children\n ) : (\n // default slider thumb\n <div\n ref={wrapperRef}\n className={clsx('tremolo-slider-thumb', className)}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n aria-disabled={disabled}\n aria-readonly={readonly}\n style={{\n ...{ '--color': color },\n width: size ?? width,\n height: size ?? height,\n ...style,\n }}\n ></div>\n )}\n </div>\n )\n },\n)\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactElement } from 'react'\n\nimport { styleHelper, xor } from '@tremolo-ui/functions'\n\nimport { useSliderContext } from './context'\n\nexport const defaultLength = 140\nexport const defaultThickness = 10\n\n/** @category Slider */\nexport interface SliderTrackProps {\n length?: number | string\n thickness?: number | string\n\n active?: string\n inactive?: string\n\n defaultStyle?: boolean\n\n className?: string\n style?: CSSProperties\n children?: ReactElement\n\n /** @internal */\n __thumb?: ReactElement\n /** @internal */\n __percent?: number\n}\n\n/** @category Slider */\nexport function SliderTrack({\n length = defaultLength,\n thickness = defaultThickness,\n active,\n inactive,\n children,\n className,\n style,\n defaultStyle = true,\n __thumb,\n __percent = 0,\n ...props\n}: SliderTrackProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof SliderTrackProps>) {\n const vertical = useSliderContext((s) => s.vertical)\n const reverse = useSliderContext((s) => s.reverse)\n const disabled = useSliderContext((s) => s.disabled)\n\n const direction = vertical ? 'bottom' : 'right'\n const colors = {\n '--active': active,\n '--inactive': inactive,\n }\n\n return (\n <div\n className={clsx('tremolo-slider-track', className)}\n aria-disabled={disabled}\n data-vertical={vertical}\n style={\n !defaultStyle\n ? style\n : {\n ...colors,\n background: xor(vertical, reverse)\n ? `linear-gradient(to ${direction}, var(--inactive, #eee) ${__percent}%, var(--active, #7998ec) ${__percent}%)`\n : `linear-gradient(to ${direction}, var(--active, #7998ec) ${__percent}%, var(--inactive, #eee) ${__percent}%)`,\n borderRadius: styleHelper(thickness!, '/', 2),\n width: !vertical ? length : thickness,\n height: vertical ? length : thickness,\n ...style,\n }\n }\n {...props}\n >\n {children}\n {__thumb}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport React, {\n ComponentPropsWithoutRef,\n CSSProperties,\n forwardRef,\n ReactElement,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react'\n\nimport {\n clamp,\n normalizeValue,\n rawValue,\n stepValue,\n toFixed,\n InputEventOption,\n styleHelper,\n xor,\n} from '@tremolo-ui/functions'\n\nimport { useDragWithElement } from '../../hooks/useDragWithElement'\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\nimport { addNoSelect, removeNoSelect } from '../_util'\n\nimport { SliderProvider } from './context'\nimport { Scale } from './Scale'\nimport { SliderThumb, SliderThumbMethods, SliderThumbProps } from './Thumb'\nimport { SliderTrack, SliderTrackProps } from './Track'\n\n/** @category Slider */\nexport interface SliderProps {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n skew?: number // TODO | SkewFunction\n vertical?: boolean\n reverse?: boolean\n bodyNoSelect?: boolean\n /**\n * wheel control option\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n */\n keyboard?: InputEventOption | null\n /**\n * Only the appearance will change.\n * Please consider using with readonly.\n */\n disabled?: boolean\n /**\n * Make the value unchangeable.\n */\n readonly?: boolean\n className?: string\n style?: CSSProperties\n onChange?: (value: number) => void\n onDragStart?: (value: number) => void\n onDragEnd?: (value: number) => void\n /** \\<SliderThumb /> | \\<SliderTrack /> */\n children?: ReactElement | ReactElement[]\n // ReactElement<typeof SliderThumb, typeof SliderTrack>[]\n}\n\n/**\n * @category Slider\n */\nexport interface SliderMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = SliderProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof SliderProps>\n\n/**\n * Customizable slider\n * @category Slider\n */\nexport const Slider = forwardRef<SliderMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n skew = 1,\n vertical = false,\n reverse = false,\n bodyNoSelect = true,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n disabled = false,\n readonly = false,\n onChange,\n onDragStart,\n onDragEnd,\n className,\n style,\n children,\n onFocus,\n onBlur,\n onPointerDown,\n onKeyDown,\n ...props\n }: Props,\n ref,\n ) => {\n // -- state and ref ---\n const trackElementRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<SliderThumbMethods>(null)\n\n // --- interpret props ---\n const p = toFixed(normalizeValue(value, min, max, skew) * 100)\n const rev = toFixed(100 - p)\n // NOTE\n // normal -> normal (right)\n // vertical -> rev (up)\n // reverse -> rev (left)\n // vertical & reverse -> normal (down)\n const displayReversed = useMemo(\n () => xor(vertical, reverse),\n [vertical, reverse],\n )\n const percent = displayReversed ? rev : p\n\n let trackProps: SliderTrackProps = {}\n let thumbProps: SliderThumbProps = {}\n let scaleComponent: ReactElement | undefined = undefined\n if (children != undefined) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) {\n if (child.type == SliderThumb) {\n thumbProps = child.props as SliderThumbProps\n } else if (child.type == SliderTrack) {\n trackProps = child.props as SliderTrackProps\n } else if (child.type == Scale) {\n scaleComponent = child\n } else {\n throw new Error('only <SliderThumb> or <SliderTrack>')\n }\n } else {\n throw new Error('children is an invalid element.')\n }\n })\n }\n\n // --- internal functions ---\n const onDrag = useCallback(\n (nx: number, ny: number) => {\n if (!onChange || readonly) return\n const n = vertical ? ny : nx\n const v = rawValue(displayReversed ? 1 - n : n, min, max, skew)\n const v2 = clamp(stepValue(v, step), min, max)\n onChange(v2)\n },\n [displayReversed, max, min, onChange, readonly, skew, step, vertical],\n )\n\n const updateValueByEvent = useCallback(\n (eventType: InputEventOption[0], x: number) => {\n let newValue\n if (eventType == 'normalized') {\n const n = normalizeValue(value, min, max, skew)\n newValue = rawValue(n + x, min, max, skew)\n } else {\n newValue = value + x\n }\n return clamp(stepValue(newValue, step), min, max)\n },\n [max, min, skew, step, value],\n )\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!keyboard || !onChange || readonly) return\n const key = event.key\n if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {\n event.preventDefault()\n let x =\n key == 'ArrowRight' || key == 'ArrowUp' ? keyboard[1] : -keyboard[1]\n if (reverse) x *= -1\n onChange(updateValueByEvent(keyboard[0], x))\n }\n },\n [keyboard, onChange, readonly, reverse, updateValueByEvent],\n )\n\n // --- hooks ---\n const [touchMoveRefCallback, pointerDownHandler] =\n useDragWithElement<HTMLDivElement>({\n baseElementRef: trackElementRef,\n onDrag: onDrag,\n onDragStart: (nx, ny) => {\n if (readonly) return\n if (bodyNoSelect) addNoSelect()\n thumbRef.current?.focus()\n onDragStart?.(\n clamp(\n stepValue(rawValue(vertical ? ny : nx, min, max, skew), step),\n min,\n max,\n ),\n )\n },\n onDragEnd: (nx, ny) => {\n if (readonly) return\n if (bodyNoSelect) removeNoSelect()\n onDragEnd?.(\n clamp(\n stepValue(rawValue(vertical ? ny : nx, min, max, skew), step),\n min,\n max,\n ),\n )\n },\n })\n\n const wheelRefCallback = useRefCallbackEvent(\n 'wheel',\n (event) => {\n if (!wheel || !onChange || readonly) return\n event.preventDefault()\n let x\n if (!vertical && event.deltaX != 0) {\n x = event.deltaX > 0 ? wheel[1] : -wheel[1]\n } else {\n if (event.deltaY == 0) return\n x = event.deltaY > 0 ? -wheel[1] : wheel[1]\n }\n if (vertical && reverse) x *= -1\n onChange(updateValueByEvent(wheel[0], x))\n },\n {\n passive: false,\n },\n [wheel, vertical, readonly, onChange, updateValueByEvent],\n )\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n thumbRef.current?.focus()\n },\n blur() {\n thumbRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <SliderProvider\n min={min}\n max={max}\n step={step}\n skew={skew}\n vertical={vertical}\n reverse={reverse}\n disabled={disabled}\n readonly={readonly}\n >\n <div\n className={clsx('tremolo-slider', className)}\n ref={(div) => {\n wheelRefCallback(div)\n touchMoveRefCallback(div)\n }}\n tabIndex={-1}\n role=\"slider\"\n aria-valuenow={value}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-orientation={vertical ? 'vertical' : 'horizontal'}\n aria-disabled={disabled}\n aria-readonly={readonly}\n style={{\n margin: `calc(${styleHelper(thumbProps?.size ?? 22)} / 2)`, // half thumb size\n ...style,\n }}\n onPointerDown={(event) => {\n pointerDownHandler(event)\n onPointerDown?.(event)\n }}\n onKeyDown={(event) => {\n handleKeyDown(event)\n onKeyDown?.(event)\n }}\n onFocus={(event) => {\n thumbRef.current?.focus()\n onFocus?.(event)\n }}\n onBlur={(event) => {\n thumbRef.current?.blur()\n onBlur?.(event)\n }}\n {...props}\n >\n <div\n style={{\n display: 'flex',\n flexDirection: vertical ? 'row' : 'column',\n width: !vertical ? '100%' : undefined,\n height: vertical ? '100%' : undefined,\n }}\n >\n <div className=\"tremolo-slider-track-wrapper\" ref={trackElementRef}>\n <SliderTrack\n __percent={percent}\n __thumb={\n <SliderThumb\n ref={thumbRef}\n __percent={percent}\n {...thumbProps}\n />\n }\n {...trackProps}\n />\n </div>\n {scaleComponent}\n </div>\n </div>\n </SliderProvider>\n )\n },\n)\n\nexport { useSliderContext } from './context'\nexport {\n SliderThumb,\n type SliderThumbMethods,\n type SliderThumbProps,\n} from './Thumb'\nexport { SliderTrack, type SliderTrackProps } from './Track'\nexport { Scale, type ScaleProps } from './Scale'\nexport { ScaleOption, type ScaleOptionProps } from './ScaleOption'\n","import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react'\n\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\n\n/**\n * @example\n * <WheelObserver\n * onWheel={(event) => {\n * event.preventDefault()\n * console.log(event.deltaY)\n * }\n * >\n * <div>Wheel here</div>\n * </WheelObserver>\n */\n\n/** @category WheelObserver */\nexport interface WheelObserverProps<T extends ElementType> {\n /**\n * React.ElementType\n * @default div\n */\n as?: T\n\n children?: ReactNode\n onWheel?: (event: WheelEvent) => void\n}\n\n/** @category WheelObserver */\nexport function WheelObserver<T extends ElementType = 'div'>(\n props: WheelObserverProps<T> &\n Omit<ComponentPropsWithoutRef<T>, keyof WheelObserverProps<T>>,\n) {\n const { children, onWheel, as: Component = 'div', ...attributes } = props\n\n const wheelRefCallback = useRefCallbackEvent(\n 'wheel',\n (event) => {\n if (onWheel) onWheel(event)\n },\n { passive: false },\n [onWheel],\n )\n\n return (\n <Component ref={wheelRefCallback} {...attributes}>\n {children}\n </Component>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactElement } from 'react'\n\n/** @category XYPad */\nexport interface AreaProps {\n width?: number | string\n height?: number | string\n color?: string\n className?: string\n style?: CSSProperties\n children?: ReactElement\n\n /** inherit */\n __thumb?: ReactElement\n}\n\n/** @category XYPad */\nexport function XYPadArea({\n width = 120,\n height = 120,\n color,\n children,\n className,\n style,\n __thumb,\n ...props\n}: AreaProps & Omit<ComponentPropsWithoutRef<'div'>, keyof AreaProps>) {\n return (\n <div\n className={clsx('tremolo-xy-pad-area', className)}\n style={{\n ...{ '--color': color },\n width: width,\n height: height,\n ...style,\n }}\n {...props}\n >\n {children}\n {__thumb}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n CSSProperties,\n forwardRef,\n ReactNode,\n useImperativeHandle,\n useRef,\n} from 'react'\n\n/** @category XYPad */\nexport interface ThumbProps {\n size?: number | string\n width?: number | string\n height?: number | string\n\n color?: string\n\n wrapperClassName?: string\n wrapperStyle?: CSSProperties\n\n children?: ReactNode\n\n /** @internal */\n __disabled?: boolean\n /** @internal */\n __css?: CSSProperties\n}\n\n/** @category XYPad */\nexport interface XYPadThumbMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = ThumbProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof ThumbProps>\n\n/** @category XYPad */\nexport const XYPadThumb = forwardRef<XYPadThumbMethods, Props>(\n (\n {\n size,\n width = 22,\n height = 22,\n color,\n children,\n wrapperClassName,\n wrapperStyle,\n className,\n style,\n __disabled,\n __css,\n ...props\n }: Props,\n ref,\n ) => {\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n wrapperRef.current?.focus()\n },\n blur() {\n wrapperRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <div\n className={clsx('tremolo-xy-pad-thumb-wrapper', wrapperClassName)}\n style={{\n ...__css,\n ...wrapperStyle,\n }}\n {...props}\n >\n {children ? (\n children\n ) : (\n // default thumb\n <div\n ref={wrapperRef}\n className={clsx('tremolo-xy-pad-thumb', className)}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n aria-disabled={__disabled}\n style={{\n ...{ '--color': color },\n width: size ?? width,\n height: size ?? height,\n ...style,\n }}\n ></div>\n )}\n </div>\n )\n },\n)\n","import clsx from 'clsx'\nimport React, {\n ComponentPropsWithoutRef,\n forwardRef,\n ReactElement,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react'\n\nimport {\n clamp,\n normalizeValue,\n rawValue,\n stepValue,\n toFixed,\n InputEventOption,\n styleHelper,\n} from '@tremolo-ui/functions'\n\nimport { useDragWithElement } from '../../hooks/useDragWithElement'\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\nimport { addNoSelect, removeNoSelect } from '../_util'\n\nimport { XYPadArea, AreaProps } from './Area'\nimport { XYPadThumb, XYPadThumbMethods, ThumbProps } from './Thumb'\n\n/**\n * Two-dimensional slider component.\n * @category XYPad\n */\nexport interface ValueOptions {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n skew?: number\n reverse?: boolean\n /**\n * wheel control option\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n */\n keyboard?: InputEventOption | null\n}\n\n/** @category XYPad */\nexport interface XYPadProps {\n x: ValueOptions\n y: ValueOptions\n\n bodyNoSelect?: boolean\n disabled?: boolean\n readonly?: boolean\n onChange?: (valueX: number, valueY: number) => void\n onDragStart?: (valueX: number, valueY: number) => void\n onDragEnd?: (valueX: number, valueY: number) => void\n /** \\<XYPadThumb /> | \\<XYPadArea /> */\n children?: ReactElement | ReactElement[]\n}\n\n/** @category XYPad */\nexport interface XYPadMethods {\n focus: () => void\n blur: () => void\n}\n\nconst defaultValueOptions = {\n skew: 1,\n step: 1,\n reverse: false,\n wheel: ['raw', 1] as InputEventOption,\n keyboard: ['raw', 1] as InputEventOption,\n}\n\ntype Props = XYPadProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadProps>\n\n/**\n * Simple XYPad\n * @category XYPad\n */\nexport const XYPad = forwardRef<XYPadMethods, Props>(\n (\n {\n x: _x,\n y: _y,\n className,\n style,\n bodyNoSelect = true,\n disabled = false,\n readonly = false,\n onChange,\n onDragStart,\n onDragEnd,\n onPointerDown,\n onKeyDown,\n onFocus,\n onBlur,\n children,\n ...props\n }: Props,\n ref,\n ) => {\n const x = useMemo(() => {\n return { ...defaultValueOptions, ..._x }\n }, [_x])\n const y = useMemo(() => {\n return { ...defaultValueOptions, ..._y }\n }, [_y])\n\n // -- state and ref ---\n const areaElementRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<XYPadThumbMethods>(null)\n\n // --- interpret props ---\n const nx = normalizeValue(x.value, x.min, x.max, x.skew)\n const ny = normalizeValue(y.value, y.min, y.max, y.skew)\n const percentX = toFixed((x.reverse ? 1 - nx : nx) * 100)\n const percentY = toFixed((y.reverse ? 1 - ny : ny) * 100)\n\n let areaProps: AreaProps = {}\n let thumbProps: ThumbProps = {}\n if (children != undefined) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) {\n if (child.type == XYPadThumb) {\n thumbProps = child.props as ThumbProps\n } else if (child.type == XYPadArea) {\n areaProps = child.props as AreaProps\n } else {\n throw new Error('only <XYPadThumb> or <XYPadArea>')\n }\n } else {\n throw new Error('children is an invalid element.')\n }\n })\n }\n\n // --- internal functions ---\n const onDrag = useCallback(\n (nx: number, ny: number) => {\n if (!onChange || readonly) return\n const vx = rawValue(x.reverse ? 1 - nx : nx, x.min, x.max, x.skew)\n const vy = rawValue(y.reverse ? 1 - ny : ny, y.min, y.max, y.skew)\n const newX = clamp(stepValue(vx, x.step), x.min, x.max)\n const newY = clamp(stepValue(vy, y.step), y.min, y.max)\n onChange(newX, newY)\n },\n [\n onChange,\n readonly,\n x.max,\n x.min,\n x.reverse,\n x.skew,\n x.step,\n y.max,\n y.min,\n y.reverse,\n y.skew,\n y.step,\n ],\n )\n\n const updateValueByEvent = useCallback(\n (\n eventType: InputEventOption[0],\n target: Required<ValueOptions>,\n x: number,\n ) => {\n let v\n if (eventType == 'normalized') {\n const n = normalizeValue(\n target.value,\n target.min,\n target.max,\n target.skew,\n )\n v = rawValue(n + x, target.min, target.max, target.skew)\n } else {\n v = target.value + x\n }\n return clamp(stepValue(v, target.step), target.min, target.max)\n },\n [],\n )\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onChange || readonly) return\n const key = event.key\n if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {\n const isHorizontal = key == 'ArrowRight' || key == 'ArrowLeft'\n const target = isHorizontal ? x : y\n if (!target.keyboard) return\n event.preventDefault()\n let delta = target.keyboard[1]\n if (key == 'ArrowLeft' || key == 'ArrowUp') delta *= -1\n if (target.reverse) delta *= -1\n const newValue = updateValueByEvent(target.keyboard[0], target, delta)\n if (isHorizontal) {\n onChange(newValue, y.value)\n } else {\n onChange(x.value, newValue)\n }\n }\n },\n [onChange, readonly, x, y, updateValueByEvent],\n )\n\n // --- hooks ---\n const [touchMoveRefCallback, pointerDownHandler] =\n useDragWithElement<HTMLDivElement>({\n baseElementRef: areaElementRef,\n onDrag: onDrag,\n onDragStart: (nx, ny) => {\n if (readonly) return\n if (bodyNoSelect) addNoSelect()\n thumbRef.current?.focus()\n const valueX = clamp(\n stepValue(rawValue(nx, x.min, x.max, x.skew), x.step),\n x.min,\n x.max,\n )\n const valueY = clamp(\n stepValue(rawValue(ny, y.min, y.max, y.skew), y.step),\n y.min,\n y.max,\n )\n onDragStart?.(valueX, valueY)\n },\n onDragEnd: (nx, ny) => {\n if (readonly) return\n if (bodyNoSelect) removeNoSelect()\n const valueX = clamp(\n stepValue(rawValue(nx, x.min, x.max, x.skew), x.step),\n x.min,\n x.max,\n )\n const valueY = clamp(\n stepValue(rawValue(ny, y.min, y.max, y.skew), y.step),\n y.min,\n y.max,\n )\n onDragEnd?.(valueX, valueY)\n },\n })\n\n const wheelRefCallback = useRefCallbackEvent(\n 'wheel',\n (event) => {\n if (!onChange || readonly) return\n const target = event.shiftKey ? x : y\n if (!target.wheel) return\n event.preventDefault()\n let delta = target.wheel[1]\n if (event.deltaY < 0) delta *= -1\n if (target.reverse) delta *= -1\n const newValue = updateValueByEvent(target.wheel[0], target, delta)\n if (event.shiftKey) {\n onChange(newValue, y.value)\n } else {\n onChange(x.value, newValue)\n }\n },\n {\n passive: false,\n },\n [x, y, onChange, readonly, updateValueByEvent],\n )\n\n useImperativeHandle(ref, () => {\n return {\n focus() {\n thumbRef.current?.focus()\n },\n blur() {\n thumbRef.current?.blur()\n },\n }\n }, [])\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n className={clsx('tremolo-xy-pad', className)}\n ref={(div) => {\n wheelRefCallback(div)\n touchMoveRefCallback(div)\n }}\n tabIndex={-1}\n aria-disabled={disabled}\n aria-readonly={readonly}\n style={{\n margin: `calc(${styleHelper(thumbProps?.size ?? 22)} / 2)`, // half thumb size\n cursor: readonly ? 'not-allowed' : 'pointer',\n WebkitTapHighlightColor: 'transparent',\n ...style,\n }}\n onPointerDown={(event) => {\n pointerDownHandler(event)\n onPointerDown?.(event)\n }}\n onKeyDown={(event) => {\n handleKeyDown(event)\n onKeyDown?.(event)\n }}\n onFocus={(event) => {\n thumbRef.current?.focus()\n onFocus?.(event)\n }}\n onBlur={(event) => {\n thumbRef.current?.blur()\n onBlur?.(event)\n }}\n {...props}\n >\n <div className=\"tremolo-xy-pad-area-wrapper\" ref={areaElementRef}>\n <XYPadArea\n __thumb={\n <XYPadThumb\n ref={thumbRef}\n __disabled={disabled}\n __css={{\n top: `${percentY}%`,\n left: `${percentX}%`,\n }}\n {...thumbProps}\n />\n }\n {...areaProps}\n />\n </div>\n </div>\n )\n },\n)\n\nexport * from './Thumb'\nexport * from './Area'\n","import { DependencyList, useCallback, useEffect, useRef } from 'react'\n\nexport function useAnimationFrame(\n callback = () => {},\n deps: DependencyList = [],\n) {\n const reqIdRef = useRef(-1)\n const loop = useCallback(() => {\n reqIdRef.current = requestAnimationFrame(loop)\n callback()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [callback, ...deps])\n\n useEffect(() => {\n reqIdRef.current = requestAnimationFrame(loop)\n return () => cancelAnimationFrame(reqIdRef.current)\n }, [loop])\n}\n"],"mappings":";;;;;;;;;AACA,MAAa,eAAe;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD;;;;ACDD,SAAS,aACPA,QACAC,SACAC,OACAC,QACAC,KACA;AACA,QAAO,QAAQ,QAAQ;AACvB,QAAO,SAAS,SAAS;AAEzB,SAAQ,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AACtC,SAAQ,MAAM,KAAK,IAAI;AACvB,QAAO,MAAM,SAAS,EAAE,MAAM;AAC9B,QAAO,MAAM,UAAU,EAAE,OAAO;AACjC;AA2ED,SAAgB,gBAAgB,EAE9B,SACA,MACA,MAEA,QAAQ,KACR,SAAS,KAET,cACA,mBAAmB,MAEnB,WACA,gBAAgB,CAAC,UAAU,MAAM,gBAAgB,CACjD,GAAG,OAKF,EAAgB;CACjB,MAAM,YAAY,OAA0B,KAAK;CACjD,MAAM,gBAAgB,OAA0B,KAAK;CACrD,MAAM,WAAW,OAAO,GAAG;CAC3B,MAAM,WAAW,OAAO,EAAE;CAC1B,MAAM,YAAY,OAAO,EAAE;CAC3B,MAAM,eAAe,OAAO,GAAG;CAC/B,MAAM,eAAe,OAAO,GAAG;CAE/B,MAAM,OAAO,YACX,CACEH,SACAI,SACAC,UACAC,UACG;EACH,MAAM,MAAM,YAAY,KAAK;EAC7B,MAAM,YAAY,MAAM,aAAa;EACrC,MAAM,cAAc,MAAM,aAAa;AACvC,eAAa,UAAU;AACvB,WAAS,UAAU,sBAAsB,MACvC,KAAK,SAASC,SAAOC,UAAQ,QAAQ,EAAE,CACxC;AACD,OAAK,SAAS;GACZ,OAAOD,QAAM;GACb,QAAQC,SAAO;GACf,OAAO,QAAQ;GACf;GACA;GACA,KAAK,MAAO;EACb,EAAC;CACH,GACD,CAAC,IAAK,EACP;AAED,WAAU,MAAM;AACd,OAAK,UAAU,QAAS;EACxB,MAAM,SAAS,UAAU;EACzB,MAAM,UAAU,OAAO,WAAW,MAAM,QAAQ;AAChD,OAAK,QAAS,OAAM,IAAI,MAAM;EAC9B,MAAM,MAAM,WAAW;AAEvB,MAAI,cAAc;GAChB,MAAM,SAAS,OAAO;AACtB,QAAK,OAAQ,OAAM,IAAI,MAAM;GAC7B,MAAM,aAAa,cAAc;GACjC,MAAM,cAAc,YAAY,WAAW,MAAM,QAAQ;GAEzD,MAAM,KAAK,IAAI,eAAe,CAAC,YAAY;AACzC,SAAK,MAAM,SAAS,SAAS;KAE3B,MAAM,cAAc,CAAE;AACtB,UAAK,MAAM,QAAQ,aAChB,CAAC,YAAY,QAA8B,QAAQ;KAGtD,MAAMC,MAAI,MAAM,YAAY;KAC5B,MAAMC,MAAI,MAAM,YAAY;AAE5B,SAAI,oBAAoB,cAAc,aAAa;AACjD,iBAAW,QAAQD,MAAI;AACvB,iBAAW,SAASC,MAAI;AACxB,kBAAY,MAAM,IAAI,KAAK,IAAI,IAAI;AACnC,UAAI,OAAO,QAAQ,KAAK,OAAO,SAAS,EACtC,aAAY,UAAU,QAAQ,GAAG,EAAE;KAEtC;AAED,kBAAa,QAAQ,SAASD,KAAGC,KAAG,IAAI;AACxC,cAAS,UAAUD;AACnB,eAAU,UAAUC;AAEpB,UAAK,MAAM,QAAQ,aAChB,CAAC,QAAQ,QAA8B,YAAY;AAGtD,SACE,oBACA,eACA,cACA,WAAW,QAAQ,KACnB,WAAW,SAAS,EAEpB,SAAQ,UAAU,YAAY,QAAQ,GAAG,EAAE;IAE9C;GACF;AACD,MAAG,QAAQ,OAAO;GAElB,MAAM,IAAI,OAAO;GACjB,MAAM,IAAI,OAAO;AACjB,gBAAa,QAAQ,SAAS,GAAG,GAAG,IAAI;AAExC,OAAI,KACF,MAAK,SAAS;IAAE,OAAO,SAAS;IAAS,QAAQ,UAAU;GAAS,EAAC;GACvE,MAAM,MAAM,YAAY,KAAK;AAC7B,gBAAa,UAAU;AACvB,gBAAa,UAAU;AACvB,QAAK,SAAS,UAAU,WAAW,GAAG;AAEtC,UAAO,MAAM;AACX,QAAI,SAAS,QAAS,sBAAqB,SAAS,QAAQ;AAC5D,OAAG,YAAY;GAChB;EACF,OAAM;GACL,MAAM,OAAO,OAAO,uBAAuB;AAC3C,gBAAa,QAAQ,SAAS,KAAK,OAAO,KAAK,QAAQ,IAAI;AAC3D,YAAS,UAAU,KAAK;AACxB,aAAU,UAAU,KAAK;AAEzB,OAAI,KACF,MAAK,SAAS;IAAE,OAAO,SAAS;IAAS,QAAQ,UAAU;GAAS,EAAC;GACvE,MAAM,MAAM,YAAY,KAAK;AAC7B,gBAAa,UAAU;AACvB,gBAAa,UAAU;AACvB,QAAK,SAAS,UAAU,WAAW,GAAG;AAEtC,UAAO,MAAM;AACX,QAAI,SAAS,QAAS,sBAAqB,SAAS,QAAQ;GAC7D;EACF;CACF,GAAE;EAAC;EAAM;EAAM;EAAS;EAAkB;CAAa,EAAC;AAEzD,wBACE,4CACE,IAAC;EACC,WAAW,KAAK,4BAA4B,UAAU;EACtD,OAAO,eAAe,IAAI;EAC1B,QAAQ,eAAe,IAAI;EAC3B,KAAK;EACU;EACf,GAAI;GACI,EACT,gBAAgB,oCACf,IAAC;EAAO,OAAO,EAAE,SAAS,OAAQ;EAAE,KAAK;GAAwB,IAElE;AAEN;;;;;;;;ACnQD,SAAgB,eACdC,UACAC,OAA6B,CAAE,GAC/B;CACA,MAAM,cAAc,OAAwB,MAAM;AAChD,QAAM,IAAI,MAAM;CACjB,EAAC;AAEF,oBAAmB,MAAM;AACvB,cAAY,UAAU;CACvB,EAAC;AAGF,QAAO,YAAY,CAAC,GAAG,SAAe,YAAY,UAAU,GAAG,KAAK,EAAE,KAAK;AAC5E;;;;ACKD,SAAgB,iBACdC,QACAC,OACAC,SACAC,SACA;CACA,MAAM,WAAW,eAAe,QAAQ;AAExC,WAAU,MAAM;EACd,MAAM,cAAc,WAAW,aAAa,QAAQ,GAAI,UAAU;AAElE,OAAK,YAAY,KAAM;AAEvB,OAAK,iBAAiB,OAAO,UAAU,QAAQ;AAC/C,SAAO,MAAM;AACX,QAAK,oBAAoB,OAAO,UAAU,QAAQ;EACnD;CACF,GAAE;EAAC;EAAO;EAAQ;EAAS;EAAU;CAAQ,EAAC;AAE/C,QAAO,MAAM;EACX,MAAM,cAAc,WAAW,aAAa,QAAQ,GAAI,UAAU;AAClE,QAAM,oBAAoB,OAAO,UAAU,QAAQ;CACpD;AACF;;;;ACxCD,SAAgB,oBACdC,OACAC,SACAC,SACAC,OAA6B,CAAE,GACI;AACnC,QAAO,QAAQ,MAAM;EACnB,IAAIC;AACJ,SAAO,CAACC,SAA6B;AACnC,QAAK,MAAM;AACT,eAAW;AACX;GACD;AACD,QAAK,iBAAiB,OAAO,SAAS,QAAQ;AAE9C,aAAU,MAAM;AACd,SAAK,oBAAoB,OAAO,SAAS,QAAQ;GAClD;EACF;CAEF,GAAE,KAAK;AACT;;;;;;;ACbD,SAAgB,QAA2B,EACzC,YAAY,GACZ,QACA,aACA,WACa,EAGb;CACA,MAAM,cAAc,cAAqC;CACzD,MAAM,cAAc,cAAqC;CACzD,MAAM,aAAa,OAAO,EAAE;CAC5B,MAAM,aAAa,OAAO,EAAE;CAE5B,MAAM,aAAa,YACjB,CACEC,OACA,QAAQ,UACL;EACH,MAAM,UAAU,iBAAiB;AACjC,MAAI,WAAW,MAAM,WAAY,OAAM,gBAAgB;EACvD,MAAM,UAAU,UAAU,MAAM,QAAQ,GAAG,UAAU,MAAM;EAC3D,MAAM,UAAU,UAAU,MAAM,QAAQ,GAAG,UAAU,MAAM;EAC3D,IAAI,SAAS;EACb,IAAI,SAAS;AACb,MAAI,OAAO;AACT,cAAW,UAAU;AACrB,cAAW,UAAU;EACtB;AACD,MAAI,YAAY,SAAS;AACvB,YAAS,UAAU,YAAY;AAC/B,eAAY,UAAU;EACvB;AACD,MAAI,YAAY,SAAS;AACvB,YAAS,UAAU,YAAY;AAC/B,eAAY,UAAU;EACvB;AACD,MAAI,KAAK,IAAI,OAAO,GAAG,aAAa,KAAK,IAAI,OAAO,GAAG,UAAW;AAClE,SACE,UAAU,WAAW,SACrB,UAAU,WAAW,SACrB,QACA,OACD;CACF,GACD,CAAC,WAAW,MAAO,EACpB;CAED,MAAM,aAAa,oBACjB,aACA,YACA,EAAE,SAAS,MAAO,GAClB,CAAC,MAAO,EACT;CAED,MAAM,qBAAqB,YACzB,CAACC,UAAiC;AAChC,cAAY,UAAU,MAAM;AAC5B,cAAY,UAAU,MAAM;AAC5B,aAAW,OAAO,KAAK;AACvB,iBAAe;CAChB,GACD,CAAC,YAAY,WAAY,EAC1B;AAED,kBAAiB,WAAW,QAAQ,aAAa,WAAW;AAE5D,kBAAiB,WAAW,QAAQ,aAAa,MAAM;AACrD,cAAY;AACZ,cAAY;AACZ,eAAa;CACd,EAAC;AAEF,QAAO,CAAC,YAAY,kBAAmB;AACxC;;;;AC1FD,SAAgB,cAAc;AAC5B,UAAS,KAAK,UAAU,IAAI,oBAAoB;AACjD;AAED,SAAgB,iBAAiB;AAC/B,UAAS,KAAK,UAAU,OAAO,oBAAoB;AACpD;;;;;;;;ACyFD,MAAa,gBAAgB,WAC3B,CACE,EACE,OACA,KACA,KACA,eAAe,KACf,aAAa,KACb,OAAO,GACP,OAAO,GACP,MACA,QAAQ,IACR,SAAS,IACT,cAAc,WACd,gBAAgB,QAChB,KAAK,QACL,QAAQ,WACR,aAAa,GACb,cAAc,GACd,MACA,eAAe,MACf,QAAQ,CAAC,OAAO,CAAE,GAClB,WAAW,CAAC,OAAO,CAAE,GACrB,2BAA2B,MAC3B,OACA,WACA,SACA,GAAG,OACG,EACR,QACG;CAEH,MAAM,WAAW,OAAO,EAAE;CAC1B,MAAM,SAAS,OAAuB,KAAK;CAG3C,MAAM,yBACI,QAAQ,UAAU,mBAAmB,UAAU;CAEzD,MAAM,SAAS,YACb,CAACC,IAAYC,MAAc;AACzB,OAAK,SAAU;EACf,MAAM,IAAI,SAAS,SAAS,UAAU,IAAI,KAAK,KAAK,KAAK,KAAK;EAC9D,MAAM,KAAK,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK,IAAI;AAC9C,WAAS,GAAG;CACb,GACD;EAAC;EAAK;EAAK;EAAU;EAAM;CAAK,EACjC;CAED,MAAM,gBAAgB,YACpB,CAACC,UAA+C;AAC9C,OAAK,aAAa,SAAU;EAC5B,MAAM,MAAM,MAAM;AAClB,MAAI;GAAC;GAAc;GAAa;GAAW;EAAY,EAAC,SAAS,IAAI,EAAE;AACrE,SAAM,gBAAgB;GACtB,MAAM,IACJ,OAAO,gBAAgB,OAAO,YAAY,SAAS,MAAM,SAAS;GACpE,IAAI;AACJ,OAAI,SAAS,MAAM,cAAc;IAC/B,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,KAAK;AAC/C,QAAI,SAAS,IAAI,GAAG,KAAK,KAAK,KAAK;GACpC,MACC,KAAI,QAAQ;AAEd,YAAS,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC;EAC9C;CACF,GACD;EAAC;EAAO;EAAK;EAAK;EAAM;EAAM;EAAU;CAAS,EAClD;CAGD,MAAM,CAAC,sBAAsB,mBAAmB,GAAG,QAAwB;EACjE;EACR,aAAa,MAAM;AACjB,YAAS,UAAU,eAAe,OAAO,KAAK,KAAK,KAAK;AACxD,OAAI,aAAc,cAAa;EAChC;EACD,WAAW,MAAM;AACf,OAAI,aAAc,iBAAgB;EACnC;CACF,EAAC;CAEF,MAAM,mBAAmB,oBACvB,SACA,CAAC,UAAU;AACT,OAAK,MAAO;AACZ,QAAM,gBAAgB;EACtB,MAAM,IAAI,MAAM,SAAS,KAAK,MAAM,KAAK,MAAM;EAC/C,IAAI;AACJ,MAAI,MAAM,MAAM,cAAc;GAC5B,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,KAAK;AAC/C,OAAI,SAAS,IAAI,GAAG,KAAK,KAAK,KAAK;EACpC,MACC,KAAI,QAAQ;AAEd,MAAI,SAAU,UAAS,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC;CAC5D,GACD,EAAE,SAAS,MAAO,GAClB;EAAC;EAAO;EAAO;EAAK;EAAK;EAAM;EAAM;CAAS,EAC/C;AAED,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,WAAO,SAAS,OAAO;GACxB;GACD,OAAO;AACL,WAAO,SAAS,MAAM;GACvB;EACF;CACF,GAAE,CAAE,EAAC;AAEN,wBACE,IAAC;EACC,WAAW,KAAK,0BAA0B,UAAU;EACpD,KAAK,CAAC,QAAQ;AACZ,UAAO,UAAU;AACjB,oBAAiB,IAAI;AACrB,wBAAqB,IAAI;EAC1B;EACD,MAAK;EACL,UAAU;EACV,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,OAAO;GACL,SAAS;GACT,OAAO,QAAQ;GACf,QAAQ,QAAQ;GAChB,QAAQ;GACR,yBAAyB;GACzB,GAAG;EACJ;EACD,eAAe;EACf,eAAe,MAAM;AACnB,OAAI,4BAA4B,SAC9B,UAAS,aAAa;EAEzB;EACD,WAAW;EACX,GAAI;4BAEJ,IAAC;GACC,GAAK,iBACD,EAAE,cAAc,KAAM,IACtB;IACE,OAAO,QAAQ;IACf,QAAQ,QAAQ;GACjB;GACL,MACE,OACI,OACA,CAAC,KAAK,EAAE,gBAAO,kBAAQ,KAAK;IAC1B,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,KAAK;IAC/C,MAAM,SAAS,eAAe,YAAY,KAAK,KAAK,KAAK;IACzD,MAAM,KAAKC,UAAQ;IACnB,MAAM,KAAKC,WAAS;IACpB,MAAM,IAAI,KAAK,IAAI,IAAI,GAAG;AAC1B,QAAI,KAAK,EAAG;AAGZ,QAAI,UAAU,GAAG,GAAGD,SAAOC,SAAO;AAClC,QAAI,UAAU;AAGd,QAAI,WAAW;AACf,QAAI,YAAY;AAChB,QAAI,IAAI,IAAI,IAAI,IAAI,IAAK,GAAG,IAAI,KAAK,GAAG;AACxC,QAAI,MAAM;AAEV,QAAI,YAAY;AAGhB,QAAI,WAAW;AACf,QAAI,cAAc;AAClB,QAAI,IACF,IACA,IACA,IAAI,KAAM,aAAa,GACvB,OAAO,IAAI,EACX,OAAO,GAAG,CACX;AACD,QAAI,QAAQ;AAGZ,QAAI,WAAW;AACf,QAAI,cAAc;AAClB,QAAI,IACF,IACA,IACA,IAAI,KAAM,aAAa,GACvB,OAAO,MAAM,MAAM,OAAO,EAC1B,OAAO,MAAM,MAAM,EAAE,EACrB,IAAI,OACL;AACD,QAAI,QAAQ;AAGZ,QAAI,UAAU;AACd,QAAI,WAAW;AACf,QAAI,OAAO,IAAI,GAAG;AAClB,QAAI,OACF,KACE,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,CAAC,IAC5B,IAAI,KAAM,cAAc,IAC7B,KACE,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,CAAC,IAC5B,IAAI,KAAM,cAAc,GAC9B;AACD,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,QAAQ;GACb;IAEP;GACE;AAET,EACF;;;;;AChSD,SAAgB,aACdC,OAEA;CACA,MAAM,EACJ,IAAI,YAAY,OAChB,YAAY,GACZ,UACA,QACA,aACA,UACA,GAAG,YACJ,GAAG;CAEJ,MAAM,CAAC,aAAa,mBAAmB,GAAG,QAAQ;EACrC;EACH;EACK;EACF;CACZ,EAAC;AAEF,wBACE,IAAC;EACC,KAAK;EACL,eAAe;EACf,GAAI;EAEH;GACS;AAEf;;;;;;;;;ACmDD,MAAa,OAAO,WAClB,CACE,EACE,OACA,KACA,KACA,OAAO,GACP,OAAO,GACP,eAAe,KACf,aAAa,KACb,OAAO,IACP,eAAe,MACf,QAAQ,CAAC,OAAO,CAAE,GAClB,WAAW,CAAC,OAAO,CAAE,GACrB,2BAA2B,MAC3B,WAAW,OACX,WAAW,OACX,YACA,cACA,OACA,WACA,UACA,WACA,eACA,eACA,WACA,QACA,GAAG,OACG,EACR,QACG;CACH,MAAM,WAAW,OAAO,EAAE;CAC1B,MAAM,SAAS,OAAyB,KAAK;CAG7C,MAAM,UAAU;CAChB,MAAM,kBAAkB;CACxB,MAAM,kBAAkB;CACxB,MAAM,aAAa,OAAO;CAC1B,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,KAAK;CAC/C,MAAM,IAAI,eAAe,YAAY,KAAK,KAAK,KAAK;CAGpD,MAAM,SAAS,YACb,CAACC,IAAYC,MAAc;AACzB,OAAK,YAAY,SAAU;EAC3B,MAAM,IAAI,SAAS,SAAS,UAAU,IAAI,KAAK,KAAK,KAAK,KAAK;EAC9D,MAAM,KAAK,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK,IAAI;AAC9C,WAAS,GAAG;CACb,GACD;EAAC;EAAK;EAAK;EAAU;EAAU;EAAM;CAAK,EAC3C;CAED,MAAM,qBAAqB,YACzB,CAACC,WAAgCC,MAAc;EAC7C,IAAI;AACJ,MAAI,aAAa,cAAc;GAC7B,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,KAAK;AAC/C,cAAW,SAAS,IAAI,GAAG,KAAK,KAAK,KAAK;EAC3C,MACC,YAAW,QAAQ;AAErB,SAAO,MAAM,UAAU,UAAU,KAAK,EAAE,KAAK,IAAI;CAClD,GACD;EAAC;EAAK;EAAK;EAAM;EAAM;CAAM,EAC9B;CAED,MAAM,gBAAgB,YACpB,CAACC,UAAiD;AAChD,OAAK,aAAa,YAAY,SAAU;EACxC,MAAM,MAAM,MAAM;AAClB,MAAI;GAAC;GAAc;GAAa;GAAW;EAAY,EAAC,SAAS,IAAI,EAAE;AACrE,SAAM,gBAAgB;GACtB,MAAM,IACJ,OAAO,gBAAgB,OAAO,YAAY,SAAS,MAAM,SAAS;AACpE,YAAS,mBAAmB,SAAS,IAAI,EAAE,CAAC;EAC7C;CACF,GACD;EAAC;EAAU;EAAU;EAAU;CAAmB,EACnD;CAGD,MAAM,CAAC,sBAAsB,mBAAmB,GAAG,QAAoB;EAC7D;EACR,aAAa,MAAM;AACjB,YAAS,UAAU,eAAe,OAAO,KAAK,KAAK,KAAK;AACxD,OAAI,aAAc,cAAa;EAChC;EACD,WAAW,MAAM;AACf,OAAI,aAAc,iBAAgB;EACnC;CACF,EAAC;CAEF,MAAM,mBAAmB,oBACvB,SACA,CAAC,UAAU;AACT,OAAK,SAAS,SAAU;AACxB,QAAM,gBAAgB;AACtB,OAAK,YAAY,MAAM,UAAU,EAAG;EACpC,MAAM,IAAI,KAAK,KAAK,MAAM,OAAO,IAAI,MAAM;AAC3C,WAAS,mBAAmB,MAAM,IAAI,EAAE,CAAC;CAC1C,GACD,EAAE,SAAS,MAAO,GAClB;EAAC;EAAO;EAAU;EAAU;CAAmB,EAChD;AAED,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,WAAO,SAAS,OAAO;GACxB;GACD,OAAO;AACL,WAAO,SAAS,MAAM;GACvB;EACF;CACF,GAAE,CAAE,EAAC;CAEN,MAAM,SAAS,OAAO;CACtB,MAAM,KAAK;CACX,MAAM,KAAK,OAAO,KAAK,IAAI,GAAG,EAAE,GAAG;CACnC,MAAM,KAAK,OAAO,KAAK,IAAI,GAAG,EAAE,GAAG;CACnC,MAAM,KAAK;CACX,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;CACtD,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG,CAAC;AAEtD,wBACE,KAAC;EACC,WAAW,KAAK,gBAAgB,UAAU;EAC1C,KAAK,CAAC,QAAQ;AACZ,UAAO,UAAU;AACjB,oBAAiB,IAAI;AACrB,wBAAqB,IAAI;EAC1B;EACD,OAAO;EACP,QAAQ;EACR,UAAU;EACV,MAAK;EACL,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,eAAe,CAAC,UAAU;AACxB,sBAAmB,MAAM;AACzB,mBAAgB,MAAM;EACvB;EACD,eAAe,CAAC,UAAU;AACxB,OAAI,4BAA4B,SAC9B,UAAS,aAAa;AAExB,mBAAgB,MAAM;EACvB;EACD,WAAW,CAAC,UAAU;AACpB,iBAAc,MAAM;AACpB,eAAY,MAAM;EACnB;EACD,GAAI;;GAGH,aAAa,uBACZ,IAAC;IACC,WAAW,KACT,8BACA,SAAS,aACV;IACD,IAAI,IAAI,GAAG,GAAG,GAAG,KAAK,OAAO,GAAG,OAAO,QAAQ,KAAK,KAAK,MAAM,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG;IACpF,MAAK;IACL,QAAQ,gBAAgB;IACxB,aAAa;KACb;mBAEJ,IAAC;IACC,WAAW,KAAK,4BAA4B,SAAS,WAAW;IAChE,IAAI,IAAI,GAAG,GAAG,GAAG,KAAK,OAAO,GAAG,OAAO,QAAQ,KAAK,KAAK,MAAM,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG;IACpF,MAAK;IACL,QAAQ,cAAc;IACtB,aAAa;KACb;GACD,aAAa,uBACZ,IAAC;IACC,WAAW,KACT,8BACA,SAAS,aACV;IACD,IAAI,IAAI,GAAG,GAAG,GAAG,KAAK,OAAO,GAAG,OAAO,QAAQ,KAAK,KAAK,MAAM,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG;IACpF,MAAK;IACL,QAAQ,gBAAgB;IACxB,aAAa;KACb;mBAGJ,KAAC;IAAI,WAAW,KAAK,sBAAsB,SAAS,MAAM;+BACxD,IAAC;KACC,IAAG;KACH,IAAG;KACH,IAAI,EAAE,KAAK,QAAQ;KACnB,MAAM,SAAS;MACf,kBACF,IAAC;KACC,WAAW,KAAK,2BAA2B,SAAS,UAAU;KAC9D,IAAG;KACH,KAAK,EAAE,QAAQ;KACf,IAAG;KACH,KAAK,EAAE,gBAAgB;KACvB,QAAQ,aAAa;KACrB,cAAc,EAAE,gBAAgB;KAIhC,OAAO;MACL,YAAY,SAAS,OAAO,IAAI,IAAI;MACpC,iBAAiB;KAClB;MACD;KACE;;GACF;AAET,EACF;;;;AC5SD,SAAgB,UACdC,OACA,MAAM,OAAO,kBACb,MAAM,OAAO,kBACb;AACA,QAAO,MAAM,OAAO,KAAK,IAAI;AAC9B;AAED,MAAM,yBAAyB,CAACC,cAA8B;CAC5D,MAAMC,gBAAuB;EAC3B,OAAO;EACP,eAAe;EACf,KAAK;EACL,KAAK;EACL,MAAM;EACN,UAAU;EACV,iBAAiB;EACjB,UAAU,CAACC,IAAYC,OAAe,CAAE;CACzC;AAED,QAAO,aAA6B,CAAC,CAAC,SAAS;EAC7C,GAAG;EACH,GAAG;EAED,OAAO,WACL,OAAO,WAAW,SAAS,GAAG,EAC9B,WAAW,OACX,WAAW,MACZ,CAAC;EACF,eAAe,WACb,OAAO,WAAW,SAAS,GAAG,EAC9B,WAAW,OACX,WAAW,MACZ,CAAC;EAEJ,WAAW,MACT,IAAI,CAAC,UAAU;AACb,OAAI,MAAM,SAAU,QAAO,CAAE;GAC7B,MAAM,UAAU,WACd,MAAM,OACN,MAAM,OACN,MAAM,MACP,CAAC;GACF,IAAI,OAAO,WAAW,MAAM,QAAQ;AACpC,OAAI,MAAM,gBACR,QAAO,UAAU,MAAM,MAAM,KAAK,MAAM,IAAI;GAE9C,MAAM,IAAI,WAAW,OAAO,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,CAAC;AAC7D,UAAO,WAAW,MAAM,EAAE;AAC1B,UAAO;IACL,OAAO;IACP,eAAe;GAChB;EACF,EAAC;EACJ,WAAW,MACT,IAAI,CAAC,UAAU;AACb,OAAI,MAAM,SAAU,QAAO,CAAE;GAC7B,MAAM,UAAU,WACd,MAAM,OACN,MAAM,OACN,MAAM,MACP,CAAC;GACF,IAAI,OAAO,WAAW,MAAM,QAAQ;AACpC,OAAI,MAAM,gBACR,QAAO,UAAU,MAAM,MAAM,KAAK,MAAM,IAAI;GAE9C,MAAM,IAAI,WAAW,OAAO,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,CAAC;AAC7D,UAAO,WAAW,MAAM,EAAE;AAC1B,UAAO;IACL,OAAO;IACP,eAAe;GAChB;EACF,EAAC;EACJ,QAAQ,CAAC,UACP,IAAI,CAAC,UAAU;AACb,OAAI,MAAM,SAAU,QAAO,CAAE;GAC7B,MAAM,IAAI,SAAS;AACnB,UAAO;IACL,OAAO;IACP,eAAe,WAAW,GAAG,MAAM,OAAO,MAAM,MAAM,CAAC;GACxD;EACF,EAAC;CACL,GAAE;AACJ;AAED,MAAM,qBAAqB,cAAuC,KAAK;AAIvE,SAAgB,oBAAoB,EAClC,SACA,GAAG,OACsB,EAAE;CAC3B,MAAM,WAAW,OAAyB,KAAK;AAC/C,MAAK,SAAS,QACZ,UAAS,UAAU,uBAAuB,MAAM;AAGlD,WAAU,MAAM;AACd,MAAI,SAAS,SAAS;GACpB,MAAM,SAAS,WACb,OAAO,OAAO,SAAS,GAAG,EAC1B,OAAO,OACP,OAAO,MACR;AACD,YAAS,QAAQ,SAAS;IACxB,GAAG;IAED,OAAO,OAAO;IACd,eAAe,OAAO;GAEzB,EAAC;EACH,MACC,UAAS,UAAU,uBAAuB,MAAM;CAEnD,GAAE,CAAC,KAAM,EAAC;AAEX,wBACE,IAAC,mBAAmB;EAAS,OAAO,SAAS;EAC1C;GAC2B;AAEjC;;AAGD,SAAgB,sBACdC,UACG;CACH,MAAM,QAAQ,WAAW,mBAAmB;AAC5C,MAAK,MAAO,OAAM,IAAI,MAAM;AAC5B,QAAO,SAAS,OAAO,SAAS;AACjC;;;;AC5GD,MAAa,gBAAgB,WAI3B,CACE,EACE,UACA,UACA,iBACA,aACA,kBACA,OACA,UACA,WACA,UACA,SACA,QACA,WACA,UAAU,UACV,GAAG,OACyB,EAC9B,QACG;CACH,MAAM,SAAS,OAAyB,KAAK;CAC7C,MAAM,CAAC,SAAS,WAAW,GAAG,SAAS,MAAM;CAC7C,MAAM,QAAQ,sBAAsB,CAAC,MAAM,EAAE,MAAM;CACnD,MAAM,gBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc;CACnE,MAAM,MAAM,sBAAsB,CAAC,MAAM,EAAE,IAAI;CAC/C,MAAM,MAAM,sBAAsB,CAAC,MAAM,EAAE,IAAI;CAC/C,MAAM,OAAO,sBAAsB,CAAC,MAAM,EAAE,KAAK;CACjD,MAAM,QAAQ,sBAAsB,CAAC,MAAM,EAAE,MAAM;CACnD,MAAM,QAAQ,sBAAsB,CAAC,MAAM,EAAE,MAAM;CACnD,MAAM,SAAS,sBAAsB,CAAC,MAAM,EAAE,OAAO;CAErD,MAAM,QAAQ,QAAQ,MAAM;AAC1B,MAAI,QAAS,QAAO;EACpB,MAAM,IAAI;AACV,UAAQ,OAAO,aAAa,KAAK,KAAK,OAAO;CAC9C,GAAE;EAAC;EAAS;EAAK;EAAK;CAAc,EAAC;CAEtC,MAAM,qBAAqB,YACzB,CAACC,WAAgCC,MAAc;EAC7C,IAAI;AACJ,MAAI,aAAa,cAAc;AAC7B,QAAK,QAAQ,IACX,OAAM,IAAI,MAAM;GAElB,MAAM,IAAI,eAAe,eAAe,KAAK,IAAI;AACjD,cAAW,SAAS,IAAI,GAAG,KAAK,IAAI;AACpC,UAAO,MAAM,UAAU,UAAU,KAAK,EAAE,KAAK,IAAI;EAClD,OAAM;AACL,cAAW,gBAAgB;AAC3B,UAAO,UAAU,UAAU,KAAK;EACjC;CACF,GACD;EAAC;EAAK;EAAK;EAAM;CAAc,EAChC;CAED,MAAM,gBAAgB,YACpB,CAACC,UAA+C;AAC9C,OAAK,aAAa,YAAY,SAAU;EACxC,MAAM,MAAM,MAAM;AAClB,OAAK,CAAC,WAAW,WAAY,EAAC,SAAS,IAAI,CAAE;AAC7C,QAAM,gBAAgB;EACtB,MAAM,IAAI,OAAO,YAAY,SAAS,MAAM,SAAS;EACrD,MAAM,SAAS,WAAW,OAAO,mBAAmB,SAAS,IAAI,EAAE,CAAC,CAAC;AAErE,aAAW,OAAO,UAAU,OAAO,YAAY;CAChD,GACD;EAAC;EAAU;EAAU;EAAU;CAAmB,EACnD;CAED,MAAM,mBAAmB,oBACvB,SACA,CAAC,UAAU;AACT,OAAK,SAAS,SAAU;AACxB,QAAM,gBAAgB;AACtB,OAAK,YAAY,MAAM,UAAU,EAAG;EACpC,MAAM,IAAI,KAAK,KAAK,MAAM,OAAO,IAAI,MAAM;EAC3C,MAAM,SAAS,WAAW,OAAO,mBAAmB,MAAM,IAAI,EAAE,CAAC,CAAC;AAElE,aAAW,OAAO,UAAU,OAAO,YAAY;CAChD,GACD,EAAE,SAAS,MAAO,GAClB;EAAC;EAAO;EAAU;EAAU;CAAmB,EAChD;AAED,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,WAAO,SAAS,OAAO;GACxB;GACD,OAAO;AACL,WAAO,SAAS,MAAM;GACvB;EACF;CACF,GAAE,CAAE,EAAC;AAEN,wBACE,IAAC;EACC,KAAK,CAAC,UAAU;AACd,UAAO,UAAU;AACjB,oBAAiB,MAAM;EACxB;EACD,WAAW,KAAK,wBAAwB,UAAU;EAC3C;EACF;EACA;EACC;EACN,MAAK;EACL,iBAAe;EACf,iBAAe;EACf,UAAU;EACV,cAAY;EACZ,UAAU,CAAC,UAAU;AACnB,OAAI,SAAU;GACd,MAAM,IAAI,MAAM,cAAc;GAC9B,MAAM,YAAY,MAAM,OAAO;AAC/B,UAAO,EAAE;GACT,MAAMC,kBAAgB,WAAW,GAAG,OAAO,MAAM,CAAC;AAClD,cAAWA,iBAAe,EAAE;AAC5B,OAAI,WAAW;AACb,UAAM,OAAO,iBAAiB;AAC9B,UAAM,OAAO,eAAe;GAC7B;EACF;EACD,SAAS,CAAC,UAAU;AAClB,cAAW,KAAK;GAChB,MAAM,IAAI,MAAM,cAAc;GAC9B,MAAM,SAAS,WAAW,GAAG,OAAO,MAAM;AAC1C,OAAI,mBAAmB,MACrB,OAAM,cAAc,kBAAkB,GAAG,EAAE,OAAO;YACzC,mBAAmB,SAC5B,OAAM,cAAc,kBAClB,GACA,OAAO,YAAY,SAAS,OAAO,KAAK,OACzC;AAEH,aAAU,OAAO,UAAU,OAAO,aAAa,MAAM;EACtD;EACD,QAAQ,CAAC,UAAU;AACjB,cAAW,MAAM;GAEjB,IAAI,IAAI,WAAW,MAAM,cAAc,OAAO,OAAO,MAAM,CAAC;AAC5D,OAAI,iBACF,KAAI,UAAU,GAAG,KAAK,IAAI;GAE5B,MAAM,SAAS,WAAW,OAAO,EAAE,EAAE,OAAO,MAAM;AAClD,UAAO,OAAO,YAAY;AAC1B,OAAI,iBACF,YAAW,OAAO,UAAU,OAAO,YAAY;AAEjD,YAAS,OAAO,UAAU,OAAO,aAAa,MAAM;EACrD;EACD,WAAW,CAAC,UAAU;AACpB,OAAI,eAAe,MAAM,OAAO,QAC9B,OAAM,cAAc,MAAM;AAE5B,iBAAc,MAAM;AACpB,eAAY,MAAM;EACnB;EACD,GAAI;GACJ;AAEL,EACF;;;;;AC/MD,SAAgB,QAAQ,EACtB,UAAU,MACV,UACA,UACA,GAAG,OACsE,EAAE;AAC3E,wBACE,IAAC;EACC,WAAW,KAAK,gCAAgC,UAAU;EAC1D,gBAAc;EACd,GAAI;EAEH;GACG;AAET;;;;ACxBD,SAAgB,YAAYC,UAAsBC,OAAsB;CACtE,MAAM,gBAAgB,OAAO,SAAS;AAGtC,WAAU,MAAM;AACd,gBAAc,UAAU;CACzB,GAAE,CAAC,QAAS,EAAC;AAGd,WAAU,MAAM;AAGd,MAAI,UAAU,KACZ;EAGF,MAAM,KAAK,YAAY,MAAM;AAC3B,iBAAc,SAAS;EACxB,GAAE,MAAM;AAET,SAAO,MAAM;AACX,iBAAc,GAAG;EAClB;CACF,GAAE,CAAC,KAAM,EAAC;AACZ;;;;ACrBD,SAAgB,aACdC,UACA,eAAe,KACf,WAAW,IACX;CACA,MAAM,CAAC,SAAS,WAAW,GAAG,SAAS,MAAM;CAC7C,MAAM,CAAC,OAAO,SAAS,GAAG,SAAS,aAAa;AAEhD,aACE,MAAM;AACJ,YAAU;AACV,WAAS,SAAS;CACnB,GACD,UAAU,QAAQ,KACnB;AAED,kBAAiB,WAAW,QAAQ,aAAa,MAAM;AACrD,aAAW,MAAM;AACjB,WAAS,aAAa;CACvB,EAAC;AAEF,QAAO,YAAY,MAAM;AACvB,YAAU;AACV,aAAW,KAAK;CACjB,GAAE,CAAC,QAAS,EAAC;AACf;;;;;AChBD,SAAgB,iBAAiB,EAC/B,OAAO,IACP,UACA,UACA,GAAG,OAE+D,EAAE;CACpE,MAAM,MAAM,sBAAsB,CAAC,MAAM,EAAE,IAAI;CAC/C,MAAM,gBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc;CACnE,MAAM,WAAW,sBAAsB,CAAC,MAAM,EAAE,SAAS;CACzD,MAAM,kBAAkB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB;CACvE,MAAM,YAAY,sBAAsB,CAAC,MAAM,EAAE,UAAU;CAE3D,MAAM,QAAQ,aAAa,UAAU;AAErC,wBAEE,IAAC;EACC,WAAW,KAAK,0CAA0C,UAAU;EACpE,MAAK;EACL,UAAU;EACV,iBACE,mBAAmB,kBAAkB,OAAO,OAAO;EAErD,iBAAe;EACf,eAAe;EACf,GAAI;YAEH,4BACC,IAAC;GACC,OAAO;GACP,QAAQ;GACR,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;6BAEf,IAAC,cAAS,QAAO,oBAAoB;IACjC;GAEJ;AAET;;;;;AC5CD,SAAgB,iBAAiB,EAC/B,OAAO,IACP,UACA,UACA,GAAG,OAE+D,EAAE;CACpE,MAAM,MAAM,sBAAsB,CAAC,MAAM,EAAE,IAAI;CAC/C,MAAM,gBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc;CACnE,MAAM,WAAW,sBAAsB,CAAC,MAAM,EAAE,SAAS;CACzD,MAAM,kBAAkB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB;CACvE,MAAM,YAAY,sBAAsB,CAAC,MAAM,EAAE,UAAU;CAE3D,MAAM,QAAQ,aAAa,UAAU;AAErC,wBAEE,IAAC;EACC,WAAW,KAAK,0CAA0C,UAAU;EACpE,MAAK;EACL,UAAU;EACV,iBACE,mBAAmB,kBAAkB,OAAO,OAAO;EAErD,iBAAe;EACf,eAAe;EACf,GAAI;YAEH,4BACC,IAAC;GACC,OAAO;GACP,QAAQ;GACR,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;6BAEf,IAAC,cAAS,QAAO,mBAAmB;IAChC;GAEJ;AAET;;;;;;;;AC2CD,MAAa,cAAc,WACzB,CACE,EACE,OACA,KACA,KACA,OAAO,GACP,OACA,WAAW,OACX,WAAW,OACX,OACA,UAAU,WACV,kBAAkB,QAClB,cAAc,MACd,kBAAkB,MAClB,mBAAmB,MACnB,QAAQ,CAAC,OAAO,CAAE,GAClB,WAAW,CAAC,OAAO,CAAE,GACrB,aACA,kBACA,WACA,UACA,SACA,QACA,SACA,GAAG,OACG,EACR,QACG;CACH,MAAMC,SAAgD,EACpD,kBAAkB,YACnB;AACD,wBACE,IAAC;EACC,OAAO,OAAO,MAAM;EACf;EACA;EACC;EACC;EACA;EACG;EACO;EACP;4BAEV,KAAC;GACC,WAAW,KAAK,gCAAgC,iBAAiB;GAEjE,UAAU;GACV,OAAO,EACL,GAAG,OACJ;GACD,kBAAgB;GAChB,gBAAc;8BAEd,IAAC;IACM;IACK;IACA;IACO;IACJ;IACK;IACX;IACG;IACC;IACD;IACD;IACD;IACR,GAAI;KACJ,EACD;IACG;GACc;AAEzB,EACF;;;;;;;AC9JD,SAAgB,mBAAsC,EACpD,gBACA,QACA,aACA,WAC2B,EAG3B;CACA,MAAM,UAAU,OAAO,MAAM;CAC7B,MAAM,cAAc,OAAO,EAAE;CAC7B,MAAM,cAAc,OAAO,EAAE;CAE7B,MAAM,aAAa,YACjB,CAACC,UAA2D;AAC1D,OAAK,eAAe,YAAY,QAAQ,QACtC;EAEF,MAAM,UAAU,iBAAiB;AACjC,MAAI,WAAW,MAAM,WAAY,OAAM,gBAAgB;EACvD,MAAM,EAAE,MAAM,KAAK,OAAO,QAAQ,GAChC,eAAe,QAAQ,uBAAuB;EAChD,MAAM,SAAS,UAAU,MAAM,QAAQ,GAAG,UAAU,MAAM;EAC1D,MAAM,SAAS,UAAU,MAAM,QAAQ,GAAG,UAAU,MAAM;EAC1D,MAAM,KAAK,eAAe,QAAQ,MAAM,MAAM;EAC9C,MAAM,KAAK,eAAe,QAAQ,KAAK,OAAO;AAC9C,cAAY,UAAU;AACtB,cAAY,UAAU;AACtB,SAAO,IAAI,GAAG;CACf,GACD,CAAC,QAAQ,cAAe,EACzB;CAED,MAAM,aAAa,oBACjB,aACA,YACA,EAAE,SAAS,MAAO,GAClB,CAAC,MAAO,EACT;CAED,MAAM,qBAAqB,YACzB,CAACC,UAAiC;AAChC,UAAQ,UAAU;AAClB,aAAW,MAAM;AACjB,gBAAc,YAAY,SAAS,YAAY,QAAQ;CACxD,GACD,CAAC,YAAY,WAAY,EAC1B;AAED,kBAAiB,WAAW,QAAQ,eAAe,WAAW;AAE9D,kBAAiB,WAAW,QAAQ,aAAa,MAAM;AACrD,OAAK,QAAQ,QAAS;AACtB,UAAQ,UAAU;AAClB,cAAY,YAAY,SAAS,YAAY,QAAQ;CACtD,EAAC;AAEF,QAAO,CAAC,YAAY,kBAAmB;AACxC;;;;AClDD,MAAM,mBAAmB,CAACC,cAAuC;CAE/D,MAAMC,gBAAuB;EAC3B,WAAW;GAAE,OAAO;GAAG,MAAM;EAAK;EAClC,WAAW;EACX,SAAS;EACT,MAAM;EACN,OAAO;EACP,YAAY,MAAM,CAAE;EACpB,YAAY,MAAM,CAAE;CACrB;AAED,QAAO,aAA6B,CAAC,OAAO;EAC1C,GAAG;EACH,GAAG;EACH,cAAc,UAAU;CACzB,GAAE;AACJ;AAED,MAAM,eAAe,cAAiC,KAAK;AAI3D,SAAgB,cAAc,EAAE,SAAU,GAAG,OAA2B,EAAE;CACxE,MAAM,WAAW,OAAmB,KAAK;AACzC,MAAK,SAAS,QACZ,UAAS,UAAU,iBAAiB,MAAM;AAG5C,WAAU,MAAM;AACd,MAAI,SAAS,QACX,UAAS,QAAQ,SAAS,MAAM;MAEhC,UAAS,UAAU,iBAAiB,MAAM;CAE7C,GAAE,CAAC,KAAM,EAAC;AAEX,wBACE,IAAC,aAAa;EAAS,OAAO,SAAS;EACpC;GACqB;AAE3B;;AAGD,SAAgB,gBAAmBC,UAA2C;CAC5E,MAAM,QAAQ,WAAW,aAAa;AACtC,MAAK,MAAO,OAAM,IAAI,MAAM;AAC5B,QAAO,SAAS,OAAO,SAAS;AACjC;;;;;AClDD,SAAgB,SAAS,EACvB,OACA,WACA,kBACA,cACA,QACA,QACA,GAAG,OACwE,EAAE;CAC7E,MAAM,YAAY,gBAAgB,CAAC,MAAM,EAAE,UAAU;CACrD,MAAM,iBAAiB,kBAAkB,UAAU;CACnD,MAAM,QAAQ,eAAe,QAAQ,OAAQ;CAC7C,MAAM,UAAU,QACZ,MAAM,QAAS,MAAM,GACrB,WAAW,QAAQ,QAAS,MAAM;AAEtC,SACG,qBAAwB,WAAW,yBAClC,IAAC;EACC,WAAW,KAAK,mCAAmC,iBAAiB;EACpE,OAAO;4BAEP,IAAC;GAAI,WAAW,KAAK,2BAA2B,UAAU;GAAE,GAAI;aAC7D;IACG;GACF;AAGX;;;;;ACDD,MAAa,uBAAuB;;AAEpC,MAAa,uBAAuB;AAEpC,MAAM,UAAU,WACd,CACE,EACE,SACA,YACA,OACA,QACA,IACA,OACA,UACA,aACA,WACA,OACA,UACA,QACA,GAAG,OACO,EACZ,QACG;CACH,MAAM,CAAC,QAAQ,UAAU,GAAG,SAAS,MAAM;CAC3C,MAAM,UAAU,gBAAgB,CAAC,MAAM,EAAE,QAAQ;CACjD,MAAM,OAAO,gBAAgB,CAAC,MAAM,EAAE,KAAK;CAE3C,MAAM,aAAa,gBAAgB,CAAC,MAAM,EAAE,WAAW;CACvD,MAAM,aAAa,gBAAgB,CAAC,MAAM,EAAE,WAAW;CACvD,MAAM,QAAQ,gBAAgB,CAAC,MAAM,EAAE,MAAM;CAC7C,MAAM,eAAe,gBAAgB,CAAC,MAAM,EAAE,aAAa;CAC3D,MAAM,WAAW,aAAa,WAAW;CAEzC,MAAM,WAAW,aAAa;CAC9B,MAAM,SAAS;EACb,QAAQ;EACR,WAAW;EACX,eAAe;EACf,kBAAkB;CACnB;AAED,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,OAAO;AACL,QAAI,SAAU;AACd,cAAU,KAAK;AACf,QAAI,WAAY,YAAW,WAAW;GACvC;GACD,OAAO;AACL,cAAU,MAAM;AAChB,QAAI,WAAY,YAAW,WAAW;GACvC;GACD,SAAS;AACP,WAAO;GACR;EACF;CACF,GAAE;EAAC;EAAU;EAAY;EAAY;EAAY;CAAO,EAAC;CAE1D,IAAIC,gBAA+B,CAAE;AACrC,KAAI,mBACF,OAAM,SAAS,QAAQ,UAAU,CAAC,UAAU;AAC1C,MAAI,MAAM,eAAe,MAAM,CAC7B,KAAI,MAAM,QAAQ,SAChB,iBAAgB,MAAM;MAEtB,OAAM,IAAI,MAAM;MAGlB,OAAM,IAAI,MAAM;CAEnB,EAAC;AAGJ,wBACE,IAAC;EACC,WAAW,MAAM,gBAAgB,QAAQ,OAAO,UAAU;EAC1D,iBAAe;EACf,eAAa;EACb,OAAO;GACL,GAAG;GACH,MAAM;GACN,OAAO,OAAO,UAAU;GAChB;GACR,GAAG;EACJ;EAyBD,GAAI;4BAEJ,IAAC;GAAgB;GAAO,QAAQ;GAAY,GAAI;IAAiB;GAC7D;AAET,EACF;;AAGD,MAAa,WAAW,WACtB,CACE,EACE,QAAQ,sBACR,SAAS,QACT,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,CACzC,GAAG,OACG,EACR,QACG;AACH,wBACE,IAAC;EACM;EACL,SAAQ;EACD;EACC;EACO;EACf,GAAI;GACJ;AAEL,EACF;;AAGD,MAAa,WAAW,WACtB,CACE,EACE,QAAQ,sBACR,SAAS,OACT,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,CACzC,GAAG,OACG,EACR,QACG;AACH,wBACE,IAAC;EACM;EACL,SAAQ;EACD;EACC;EACO;EACf,GAAI;GACJ;AAEL,EACF;;;;;AC5MD,MAAa,YAAY,EACvB,UAAU,EACR,MAAM;CACJ;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,EACF,EACF;;;;;;;;;;;ACYD,SAAgB,kBAAkBC,WAAsB;AACtD,QAAO,MAAM,KACX,EAAE,QAAQ,UAAU,OAAO,UAAU,QAAQ,EAAG,GAChD,CAAC,GAAG,MAAM,IAAI,UAAU,MACzB;AACF;AA6BD,MAAM,qBAAqB,uBAAuB;;;;;AAMlD,SAAgB,MAAM,EACpB,WACA,YAAY,MACZ,UAAU,KACV,mBACA,OAAO,OACP,SAAS,OAAO,SAAS,KACzB,gBAAgB,kBAAkB,sBAClC,OACA,WACA,YACA,YACA,OACA,UACA,cACA,GAAG,OACkE,EAAE;CAEvE,MAAM,CAAC,gBAAgB,kBAAkB,GAAG,SAAS,gBAAgB;CACrE,MAAM,UAAU,OAAuC,CAAE,EAAC;AAC1D,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,OAAO,UAAU,QAAQ,GAAG,IACxD,SAAQ,QAAQ,KAAK,WAAuB;CAE9C,MAAM,WAAW,OAAuB,KAAK;CAC7C,MAAM,cAAc,OAAO,GAAG;CAG9B,MAAM,iBAAiB,kBAAkB,UAAU;CACnD,MAAM,aAAa,eAAe,OAAO,CAAC,MAAM,WAAW,EAAE,CAAC;CAC9D,MAAM,aAAa,eAAe,OAAO,CAAC,MAAM,WAAW,EAAE,CAAC;CAC9D,MAAM,iBAAiB,WAAW;CAClC,MAAM,UAAU;CAChB,MAAM,eAAe,iBAAiB,WAAW;CAGjD,MAAM,oBAAoB,QAAQ,MAAM;AACtC,SACE,YACA,MAAM,SAAS,IAAI,UAAU,CAAC,OAAO,UAAU;AAC7C,OAAI,MAAM,eAAe,MAAM,EAAE;IAC/B,MAAM,UACJ,MAAM,QAAQ,WAAW,iBAAiB,iBAAiB;IAC7D,MAAMC,UAAQ;KAAE,KAAK,QAAQ,QAAQ;KAAQ;IAAS;AACtD,WAAO,MAAM,aAAa,OAAOA,QAAM;GACxC;AACD,UAAO;EACR,EAAC;CAEL,GAAE,CAAC,UAAU,cAAe,EAAC;CAG9B,MAAM,eAAe,YACnB,CAACC,SAAiB;EAChB,MAAMC,iBAA0C;GAC9C,GAAG;GACH,MAAM;GACN,GAAG;GACH,MAAM;GACN,GAAG;GACH,GAAG;GACH,MAAM;GACN,GAAG;GACH,MAAM;GACN,GAAG;GACH,MAAM;GACN,GAAG;EACJ;EAED,MAAM,iBAAiB,iBAAiB;EACxC,MAAMC,YAAU;EAChB,MAAM,gBAAgB,QAAQ,KAAK;EACnC,MAAM,eAAe,QAAQ,UAAU,MAAM;EAC7C,MAAM,SAAS,KAAK,OAAO,OAAO,UAAU,SAAS,GAAG;EACxD,MAAM,eACJ,SAAS,QAAQ,aAAa,GAAG,SAAS,QAAQ,cAAc,GAAG,IAAI;EACzE,MAAM,IAAI,iBAAiBA;EAC3B,MAAM,MAAM,eAAe,iBAAiB,eAAe;EAC3D,MAAM,iBAAiB,WAAW,KAAK,GAAG,iBAAiB,IAAI;AAC/D,SAAO,MAAM,KAAK,SAAS,gBAAgB,IAAI,IAAI;CACpD,GACD,CAAC,UAAU,OAAO,cAAe,EAClC;CAED,MAAM,iBAAiB,YACrB,CAACC,GAAWC,MAAc;AACxB,OAAK,SAAS,QAAS,QAAO;EAC9B,MAAM,kBAAkB,SAAS,QAAQ;EACzC,MAAM,QAAQ,CAAC,GAAG,YAAY,GAAG,UAAW;AAC5C,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACrC,MAAM,OAAO,MAAM;GACnB,MAAM,MAAM,aAAa,KAAK;GAC9B,MAAM,IAAI,WAAW,KAAK,GACtB,iBACA,iBAAiB;GACrB,MAAM,IAAI,WAAW,KAAK,GAAG,kBAAkB,kBAAkB;AACjE,OAAI,OAAO,KAAK,IAAI,MAAM,KAAK,KAAK,KAAK,IAAI,EAC3C,QAAO;EAEV;AACD,SAAO;CACR,GACD;EAAC;EAAY;EAAc;EAAgB;CAAW,EACvD;CAKD,MAAM,SAAS,YACb,CAACC,MAAcC,SAAiB;AAC9B,OAAK,SAAS,QAAS;EACvB,MAAM,IAAI,OAAO;EACjB,MAAM,IAAI,OAAO,SAAS,QAAQ;EAClC,MAAM,OAAO,eAAe,GAAG,EAAE;EACjC,MAAM,QAAQ,eAAe,QAAQ,KAAK;AAC1C,MAAI,SAAS,GAAI;AACjB,MAAI,YAAY,WAAW,OAAO;AAChC,WAAQ,QAAQ,YAAY,UAAU,SAAS,MAAM;AACrD,WAAQ,QAAQ,QAAQ,SAAS,MAAM;AACvC,eAAY,UAAU;EACvB;CACF,GACD;EAAC;EAAgB;EAAgB;CAAY,EAC9C;CAED,MAAM,YAAY,YAAY,MAAM;AAClC,MAAI,QAAQ,QAAQ,YAAY,UAAU,SAAS,QAAQ,CACzD,SAAQ,QAAQ,YAAY,UAAU,SAAS,MAAM;AAEvD,cAAY,UAAU;CACvB,GAAE,CAAC,OAAQ,EAAC;AAGb,WAAU,MAAM;AACd,MAAI,QAAQ,SAAS,SAAS;GAC5B,MAAM,SAAS,SAAS,QAAQ;AAChC,QAAK,OAAQ,OAAM,IAAI,MAAM;GAC7B,MAAM,iBAAiB,IAAI,eAAe,MAAM;IAC9C,MAAM,IAAI,SAAS,QAAS;AAC5B,sBAAkB,IAAI,iBAAiB,QAAQ;GAChD;AACD,kBAAe,QAAQ,OAAO;AAC9B,UAAO,MAAM;AACX,mBAAe,UAAU,OAAO;GACjC;EACF,MACC,mBAAkB,gBAAgB;CAErC,GAAE;EAAC;EAAM;EAAiB;CAAe,EAAC;CAE3C,MAAM,CAAC,sBAAsB,mBAAmB,GAC9C,mBAAmC;EACjC,gBAAgB;EACR;EACG;CACZ,EAAC;AAEJ,kBAAiB,WAAW,QAAQ,WAAW,CAAC,MAAM;AACpD,MAAI,EAAE,OAAQ;AACd,OAAK,kBAAmB;EACxB,MAAM,QAAQ,kBAAkB,KAAK,QAAQ,EAAE,IAAI;AACnD,MAAI,SAAS,IACX;QAAK,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,CAC5C,SAAQ,QAAQ,QAAQ,SAAS,MAAM;EACxC;CAEJ,EAAC;AAEF,kBAAiB,WAAW,QAAQ,SAAS,CAAC,MAAM;AAClD,MAAI,EAAE,OAAQ;AACd,OAAK,kBAAmB;EACxB,MAAM,QAAQ,kBAAkB,KAAK,QAAQ,EAAE,IAAI;AACnD,MAAI,SAAS,GACX,SAAQ,QAAQ,QAAQ,SAAS,MAAM;CAE1C,EAAC;AAEF,wBACE,IAAC;EACe;EACH;EACA;EACF;EACH;EACM;EACA;EACL;4BAEP,IAAC;GACC,KAAK,CAAC,QAAQ;AACZ,aAAS,UAAU;AACnB,yBAAqB,IAAI;GAC1B;GACD,WAAW,KAAK,iBAAiB,UAAU;GAC3C,OAAO;IACL,OAAO,OAAO,SAAS;IACf;IACR,GAAG;GACJ;GACD,eAAe,CAAC,UAAU;AACxB,uBAAmB,MAAM;AACzB,oBAAgB,MAAM;GACvB;GACD,GAAI;aAEH,qBACC,eAAe,IAAI,CAAC,MAAM,UACxB,WAAW,KAAK,mBACd,IAAC;IACC,KAAK,QAAQ,QAAQ;IAErB,YAAY;IACZ,SAAS;MAFJ,KAGL,mBAEF,IAAC;IACC,KAAK,QAAQ,QAAQ;IAErB,YAAY;IACZ,SAAS,iBAAiB;MAFrB,KAGL,CAEL;IACC;GACQ;AAEnB;;;;ACrSD,MAAM,oBAAoB,CAACC,cAA+B;CACxD,MAAMC,gBAAuB;EAC3B,KAAK;EACL,KAAK;EACL,MAAM;EACN,MAAM;EACN,UAAU;EACV,SAAS;EACT,UAAU;EACV,UAAU;CACX;AAED,QAAO,aAAoB,CAAC,OAAO;EACjC,GAAG;EACH,GAAG;CACJ,GAAE;AACJ;AAED,MAAM,gBAAgB,cAAkC,KAAK;AAI7D,SAAgB,eAAe,EAAE,SAAU,GAAG,OAA4B,EAAE;CAC1E,MAAM,WAAW,OAAoB,KAAK;AAC1C,MAAK,SAAS,QACZ,UAAS,UAAU,kBAAkB,MAAM;AAG7C,WAAU,MAAM;AACd,MAAI,SAAS,QACX,UAAS,QAAQ,SAAS,MAAM;MAEhC,UAAS,UAAU,kBAAkB,MAAM;CAE9C,GAAE,CAAC,KAAM,EAAC;AAEX,wBACE,IAAC,cAAc;EAAS,OAAO,SAAS;EACrC;GACsB;AAE5B;;AAGD,SAAgB,iBAAoBC,UAAkC;CACpE,MAAM,QAAQ,WAAW,cAAc;AACvC,MAAK,MAAO,OAAM,IAAI,MAAM;AAC5B,QAAO,SAAS,OAAO,SAAS;AACjC;;;;;AC7BD,SAAgB,YAAY,EAC1B,OACA,OAAO,eACP,OACA,YAAY,GACZ,SAAS,UACT,MAAM,GACN,YACA,SACA,QACA,WACA,MACA,GAAG,OAE0D,EAAE;CAC/D,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI;CAC1C,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI;CAC1C,MAAM,OAAO,iBAAiB,CAAC,MAAM,EAAE,KAAK;CAC5C,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;CACpD,MAAM,UAAU,iBAAiB,CAAC,MAAM,EAAE,QAAQ;CAElD,MAAM,cAAc,YAClB,CAACC,eAAqB;AACpB,SAAO,QACL,IAAI,UAAU,QAAQ,GAClB,MAAM,eAAeC,YAAU,KAAK,KAAK,KAAK,GAAG,MACjD,eAAeA,YAAU,KAAK,KAAK,KAAK,GAAG,IAChD;CACF,GACD;EAAC;EAAU;EAAS;EAAK;EAAK;CAAK,EACpC;AAED,wBACE,KAAC;EACC,WAAW,KAAK,+BAA+B,UAAU;EACzD,OAAO;GACL,OAAO,YAAY,EAAE,YAAY,MAAM,CAAC;GACxC,KAAK,YAAY,EAAE,YAAY,MAAM,CAAC;GACtC,GAAG;EACJ;EACD,iBAAe;EACf,GAAI;aAEH,QAAQ,4BACP,IAAC;GACC,WAAW,KAAK,oCAAoC,SAAS,KAAK;GAClE,OAAO;IACL,QAAQ,WAAW,YAAY;IAC/B,QAAQ,WAAW,YAAY;IAC/B,eAAe,WAAW;IAC1B,aAAa,WAAW;IACxB,GAAG,QAAQ;GACZ;GACD,iBAAe;IACV,EAER,QAAQ,0BACP,IAAC;GACC,WAAW,KAAK,qCAAqC,SAAS,MAAM;GACpE,OAAO;IACL,OAAO;IACP,GAAG,QAAQ;GACZ;aAEA,SAAS;IACN;GAEJ;AAET;;;;;ACvFD,SAAgB,MAAM,EACpB,MAAM,GACN,SACA,UACA,WACA,MACA,GAAG,OACkE,EAAE;CACvE,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI;CAC1C,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI;CAC1C,MAAM,OAAO,iBAAiB,CAAC,MAAM,EAAE,KAAK;CAC5C,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;CACpD,MAAM,UAAU,iBAAiB,CAAC,MAAM,EAAE,QAAQ;CAElD,MAAM,cAAc,UAChB,oBAAoB,SAAS,KAAK,KAAK,KAAK,GAC5C,CAAE;AACN,KAAI,IAAI,UAAU,QAAQ,CAAE,aAAY,SAAS;AAEjD,wBACE,IAAC;EACC,WAAW,KAAK,wBAAwB,UAAU;EAClD,OAAO;GACL,YAAY,WAAW;GACvB,YAAY,WAAW;GACvB,GAAG;EACJ;EACD,GAAI;YAEH,UACG,YAAY,IAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU;AAC1C,0BAAO,IAAC;IAA+B;IAAa;MAA3B,MAAmC;EAC7D,EAAC,GACF;GACA;AAET;;;;;ACnBD,MAAa,mBAAmB;;AAGhC,MAAa,cAAc,WACzB,CACE,EACE,MACA,QAAQ,kBACR,SAAS,kBACT,OACA,UACA,WACA,OACA,WACiB,EACnB,QACG;CACH,MAAM,aAAa,OAAuB,KAAK;CAC/C,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;CACpD,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;CACpD,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;AAEpD,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,eAAW,SAAS,OAAO;GAC5B;GACD,OAAO;AACL,eAAW,SAAS,MAAM;GAC3B;EACF;CACF,GAAE,CAAE,EAAC;AAEN,wBACE,IAAC;EACC,WAAU;EACV,OAAO;GACL,KAAK,YAAY,EAAE,UAAU,KAAK;GAClC,OAAO,YAAY,EAAE,UAAU,KAAK;EACrC;YAEA,WACC,2BAGA,IAAC;GACC,KAAK;GACL,WAAW,KAAK,wBAAwB,UAAU;GAElD,UAAU;GACV,iBAAe;GACf,iBAAe;GACf,OAAO;IACA,WAAW;IAChB,OAAO,QAAQ;IACf,QAAQ,QAAQ;IAChB,GAAG;GACJ;IACI;GAEL;AAET,EACF;;;;AC1FD,MAAa,gBAAgB;AAC7B,MAAa,mBAAmB;;AAuBhC,SAAgB,YAAY,EAC1B,SAAS,eACT,YAAY,kBACZ,QACA,UACA,UACA,WACA,OACA,eAAe,MACf,SACA,YAAY,EACZ,GAAG,OAE0D,EAAE;CAC/D,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;CACpD,MAAM,UAAU,iBAAiB,CAAC,MAAM,EAAE,QAAQ;CAClD,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,SAAS;CAEpD,MAAM,YAAY,WAAW,WAAW;CACxC,MAAM,SAAS;EACb,YAAY;EACZ,cAAc;CACf;AAED,wBACE,KAAC;EACC,WAAW,KAAK,wBAAwB,UAAU;EAClD,iBAAe;EACf,iBAAe;EACf,QACG,eACG,QACA;GACE,GAAG;GACH,YAAY,IAAI,UAAU,QAAQ,IAC7B,qBAAqB,UAAU,0BAA0B,UAAU,4BAA4B,UAAU,OACzG,qBAAqB,UAAU,2BAA2B,UAAU,2BAA2B,UAAU;GAC9G,cAAc,YAAY,WAAY,KAAK,EAAE;GAC7C,QAAQ,WAAW,SAAS;GAC5B,QAAQ,WAAW,SAAS;GAC5B,GAAG;EACJ;EAEP,GAAI;aAEH,UACA;GACG;AAET;;;;;;;;ACOD,MAAa,SAAS,WACpB,CACE,EACE,OACA,KACA,KACA,OAAO,GACP,OAAO,GACP,WAAW,OACX,UAAU,OACV,eAAe,MACf,QAAQ,CAAC,OAAO,CAAE,GAClB,WAAW,CAAC,OAAO,CAAE,GACrB,WAAW,OACX,WAAW,OACX,UACA,aACA,WACA,WACA,OACA,UACA,SACA,QACA,eACA,UACA,GAAG,OACG,EACR,QACG;CAEH,MAAM,kBAAkB,OAAuB,KAAK;CACpD,MAAM,WAAW,OAA2B,KAAK;CAGjD,MAAM,IAAI,QAAQ,eAAe,OAAO,KAAK,KAAK,KAAK,GAAG,IAAI;CAC9D,MAAM,MAAM,QAAQ,MAAM,EAAE;CAM5B,MAAM,kBAAkB,QACtB,MAAM,IAAI,UAAU,QAAQ,EAC5B,CAAC,UAAU,OAAQ,EACpB;CACD,MAAM,UAAU,kBAAkB,MAAM;CAExC,IAAIC,aAA+B,CAAE;CACrC,IAAIC,aAA+B,CAAE;CACrC,IAAIC;AACJ,KAAI,mBACF,OAAM,SAAS,QAAQ,UAAU,CAAC,UAAU;AAC1C,MAAI,MAAM,eAAe,MAAM,CAC7B,KAAI,MAAM,QAAQ,YAChB,cAAa,MAAM;WACV,MAAM,QAAQ,YACvB,cAAa,MAAM;WACV,MAAM,QAAQ,MACvB,kBAAiB;MAEjB,OAAM,IAAI,MAAM;MAGlB,OAAM,IAAI,MAAM;CAEnB,EAAC;CAIJ,MAAM,SAAS,YACb,CAACC,IAAYC,OAAe;AAC1B,OAAK,YAAY,SAAU;EAC3B,MAAM,IAAI,WAAW,KAAK;EAC1B,MAAM,IAAI,SAAS,kBAAkB,IAAI,IAAI,GAAG,KAAK,KAAK,KAAK;EAC/D,MAAM,KAAK,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK,IAAI;AAC9C,WAAS,GAAG;CACb,GACD;EAAC;EAAiB;EAAK;EAAK;EAAU;EAAU;EAAM;EAAM;CAAS,EACtE;CAED,MAAM,qBAAqB,YACzB,CAACC,WAAgCC,MAAc;EAC7C,IAAI;AACJ,MAAI,aAAa,cAAc;GAC7B,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,KAAK;AAC/C,cAAW,SAAS,IAAI,GAAG,KAAK,KAAK,KAAK;EAC3C,MACC,YAAW,QAAQ;AAErB,SAAO,MAAM,UAAU,UAAU,KAAK,EAAE,KAAK,IAAI;CAClD,GACD;EAAC;EAAK;EAAK;EAAM;EAAM;CAAM,EAC9B;CAED,MAAM,gBAAgB,YACpB,CAACC,UAA+C;AAC9C,OAAK,aAAa,YAAY,SAAU;EACxC,MAAM,MAAM,MAAM;AAClB,MAAI;GAAC;GAAc;GAAa;GAAW;EAAY,EAAC,SAAS,IAAI,EAAE;AACrE,SAAM,gBAAgB;GACtB,IAAI,IACF,OAAO,gBAAgB,OAAO,YAAY,SAAS,MAAM,SAAS;AACpE,OAAI,QAAS,MAAK;AAClB,YAAS,mBAAmB,SAAS,IAAI,EAAE,CAAC;EAC7C;CACF,GACD;EAAC;EAAU;EAAU;EAAU;EAAS;CAAmB,EAC5D;CAGD,MAAM,CAAC,sBAAsB,mBAAmB,GAC9C,mBAAmC;EACjC,gBAAgB;EACR;EACR,aAAa,CAAC,IAAI,OAAO;AACvB,OAAI,SAAU;AACd,OAAI,aAAc,cAAa;AAC/B,YAAS,SAAS,OAAO;AACzB,iBACE,MACE,UAAU,SAAS,WAAW,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,KAAK,EAC7D,KACA,IACD,CACF;EACF;EACD,WAAW,CAAC,IAAI,OAAO;AACrB,OAAI,SAAU;AACd,OAAI,aAAc,iBAAgB;AAClC,eACE,MACE,UAAU,SAAS,WAAW,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,KAAK,EAC7D,KACA,IACD,CACF;EACF;CACF,EAAC;CAEJ,MAAM,mBAAmB,oBACvB,SACA,CAAC,UAAU;AACT,OAAK,UAAU,YAAY,SAAU;AACrC,QAAM,gBAAgB;EACtB,IAAI;AACJ,OAAK,YAAY,MAAM,UAAU,EAC/B,KAAI,MAAM,SAAS,IAAI,MAAM,MAAM,MAAM;OACpC;AACL,OAAI,MAAM,UAAU,EAAG;AACvB,OAAI,MAAM,SAAS,KAAK,MAAM,KAAK,MAAM;EAC1C;AACD,MAAI,YAAY,QAAS,MAAK;AAC9B,WAAS,mBAAmB,MAAM,IAAI,EAAE,CAAC;CAC1C,GACD,EACE,SAAS,MACV,GACD;EAAC;EAAO;EAAU;EAAU;EAAU;CAAmB,EAC1D;AAED,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,aAAS,SAAS,OAAO;GAC1B;GACD,OAAO;AACL,aAAS,SAAS,MAAM;GACzB;EACF;CACF,GAAE,CAAE,EAAC;AAEN,wBACE,IAAC;EACM;EACA;EACC;EACA;EACI;EACD;EACC;EACA;4BAEV,IAAC;GACC,WAAW,KAAK,kBAAkB,UAAU;GAC5C,KAAK,CAAC,QAAQ;AACZ,qBAAiB,IAAI;AACrB,yBAAqB,IAAI;GAC1B;GACD,UAAU;GACV,MAAK;GACL,iBAAe;GACf,iBAAe;GACf,iBAAe;GACf,oBAAkB,WAAW,aAAa;GAC1C,iBAAe;GACf,iBAAe;GACf,OAAO;IACL,SAAS,OAAO,YAAY,YAAY,QAAQ,GAAG,CAAC;IACpD,GAAG;GACJ;GACD,eAAe,CAAC,UAAU;AACxB,uBAAmB,MAAM;AACzB,oBAAgB,MAAM;GACvB;GACD,WAAW,CAAC,UAAU;AACpB,kBAAc,MAAM;AACpB,gBAAY,MAAM;GACnB;GACD,SAAS,CAAC,UAAU;AAClB,aAAS,SAAS,OAAO;AACzB,cAAU,MAAM;GACjB;GACD,QAAQ,CAAC,UAAU;AACjB,aAAS,SAAS,MAAM;AACxB,aAAS,MAAM;GAChB;GACD,GAAI;6BAEJ,KAAC;IACC,OAAO;KACL,SAAS;KACT,eAAe,WAAW,QAAQ;KAClC,QAAQ,WAAW;KACnB,QAAQ,WAAW;IACpB;+BAED,IAAC;KAAI,WAAU;KAA+B,KAAK;+BACjD,IAAC;MACC,WAAW;MACX,yBACE,IAAC;OACC,KAAK;OACL,WAAW;OACX,GAAI;QACJ;MAEJ,GAAI;OACJ;MACE,EACL;KACG;IACF;GACS;AAEpB,EACF;;;;;AC/SD,SAAgB,cACdC,OAEA;CACA,MAAM,EAAE,UAAU,SAAS,IAAI,YAAY,MAAO,GAAG,YAAY,GAAG;CAEpE,MAAM,mBAAmB,oBACvB,SACA,CAAC,UAAU;AACT,MAAI,QAAS,SAAQ,MAAM;CAC5B,GACD,EAAE,SAAS,MAAO,GAClB,CAAC,OAAQ,EACV;AAED,wBACE,IAAC;EAAU,KAAK;EAAkB,GAAI;EACnC;GACS;AAEf;;;;;AChCD,SAAgB,UAAU,EACxB,QAAQ,KACR,SAAS,KACT,OACA,UACA,WACA,OACA,QACA,GAAG,OACgE,EAAE;AACrE,wBACE,KAAC;EACC,WAAW,KAAK,uBAAuB,UAAU;EACjD,OAAO;GACA,WAAW;GACT;GACC;GACR,GAAG;EACJ;EACD,GAAI;aAEH,UACA;GACG;AAET;;;;;ACHD,MAAa,aAAa,WACxB,CACE,EACE,MACA,QAAQ,IACR,SAAS,IACT,OACA,UACA,kBACA,cACA,WACA,OACA,YACA,MACA,GAAG,OACG,EACR,QACG;CACH,MAAM,aAAa,OAAuB,KAAK;AAE/C,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,eAAW,SAAS,OAAO;GAC5B;GACD,OAAO;AACL,eAAW,SAAS,MAAM;GAC3B;EACF;CACF,GAAE,CAAE,EAAC;AAEN,wBACE,IAAC;EACC,WAAW,KAAK,gCAAgC,iBAAiB;EACjE,OAAO;GACL,GAAG;GACH,GAAG;EACJ;EACD,GAAI;YAEH,WACC,2BAGA,IAAC;GACC,KAAK;GACL,WAAW,KAAK,wBAAwB,UAAU;GAElD,UAAU;GACV,iBAAe;GACf,OAAO;IACA,WAAW;IAChB,OAAO,QAAQ;IACf,QAAQ,QAAQ;IAChB,GAAG;GACJ;IACI;GAEL;AAET,EACF;;;;AC3BD,MAAM,sBAAsB;CAC1B,MAAM;CACN,MAAM;CACN,SAAS;CACT,OAAO,CAAC,OAAO,CAAE;CACjB,UAAU,CAAC,OAAO,CAAE;AACrB;;;;;AASD,MAAa,QAAQ,WACnB,CACE,EACE,GAAG,IACH,GAAG,IACH,WACA,OACA,eAAe,MACf,WAAW,OACX,WAAW,OACX,UACA,aACA,WACA,eACA,WACA,SACA,QACA,SACA,GAAG,OACG,EACR,QACG;CACH,MAAM,IAAI,QAAQ,MAAM;AACtB,SAAO;GAAE,GAAG;GAAqB,GAAG;EAAI;CACzC,GAAE,CAAC,EAAG,EAAC;CACR,MAAM,IAAI,QAAQ,MAAM;AACtB,SAAO;GAAE,GAAG;GAAqB,GAAG;EAAI;CACzC,GAAE,CAAC,EAAG,EAAC;CAGR,MAAM,iBAAiB,OAAuB,KAAK;CACnD,MAAM,WAAW,OAA0B,KAAK;CAGhD,MAAM,KAAK,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;CACxD,MAAM,KAAK,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;CACxD,MAAM,WAAW,SAAS,EAAE,UAAU,IAAI,KAAK,MAAM,IAAI;CACzD,MAAM,WAAW,SAAS,EAAE,UAAU,IAAI,KAAK,MAAM,IAAI;CAEzD,IAAIC,YAAuB,CAAE;CAC7B,IAAIC,aAAyB,CAAE;AAC/B,KAAI,mBACF,OAAM,SAAS,QAAQ,UAAU,CAAC,UAAU;AAC1C,MAAI,MAAM,eAAe,MAAM,CAC7B,KAAI,MAAM,QAAQ,WAChB,cAAa,MAAM;WACV,MAAM,QAAQ,UACvB,aAAY,MAAM;MAElB,OAAM,IAAI,MAAM;MAGlB,OAAM,IAAI,MAAM;CAEnB,EAAC;CAIJ,MAAM,SAAS,YACb,CAACC,MAAYC,SAAe;AAC1B,OAAK,YAAY,SAAU;EAC3B,MAAM,KAAK,SAAS,EAAE,UAAU,IAAIC,OAAKA,MAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;EAClE,MAAM,KAAK,SAAS,EAAE,UAAU,IAAIC,OAAKA,MAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;EAClE,MAAM,OAAO,MAAM,UAAU,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI;EACvD,MAAM,OAAO,MAAM,UAAU,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI;AACvD,WAAS,MAAM,KAAK;CACrB,GACD;EACE;EACA;EACA,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;EACF,EAAE;CACH,EACF;CAED,MAAM,qBAAqB,YACzB,CACEC,WACAC,QACAC,QACG;EACH,IAAI;AACJ,MAAI,aAAa,cAAc;GAC7B,MAAM,IAAI,eACR,OAAO,OACP,OAAO,KACP,OAAO,KACP,OAAO,KACR;AACD,OAAI,SAAS,IAAIC,KAAG,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK;EACzD,MACC,KAAI,OAAO,QAAQA;AAErB,SAAO,MAAM,UAAU,GAAG,OAAO,KAAK,EAAE,OAAO,KAAK,OAAO,IAAI;CAChE,GACD,CAAE,EACH;CAED,MAAM,gBAAgB,YACpB,CAACC,UAA+C;AAC9C,OAAK,YAAY,SAAU;EAC3B,MAAM,MAAM,MAAM;AAClB,MAAI;GAAC;GAAc;GAAa;GAAW;EAAY,EAAC,SAAS,IAAI,EAAE;GACrE,MAAM,eAAe,OAAO,gBAAgB,OAAO;GACnD,MAAM,SAAS,eAAe,IAAI;AAClC,QAAK,OAAO,SAAU;AACtB,SAAM,gBAAgB;GACtB,IAAI,QAAQ,OAAO,SAAS;AAC5B,OAAI,OAAO,eAAe,OAAO,UAAW,UAAS;AACrD,OAAI,OAAO,QAAS,UAAS;GAC7B,MAAM,WAAW,mBAAmB,OAAO,SAAS,IAAI,QAAQ,MAAM;AACtE,OAAI,aACF,UAAS,UAAU,EAAE,MAAM;OAE3B,UAAS,EAAE,OAAO,SAAS;EAE9B;CACF,GACD;EAAC;EAAU;EAAU;EAAG;EAAG;CAAmB,EAC/C;CAGD,MAAM,CAAC,sBAAsB,mBAAmB,GAC9C,mBAAmC;EACjC,gBAAgB;EACR;EACR,aAAa,CAACN,MAAIC,SAAO;AACvB,OAAI,SAAU;AACd,OAAI,aAAc,cAAa;AAC/B,YAAS,SAAS,OAAO;GACzB,MAAM,SAAS,MACb,UAAU,SAASD,MAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EACrD,EAAE,KACF,EAAE,IACH;GACD,MAAM,SAAS,MACb,UAAU,SAASC,MAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EACrD,EAAE,KACF,EAAE,IACH;AACD,iBAAc,QAAQ,OAAO;EAC9B;EACD,WAAW,CAACD,MAAIC,SAAO;AACrB,OAAI,SAAU;AACd,OAAI,aAAc,iBAAgB;GAClC,MAAM,SAAS,MACb,UAAU,SAASD,MAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EACrD,EAAE,KACF,EAAE,IACH;GACD,MAAM,SAAS,MACb,UAAU,SAASC,MAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EACrD,EAAE,KACF,EAAE,IACH;AACD,eAAY,QAAQ,OAAO;EAC5B;CACF,EAAC;CAEJ,MAAM,mBAAmB,oBACvB,SACA,CAAC,UAAU;AACT,OAAK,YAAY,SAAU;EAC3B,MAAM,SAAS,MAAM,WAAW,IAAI;AACpC,OAAK,OAAO,MAAO;AACnB,QAAM,gBAAgB;EACtB,IAAI,QAAQ,OAAO,MAAM;AACzB,MAAI,MAAM,SAAS,EAAG,UAAS;AAC/B,MAAI,OAAO,QAAS,UAAS;EAC7B,MAAM,WAAW,mBAAmB,OAAO,MAAM,IAAI,QAAQ,MAAM;AACnE,MAAI,MAAM,SACR,UAAS,UAAU,EAAE,MAAM;MAE3B,UAAS,EAAE,OAAO,SAAS;CAE9B,GACD,EACE,SAAS,MACV,GACD;EAAC;EAAG;EAAG;EAAU;EAAU;CAAmB,EAC/C;AAED,qBAAoB,KAAK,MAAM;AAC7B,SAAO;GACL,QAAQ;AACN,aAAS,SAAS,OAAO;GAC1B;GACD,OAAO;AACL,aAAS,SAAS,MAAM;GACzB;EACF;CACF,GAAE,CAAE,EAAC;AAEN,wBAEE,IAAC;EACC,WAAW,KAAK,kBAAkB,UAAU;EAC5C,KAAK,CAAC,QAAQ;AACZ,oBAAiB,IAAI;AACrB,wBAAqB,IAAI;EAC1B;EACD,UAAU;EACV,iBAAe;EACf,iBAAe;EACf,OAAO;GACL,SAAS,OAAO,YAAY,YAAY,QAAQ,GAAG,CAAC;GACpD,QAAQ,WAAW,gBAAgB;GACnC,yBAAyB;GACzB,GAAG;EACJ;EACD,eAAe,CAAC,UAAU;AACxB,sBAAmB,MAAM;AACzB,mBAAgB,MAAM;EACvB;EACD,WAAW,CAAC,UAAU;AACpB,iBAAc,MAAM;AACpB,eAAY,MAAM;EACnB;EACD,SAAS,CAAC,UAAU;AAClB,YAAS,SAAS,OAAO;AACzB,aAAU,MAAM;EACjB;EACD,QAAQ,CAAC,UAAU;AACjB,YAAS,SAAS,MAAM;AACxB,YAAS,MAAM;EAChB;EACD,GAAI;4BAEJ,IAAC;GAAI,WAAU;GAA8B,KAAK;6BAChD,IAAC;IACC,yBACE,IAAC;KACC,KAAK;KACL,YAAY;KACZ,OAAO;MACL,MAAM,EAAE,SAAS;MACjB,OAAO,EAAE,SAAS;KACnB;KACD,GAAI;MACJ;IAEJ,GAAI;KACJ;IACE;GACF;AAET,EACF;;;;ACrVD,SAAgB,kBACd,WAAW,MAAM,CAAE,GACnBM,OAAuB,CAAE,GACzB;CACA,MAAM,WAAW,OAAO,GAAG;CAC3B,MAAM,OAAO,YAAY,MAAM;AAC7B,WAAS,UAAU,sBAAsB,KAAK;AAC9C,YAAU;CAEX,GAAE,CAAC,UAAU,GAAG,IAAK,EAAC;AAEvB,WAAU,MAAM;AACd,WAAS,UAAU,sBAAsB,KAAK;AAC9C,SAAO,MAAM,qBAAqB,SAAS,QAAQ;CACpD,GAAE,CAAC,IAAK,EAAC;AACX"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@tremolo-ui/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "React component library for audio app",
5
5
  "type": "module",
6
6
  "sideEffects": [
7
7
  "*.css"
8
8
  ],
9
- "main": "dist/cjs/index.js",
10
- "module": "dist/esm/index.js",
11
- "types": "dist/cjs/types/index.d.ts",
9
+ "main": "dist/index.cjs",
10
+ "module": "dist/index.js",
11
+ "types": "dist/index.d.cts",
12
12
  "scripts": {
13
13
  "sb": "storybook dev -p 6006",
14
14
  "typecheck": "tsc",
@@ -17,9 +17,9 @@
17
17
  "lint": "eslint --fix --ext .ts,.tsx .",
18
18
  "format": "prettier --write .",
19
19
  "test": "echo 'No test yet.'",
20
- "build:package": "tsc && rollup -c",
20
+ "build:package": "tsc && tsdown",
21
21
  "clean": "npm run clean:build && npm run clean:sb",
22
- "clean:build": "rimraf ./dist .rollup.cache",
22
+ "clean:build": "rimraf ./dist",
23
23
  "clean:sb": "rimraf ./storybook-static"
24
24
  },
25
25
  "devDependencies": {
@@ -36,8 +36,8 @@
36
36
  "@types/react-dom": "^19.0.4",
37
37
  "jest-environment-jsdom": "^29.7.0",
38
38
  "jotai": "^2.12.1",
39
- "react": "19.x",
40
- "react-dom": "19.x",
39
+ "react": "^19",
40
+ "react-dom": "^19",
41
41
  "storybook": "^8.6.7",
42
42
  "tone": "^15.0.4"
43
43
  },
@@ -46,7 +46,7 @@
46
46
  "react-dom": "^18 || ^19"
47
47
  },
48
48
  "dependencies": {
49
- "@tremolo-ui/functions": "0.0.12",
49
+ "@tremolo-ui/functions": "^0.1.3",
50
50
  "clsx": "^2.1.1",
51
51
  "zustand": "^5.0.3"
52
52
  },
@@ -78,14 +78,14 @@
78
78
  "exports": {
79
79
  ".": {
80
80
  "require": {
81
- "types": "./dist/cjs/types/index.d.ts",
82
- "default": "./dist/cjs/index.js"
81
+ "default": "./dist/index.cjs",
82
+ "types": "./dist/index.d.cts"
83
83
  },
84
84
  "import": {
85
- "types": "./dist/esm/types/index.d.ts",
86
- "default": "./dist/esm/index.js"
85
+ "default": "./dist/index.js",
86
+ "types": "./dist/index.d.ts"
87
87
  }
88
88
  },
89
- "./styles/index.css": "./dist/styles/index.css"
89
+ "./styles/index.css": "./dist/index.css"
90
90
  }
91
91
  }
@@ -1,9 +1,9 @@
1
1
  import { DependencyList, useCallback, useEffect, useRef } from 'react'
2
2
 
3
- export const useAnimationFrame = (
3
+ export function useAnimationFrame(
4
4
  callback = () => {},
5
5
  deps: DependencyList = [],
6
- ) => {
6
+ ) {
7
7
  const reqIdRef = useRef(-1)
8
8
  const loop = useCallback(() => {
9
9
  reqIdRef.current = requestAnimationFrame(loop)
@@ -3,7 +3,7 @@ import { useRef, useCallback } from 'react'
3
3
  import { useEventListener } from './useEventListener'
4
4
  import { useRefCallbackEvent } from './useRefCallbackEvent'
5
5
 
6
- interface Props {
6
+ export interface UseDragProps {
7
7
  threshold?: number
8
8
 
9
9
  onDrag: (x: number, y: number, deltaX: number, deltaY: number) => void
@@ -19,7 +19,7 @@ export function useDrag<T extends Element>({
19
19
  onDrag,
20
20
  onDragStart,
21
21
  onDragEnd,
22
- }: Props): [
22
+ }: UseDragProps): [
23
23
  (div: EventTarget | null) => void,
24
24
  (event: React.PointerEvent<T>) => void,
25
25
  ] {
@@ -5,7 +5,7 @@ import { normalizeValue } from '@tremolo-ui/functions'
5
5
  import { useEventListener } from './useEventListener'
6
6
  import { useRefCallbackEvent } from './useRefCallbackEvent'
7
7
 
8
- interface Props<T extends Element> {
8
+ export interface UseDragWithElementProps<T extends Element> {
9
9
  baseElementRef: RefObject<T | null>
10
10
  onDrag: (normalizedX: number, normalizedY: number) => void
11
11
  onDragStart?: (normalizedX: number, normalizedY: number) => void
@@ -20,7 +20,7 @@ export function useDragWithElement<T extends Element>({
20
20
  onDrag,
21
21
  onDragStart,
22
22
  onDragEnd,
23
- }: Props<T>): [
23
+ }: UseDragWithElementProps<T>): [
24
24
  (div: EventTarget | null) => void,
25
25
  (event: React.PointerEvent<T>) => void,
26
26
  ] {
package/src/index.ts CHANGED
@@ -5,19 +5,83 @@ import './components/Piano/index.css'
5
5
  import './components/Slider/index.css'
6
6
  import './components/XYPad/index.css'
7
7
 
8
- export * from './components/AnimationCanvas'
9
- export * from './components/AnimationKnob'
10
- export * from './components/DragObserver'
11
- export * from './components/Knob'
12
- export * from './components/NumberInput'
13
- export * from './components/Piano'
14
- export * from './components/Slider'
15
- export * from './components/WheelObserver'
16
- export * from './components/XYPad'
8
+ export {
9
+ type AbsoluteSizingProps,
10
+ AnimationCanvas,
11
+ type AnimationCanvasProps,
12
+ type CommonProps,
13
+ type DrawFunction,
14
+ type InitFunction,
15
+ type RelativeSizingProps,
16
+ } from './components/AnimationCanvas'
17
+ export {
18
+ AnimationKnob,
19
+ type AnimationKnobMethods,
20
+ type AnimationKnobProps,
21
+ } from './components/AnimationKnob'
22
+ export { DragObserver, type DragObserverProps } from './components/DragObserver'
23
+ export { Knob, type KnobMethods, type KnobProps } from './components/Knob'
24
+ export {
25
+ DecrementStepper,
26
+ type DecrementStepperProps,
27
+ IncrementStepper,
28
+ type IncrementStepperProps,
29
+ NumberInput,
30
+ type NumberInputMethods,
31
+ type NumberInputProps,
32
+ Stepper,
33
+ type StepperProps,
34
+ } from './components/NumberInput'
35
+ export {
36
+ BlackKey,
37
+ KeyLabel,
38
+ type KeyLabelProps,
39
+ type KeyMethods,
40
+ type KeyProps,
41
+ type KeyboardShortcuts,
42
+ Piano,
43
+ type PianoProps,
44
+ SHORTCUTS,
45
+ WhiteKey,
46
+ getNoteRangeArray,
47
+ } from './components/Piano'
48
+ export {
49
+ Scale,
50
+ ScaleOption,
51
+ type ScaleOptionProps,
52
+ type ScaleProps,
53
+ Slider,
54
+ type SliderMethods,
55
+ type SliderProps,
56
+ SliderThumb,
57
+ type SliderThumbMethods,
58
+ type SliderThumbProps,
59
+ SliderTrack,
60
+ type SliderTrackProps,
61
+ useSliderContext,
62
+ } from './components/Slider'
63
+ export {
64
+ WheelObserver,
65
+ type WheelObserverProps,
66
+ } from './components/WheelObserver'
67
+ export {
68
+ type AreaProps,
69
+ type ThumbProps,
70
+ type ValueOptions,
71
+ XYPad,
72
+ XYPadArea,
73
+ type XYPadMethods,
74
+ type XYPadProps,
75
+ XYPadThumb,
76
+ type XYPadThumbMethods,
77
+ } from './components/XYPad'
17
78
 
18
- export * from './hooks/useAnimationFrame'
19
- export * from './hooks/useDrag'
20
- export * from './hooks/useDragWithElement'
21
- export * from './hooks/useEventListener'
22
- export * from './hooks/useInterval'
23
- export * from './hooks/useLongPress'
79
+ export { useAnimationFrame } from './hooks/useAnimationFrame'
80
+ export { useDrag, type UseDragProps } from './hooks/useDrag'
81
+ export {
82
+ useDragWithElement,
83
+ type UseDragWithElementProps,
84
+ } from './hooks/useDragWithElement'
85
+ export { useEventListener } from './hooks/useEventListener'
86
+ export { useInterval } from './hooks/useInterval'
87
+ export { useLongPress } from './hooks/useLongPress'