@tremolo-ui/react 0.3.0 → 0.5.0

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 (64) hide show
  1. package/dist/index.cjs +1162 -1554
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +58 -93
  4. package/dist/index.d.cts +592 -278
  5. package/dist/index.d.cts.map +1 -1
  6. package/dist/index.d.ts +592 -278
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1163 -1555
  9. package/dist/index.js.map +1 -1
  10. package/package.json +12 -13
  11. package/src/components/AnimationCanvas/index.tsx +84 -155
  12. package/src/components/Knob/ActiveLine.tsx +6 -6
  13. package/src/components/Knob/InactiveLine.tsx +9 -11
  14. package/src/components/Knob/SVGRoot.tsx +9 -18
  15. package/src/components/Knob/context.tsx +57 -89
  16. package/src/components/Knob/index.css +6 -2
  17. package/src/components/Knob/index.tsx +95 -83
  18. package/src/components/NumberInput/DecrementStepper.tsx +17 -50
  19. package/src/components/NumberInput/IncrementStepper.tsx +17 -50
  20. package/src/components/NumberInput/InputField.tsx +123 -0
  21. package/src/components/NumberInput/Stepper.tsx +90 -12
  22. package/src/components/NumberInput/context.tsx +74 -146
  23. package/src/components/NumberInput/index.css +38 -102
  24. package/src/components/NumberInput/index.tsx +252 -98
  25. package/src/components/NumberInput/stepperButton.tsx +90 -0
  26. package/src/components/Piano/index.tsx +272 -288
  27. package/src/components/Piano/keyboardShortcuts.ts +34 -4
  28. package/src/components/PointsEditor/Background.tsx +8 -2
  29. package/src/components/PointsEditor/Container.tsx +19 -9
  30. package/src/components/PointsEditor/Point.tsx +117 -52
  31. package/src/components/PointsEditor/context.tsx +28 -74
  32. package/src/components/PointsEditor/index.css +5 -0
  33. package/src/components/PointsEditor/index.tsx +77 -43
  34. package/src/components/Slider/{Scale.tsx → Marks.tsx} +8 -8
  35. package/src/components/Slider/{ScaleOption.tsx → MarksOption.tsx} +16 -18
  36. package/src/components/Slider/Thumb.tsx +55 -68
  37. package/src/components/Slider/Track.tsx +15 -15
  38. package/src/components/Slider/context.tsx +36 -51
  39. package/src/components/Slider/index.css +18 -5
  40. package/src/components/Slider/index.tsx +136 -170
  41. package/src/components/Slider/type.ts +4 -4
  42. package/src/components/XYPad/Area.tsx +16 -7
  43. package/src/components/XYPad/Thumb.tsx +62 -74
  44. package/src/components/XYPad/context.tsx +46 -0
  45. package/src/components/XYPad/index.css +12 -0
  46. package/src/components/XYPad/index.tsx +193 -250
  47. package/src/hooks/useDrag.ts +41 -76
  48. package/src/hooks/useDragValue.ts +149 -0
  49. package/src/hooks/useEventListener.ts +1 -1
  50. package/src/hooks/useWheel.ts +51 -0
  51. package/src/index.ts +15 -13
  52. package/src/components/AnimationCanvas/canvas.ts +0 -46
  53. package/src/components/DragObserver/index.tsx +0 -58
  54. package/src/components/NumberInput/InternalInput.tsx +0 -221
  55. package/src/components/NumberInput/type.ts +0 -58
  56. package/src/components/Piano/KeyLabel.tsx +0 -51
  57. package/src/components/Piano/context.tsx +0 -73
  58. package/src/components/Piano/key.tsx +0 -205
  59. package/src/components/WheelObserver/index.tsx +0 -48
  60. package/src/components/_util/type.ts +0 -1
  61. package/src/hooks/useDragWithElement.ts +0 -72
  62. package/src/hooks/usePianoDrag.ts +0 -75
  63. package/src/hooks/useRefCallbackEvent.ts +0 -34
  64. /package/src/hooks/{useCallbackRef.ts → _internal/useCallbackRef.ts} +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Thumb","Thumb","defaultExternalStyles","Root","Root","Root","defaultExternalStyles","Root","Thumb","defaultExternalStyles","Root","Thumb"],"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/DragObserver/index.tsx","../src/components/_util/index.ts","../src/components/Knob/context.tsx","../src/components/Knob/ActiveLine.tsx","../src/components/Knob/InactiveLine.tsx","../src/components/Knob/Thumb.tsx","../src/components/Knob/SVGRoot.tsx","../src/components/Knob/index.tsx","../src/components/NumberInput/type.ts","../src/components/NumberInput/context.tsx","../src/hooks/useInterval.ts","../src/hooks/useLongPress.ts","../src/components/NumberInput/DecrementStepper.tsx","../src/components/NumberInput/IncrementStepper.tsx","../src/components/NumberInput/InternalInput.tsx","../src/components/NumberInput/Stepper.tsx","../src/components/NumberInput/index.tsx","../src/hooks/usePianoDrag.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/PointsEditor/Background.tsx","../src/components/PointsEditor/context.tsx","../src/components/PointsEditor/Container.tsx","../src/hooks/useDragWithElement.ts","../src/components/PointsEditor/Point.tsx","../src/components/PointsEditor/index.tsx","../src/components/Slider/context.tsx","../src/components/Slider/ScaleOption.tsx","../src/components/Slider/type.ts","../src/components/Slider/Scale.tsx","../src/components/Slider/Thumb.tsx","../src/components/Slider/Track.tsx","../src/components/Slider/index.tsx","../src/components/_util/composeRefs.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","../src/hooks/useMIDIAccess.ts","../src/hooks/useMIDIInput.ts","../src/hooks/useMIDIMessage.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\nexport function 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","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n ReactElement,\n RefObject,\n useCallback,\n useEffect,\n useRef,\n} from 'react'\n\nimport {\n DrawingContext,\n drawingState,\n DrawingStateValue,\n setDprConfig,\n} from './canvas'\n\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\nexport type DrawFunction = (\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\nexport interface CommonProps {\n draw: DrawFunction\n init?: InitFunction\n animate?: boolean\n /**\n * @see https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext#contextattributes\n */\n options?: CanvasRenderingContext2DSettings\n}\n\nexport interface AbsoluteSizingProps {\n width?: number\n height?: number\n}\n\nexport interface RelativeSizingProps {\n relativeSize?: boolean\n reduceFlickering?: boolean\n}\n\nexport type AnimationCanvasProps = CommonProps &\n AbsoluteSizingProps &\n RelativeSizingProps\n\n/**\n * A simple animatable canvas with requestAnimationFrame()\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 draw,\n init,\n animate = true,\n options,\n // absolute\n width: _width = 100,\n height: _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 if (animate) {\n reqIdRef.current = requestAnimationFrame(() =>\n loop(context, width, height, count + 1),\n )\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, animate],\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 const firstRendering = (width: number, height: number) => {\n setDprConfig(canvas, context, width, height, dpr)\n widthRef.current = width\n heightRef.current = height\n\n if (init) init(context, { width, height })\n const now = performance.now()\n deltaMemoRef.current = now\n startTimeRef.current = now\n loop(context, widthRef, heightRef, -1)\n }\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 const w = entry.contentRect.width\n const h = entry.contentRect.height\n const contextMemo = {} as DrawingContext\n if (reduceFlickering && memoCanvas && memoContext) {\n // Prevents loss of some context when the canvas is resized\n for (const prop of drawingState) {\n ;(contextMemo[prop] as DrawingStateValue) = context[prop]\n }\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 if (\n reduceFlickering &&\n memoContext &&\n memoCanvas &&\n memoCanvas.width > 0 &&\n memoCanvas.height > 0\n ) {\n for (const prop of drawingState) {\n ;(context[prop] as DrawingStateValue) = contextMemo[prop]\n }\n\n context.drawImage(memoContext.canvas, 0, 0)\n }\n\n if (!animate) {\n // re rendering\n loop(context, widthRef, heightRef, -1)\n }\n }\n })\n ro.observe(parent)\n\n const width = parent.clientWidth\n const height = parent.clientHeight\n firstRendering(width, height)\n\n return () => {\n if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current)\n ro.disconnect()\n }\n } else {\n const { width, height } = canvas.getBoundingClientRect()\n firstRendering(width, height)\n\n return () => {\n if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current)\n }\n }\n }, [loop, init, options, reduceFlickering, relativeSize, animate])\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 { DependencyList, useCallback, useInsertionEffect, useRef } from 'react'\n\n/**\n * Internal\n * @private\n */\nexport function useCallbackRef<Args extends unknown[], Return>(\n callback: ((...args: Args) => Return) | undefined,\n deps: 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,\n options?: Options,\n) {\n const listener = useCallbackRef(handler)\n\n useEffect(() => {\n const node = typeof target === 'function' ? target() : (target ?? document)\n\n if (!node) return\n\n node.addEventListener(event, listener, options)\n return () => {\n node.removeEventListener(event, listener, options)\n }\n }, [event, target, options, listener])\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\n/**\n * Internal\n * @private\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\ninterface 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: _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 threshold = Math.max(_threshold, 1)\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 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 const refHandler = useRefCallbackEvent(\n 'touchmove',\n handleDrag,\n { passive: false },\n [onDrag],\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","import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react'\n\nimport { useDrag } from '../../hooks/useDrag'\nimport { Override } from '../_util/type'\n\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\nexport function DragObserver<T extends ElementType = 'div'>(\n props: Override<DragObserverProps<T>, ComponentPropsWithoutRef<T>>,\n) {\n const {\n as: Component = 'div',\n threshold = 1,\n onDrag,\n onDragStart,\n onDragEnd,\n children,\n onPointerDown,\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={(e) => {\n pointerDownHandler(e)\n onPointerDown?.(e)\n }}\n {...attributes}\n >\n {children}\n </Component>\n )\n}\n","export function addUserSelectNone() {\n window.document.body.classList.add('tremolo-user-select-none')\n}\n\nexport function removeUserSelectNone() {\n window.document.body.classList.remove('tremolo-user-select-none')\n}\n\nconst cursorStyles = {\n grabbing: 'tremolo-cursor-grabbing',\n grab: 'tremolo-cursor-grab',\n pointer: 'tremolo-cursor-pointer',\n move: 'tremolo-cursor-move',\n none: 'tremolo-cursor-none',\n}\n\nexport type Cursor = keyof typeof cursorStyles\n\nexport function setCursorStyle(type: Cursor) {\n resetCursorStyle()\n window.document.body.classList.add(cursorStyles[type])\n}\n\nexport function resetCursorStyle() {\n Object.values(cursorStyles).forEach((s) => {\n window.document.body.classList.remove(s)\n })\n}\n","import {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useRef,\n} from 'react'\nimport { createStore, useStore } from 'zustand'\n\nimport { normalizeValue, radian } from '@tremolo-ui/functions'\n\nexport const viewBoxSize = 100\nexport const center = viewBoxSize / 2\n\ntype State = {\n value: number\n min: number\n max: number\n step: number\n skew: number // | SkewFunction // TODO\n startValue: number\n angleRange: number\n}\n\ntype DrawingState = {\n p: number // normalized value\n r1: number // ロータリー開始位置\n r2: number // activeLineの開始位置\n r3: number // activeLineの終了位置\n r4: number // ロータリー終了位置\n x1: number\n y1: number\n x2: number\n y2: number\n x3: number\n y3: number\n x4: number\n y4: number\n}\n\nfunction calcDrawingState({\n value,\n min,\n max,\n skew,\n startValue,\n angleRange,\n}: State) {\n const p = normalizeValue(value, min, max, skew)\n const s = normalizeValue(startValue, min, max, skew)\n\n const r1 = -angleRange / 2\n const r2 = r1 + Math.min(p, s) * angleRange\n const r3 = r1 + Math.max(p, s) * angleRange\n const r4 = angleRange / 2\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 p,\n r1,\n r2,\n r3,\n r4,\n x1,\n y1,\n x2,\n y2,\n x3,\n y3,\n x4,\n y4,\n }\n}\n\ntype KnobStore = ReturnType<typeof createKnobStore>\n\nconst createKnobStore = (initProps: State) => {\n return createStore<State & DrawingState>()(() => ({\n ...initProps,\n ...calcDrawingState(initProps),\n }))\n}\n\nconst KnobContext = createContext<KnobStore | null>(null)\n\nexport function KnobProvider({ children, ...props }: PropsWithChildren<State>) {\n const storeRef = useRef<KnobStore>(null)\n if (!storeRef.current) {\n storeRef.current = createKnobStore(props)\n }\n\n useEffect(() => {\n if (storeRef.current) {\n storeRef.current.setState({ ...props, ...calcDrawingState(props) })\n } else {\n storeRef.current = createKnobStore(props)\n }\n }, [props])\n\n return (\n <KnobContext.Provider value={storeRef.current}>\n {children}\n </KnobContext.Provider>\n )\n}\n\nexport function useKnobContext<T>(\n selector: (state: State & DrawingState) => T,\n): T {\n const store = useContext(KnobContext)\n if (!store) throw new Error('Missing KnobContext.Provider in the tree')\n return useStore(store, selector)\n}\n","import clsx from 'clsx'\nimport { SVGProps } from 'react'\n\nimport { center, useKnobContext } from './context'\n\nexport function ActiveLine({\n stroke = 'currentColor',\n strokeWidth = 6,\n className,\n ...props\n}: Omit<SVGProps<SVGPathElement>, 'd'>) {\n const r2 = useKnobContext((s) => s.r2)\n const r3 = useKnobContext((s) => s.r3)\n const x2 = useKnobContext((s) => s.x2)\n const y2 = useKnobContext((s) => s.y2)\n const x3 = useKnobContext((s) => s.x3)\n const y3 = useKnobContext((s) => s.y3)\n\n return (\n <path\n className={clsx('tremolo-knob-active-line', className)}\n d={`M ${x2} ${y2} A ${center} ${center} -135 ${r3 - r2 > 180 ? 1 : 0} 1 ${x3} ${y3}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n {...props}\n />\n )\n}\n","import clsx from 'clsx'\nimport { SVGProps } from 'react'\n\nimport { center, useKnobContext } from './context'\n\nexport function InactiveLine({\n stroke = 'currentColor',\n strokeWidth = 6,\n className,\n ...props\n}: Omit<SVGProps<SVGPathElement>, 'd'>) {\n const min = useKnobContext((s) => s.min)\n const max = useKnobContext((s) => s.max)\n const startValue = useKnobContext((s) => s.startValue)\n\n const r1 = useKnobContext((s) => s.r1)\n const r2 = useKnobContext((s) => s.r2)\n const r3 = useKnobContext((s) => s.r3)\n const r4 = useKnobContext((s) => s.r4)\n const x1 = useKnobContext((s) => s.x1)\n const y1 = useKnobContext((s) => s.y1)\n const x2 = useKnobContext((s) => s.x2)\n const y2 = useKnobContext((s) => s.y2)\n const x3 = useKnobContext((s) => s.x3)\n const y3 = useKnobContext((s) => s.y3)\n const x4 = useKnobContext((s) => s.x4)\n const y4 = useKnobContext((s) => s.y4)\n\n return (\n <>\n {startValue > min && (\n <path\n className={clsx('tremolo-knob-inactive-line', className)}\n d={`M ${x1} ${y1} A ${center} ${center} -135 ${r2 - r1 > 180 ? 1 : 0} 1 ${x2} ${y2}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n {...props}\n />\n )}\n {startValue < max && (\n <path\n className={clsx('tremolo-knob-inactive-line', className)}\n d={`M ${x3} ${y3} A ${center} ${center} -135 ${r4 - r3 > 180 ? 1 : 0} 1 ${x4} ${y4}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n {...props}\n />\n )}\n </>\n )\n}\n","import clsx from 'clsx'\nimport { SVGProps } from 'react'\n\nimport { clamp } from '@tremolo-ui/functions'\n\nimport { useKnobContext, viewBoxSize } from './context'\n\ninterface Props {\n /** color */\n thumb?: string\n /** color */\n thumbLine?: string\n /** percent (0-100) */\n thumbSize?: number\n /** percent (0-100) */\n thumbLineWeight?: number\n /** percent (0-100) */\n thumbLineLength?: number\n\n classes?: {\n thumb?: string\n thumbLine?: string\n }\n}\n\nexport function Thumb({\n className,\n\n thumb = 'currentColor',\n thumbLine = 'currentColor',\n thumbSize = 84,\n thumbLineWeight = 6,\n thumbLineLength = 35,\n classes,\n\n ...props\n}: Props & Omit<SVGProps<SVGSVGElement>, 'd' | keyof Props>) {\n const angleRange = useKnobContext((s) => s.angleRange)\n\n const p = useKnobContext((s) => s.p)\n const r1 = useKnobContext((s) => s.r1)\n\n return (\n <svg className={clsx('tremolo-knob-thumb', classes?.thumb)} {...props}>\n <circle cx=\"50%\" cy=\"50%\" r={`${thumbSize / 2}%`} fill={thumb} />\n <line\n className={clsx('tremolo-knob-thumb-line', classes?.thumbLine)}\n x1=\"50%\"\n y1={`${(viewBoxSize - clamp(thumbSize, 0, 100)) / 2}%`}\n x2=\"50%\"\n y2={`${thumbLineLength}%`}\n stroke={thumbLine}\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(${r1 + p * angleRange}deg)`,\n transformOrigin: '50% 50%',\n }}\n />\n </svg>\n )\n}\n","import { SVGProps } from 'react'\n\nimport { Override } from '../_util/type'\n\nimport { ActiveLine } from './ActiveLine'\nimport { viewBoxSize } from './context'\nimport { InactiveLine } from './InactiveLine'\nimport { Thumb } from './Thumb'\n\ninterface SVGRoot {\n block?: boolean\n overflowVisible?: boolean\n}\n\nexport function SVGRoot({\n children,\n style,\n ...props\n}: Override<SVGRoot, SVGProps<SVGSVGElement>>) {\n return (\n <svg\n viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}\n style={{\n display: 'block',\n overflow: 'visible',\n ...style,\n }}\n {...props}\n >\n {children || (\n <>\n <InactiveLine />\n <ActiveLine />\n <Thumb />\n </>\n )}\n </svg>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n useCallback,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react'\n\nimport {\n clamp,\n InputEventOption,\n normalizeValue,\n rawValue,\n stepValue,\n} from '@tremolo-ui/functions'\n\nimport { useDrag } from '../../hooks/useDrag'\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\nimport {\n addUserSelectNone,\n Cursor,\n removeUserSelectNone,\n resetCursorStyle,\n setCursorStyle,\n} from '../_util'\n\nimport { ActiveLine } from './ActiveLine'\nimport { KnobProvider } from './context'\nimport { InactiveLine } from './InactiveLine'\nimport { SVGRoot } from './SVGRoot'\nimport { Thumb } from './Thumb'\n\nconst defaultExternalStyles: KnobProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'grabbing',\n}\n\nexport interface KnobProps {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n skew?: number // | SkewFunction // TODO\n /**\n * value set when double-clicking\n * restriction: enableDoubleClickDefault = true\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 /** width and height */\n size?: number | string\n\n /**\n * Global style to apply when dragged\n * @default defaultExternalStyles\n */\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n /**\n * wheel control option\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n enableDoubleClickDefault?: boolean\n\n disabled?: boolean\n readonly?: boolean\n\n /** angle range [degree] */\n angleRange?: number\n\n onChange?: (value: number) => void\n}\n\nexport interface KnobMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = KnobProps & Omit<ComponentPropsWithoutRef<'div'>, keyof KnobProps>\n\nconst Root = 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,\n externalStyles: _externalStyles,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n enableDoubleClickDefault = true,\n disabled = false,\n readonly = false,\n angleRange = 270,\n onChange,\n onKeyDown,\n onPointerDown,\n onDoubleClick,\n className,\n style,\n children,\n ...props\n }: Props,\n forwardedRef,\n ) => {\n const [dragging, setDragging] = useState(false)\n const valueRef = useRef(0)\n const elmRef = useRef<HTMLElement | SVGElement>(null)\n\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\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 clamped = clamp(stepValue(v, step), min, max)\n onChange(clamped)\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<\n HTMLElement | SVGElement\n >({\n onDrag: onDrag,\n onDragStart: () => {\n setDragging(true)\n valueRef.current = normalizeValue(value, min, max, skew)\n if (externalStyles.userSelectNone) addUserSelectNone()\n if (externalStyles.cursor) setCursorStyle(externalStyles.cursor)\n },\n onDragEnd: () => {\n setDragging(false)\n if (externalStyles.userSelectNone) removeUserSelectNone()\n if (externalStyles.cursor) resetCursorStyle()\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(forwardedRef, () => {\n return {\n focus() {\n elmRef.current?.focus()\n },\n blur() {\n elmRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <KnobProvider\n value={value}\n min={min}\n max={max}\n step={step}\n skew={skew}\n startValue={startValue}\n angleRange={angleRange}\n >\n <div\n ref={(elm) => {\n elmRef.current = elm\n wheelRefCallback(elm)\n touchMoveRefCallback(elm)\n }}\n className={clsx('tremolo-knob', className)}\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 data-dragging={dragging}\n style={{\n width: size,\n height: size,\n ...style,\n }}\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 {children || <SVGRoot />}\n </div>\n </KnobProvider>\n )\n },\n)\n\n/**\n * Interactive rotary knob component implemented in SVG.\n */\nexport const Knob = {\n Root,\n SVGRoot,\n InactiveLine,\n ActiveLine,\n Thumb,\n}\n\nexport { useKnobContext } from './context'\n","/**\n * [unit, scale][]\n * @example\n * [['Hz', 1], ['kHz', 1000]]\n */\nexport type Units = [string, number][]\n\nexport function selectUnit(units: Units, value: number): [string, number] {\n let i = 0\n for (; i < units.length; i++) {\n if (Math.abs(units[i][1]) > Math.abs(value)) break\n }\n return units[Math.max(0, i - 1)]\n}\n\nexport function parseValue(\n inputString: string,\n units?: string | Units,\n digit?: number,\n): {\n rawValue: number\n formatValue: string\n unit: string\n} {\n const str = inputString.trim()\n if (!units || typeof units == 'string') {\n const m = str.match(/-?\\d+(\\.\\d+)?/)\n let v = Number(m?.[0] ?? '0')\n v = isNaN(v) ? 0 : v\n return {\n rawValue: v,\n formatValue: (digit != undefined ? v.toFixed(digit) : v) + (units ?? ''),\n unit: units ?? '',\n }\n }\n\n const unitList = units.map(([u, _s]) => u)\n const scaleList = units.map(([_u, s]) => s)\n let rawValue = 0\n let unit = unitList[0]\n let formatValue =\n (digit != undefined ? rawValue.toFixed(digit) : rawValue) + unit\n const m = str.match(/^(-?\\d+(\\.\\d+)?)\\s*(\\w*)$/)\n if (m) {\n rawValue = Number(m[1]) || 0\n const uIndex = unitList.indexOf(m[3])\n rawValue *= uIndex != -1 ? scaleList[uIndex] : 1\n const [u, scale] = selectUnit(units, rawValue)\n const v = rawValue / scale\n formatValue = (digit != undefined ? v.toFixed(digit) : v) + u\n unit = u\n }\n return {\n rawValue: rawValue,\n formatValue: formatValue,\n unit: unit,\n }\n}\n","import { createContext, useContext, useEffect, useRef } from 'react'\nimport { createStore, useStore } from 'zustand'\n\nimport { clamp } from '@tremolo-ui/functions'\n\nimport { parseValue, Units } from './type'\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\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 { 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\nexport interface DecrementStepperProps {\n size?: number\n children?: ReactNode\n}\n\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, ReactNode } from 'react'\n\nimport { useLongPress } from '../../hooks/useLongPress'\n\nimport { useNumberInputContext } from './context'\n\nexport interface IncrementStepperProps {\n size?: number\n children?: ReactNode\n}\n\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 {\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'\n\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\n\nimport { safeClamp, useNumberInputContext } from './context'\nimport { parseValue } from './type'\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(\n '[NumberInput] \"min\" and \"max\" are required when InputEventOption[0] is set to \"normalized\".',\n )\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\nexport interface StepperProps {\n /** Display only when hovering. */\n dynamic?: boolean\n children?: ReactNode\n}\n\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 clsx from 'clsx'\nimport { ComponentPropsWithoutRef, forwardRef, ReactNode } from 'react'\n\nimport { InputEventOption } from '@tremolo-ui/functions'\n\nimport { NumberInputProvider } from './context'\nimport { DecrementStepper } from './DecrementStepper'\nimport { IncrementStepper } from './IncrementStepper'\nimport { InternalInput } from './InternalInput'\nimport { Stepper } from './Stepper'\nimport { Units } from './type'\n\n/*\nTODO\n- numberMode: focusが当たった時だけ、parse + type=\"number\"にする\n- skew\n*/\n\nexport interface NumberInputProps {\n value: number | string\n\n /**\n * Number.MIN_SAFE_INTEGER\n */\n min?: number\n /**\n * 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 /**\n * wheel control option\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\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\nexport interface NumberInputMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = NumberInputProps &\n Omit<ComponentPropsWithoutRef<'input'>, keyof NumberInputProps | 'type'>\n\nconst Root = 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 forwardedRef,\n ) => {\n const colors: Record<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={forwardedRef}\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\n/**\n * Input with some useful functions for entering numerical values.\n */\nexport const NumberInput = {\n Root,\n Stepper,\n IncrementStepper,\n DecrementStepper,\n}\n\nexport { type StepperProps } from './Stepper'\nexport { type IncrementStepperProps } from './IncrementStepper'\nexport { type DecrementStepperProps } from './DecrementStepper'\nexport { type Units } from './type'\n","import { useRef, useCallback, RefObject } from 'react'\n\nimport { normalizeValue } from '@tremolo-ui/functions'\n\nimport { useEventListener } from './useEventListener'\nimport { useRefCallbackEvent } from './useRefCallbackEvent'\n\ninterface UsePianoDrag<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 * Internal\n * @returns [refCallback, pointerDownHandler]\n * @private\n */\nexport function usePianoDrag<T extends Element>({\n baseElementRef,\n onDrag,\n onDragStart,\n onDragEnd,\n}: UsePianoDrag<T>) {\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\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, velocity?: 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\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\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\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\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\nexport interface KeyMethods {\n play: (velocity?: number) => void\n stop: () => void\n played: () => boolean\n}\n\ntype Props = KeyProps & Omit<ComponentPropsWithoutRef<'div'>, keyof KeyProps>\ntype ImplProps = Props & { keyType: 'black' | 'white' }\n\nexport const defaultWhiteKeyWidth = 40\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(velocity) {\n if (disabled) return\n setPlayed(true)\n if (onPlayNote) onPlayNote(noteNumber, velocity)\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\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\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","export type KeyboardShortcuts = {\n keys: string[]\n // TODO\n flags?: {\n naturalOnly?: boolean\n }\n}\n\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 forwardRef,\n ReactElement,\n ReactNode,\n RefObject,\n useCallback,\n useEffect,\n useImperativeHandle,\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 { useEventListener } from '../../hooks/useEventListener'\nimport { usePianoDrag } from '../../hooks/usePianoDrag'\n\nimport { NoteRange, PianoProvider } from './context'\nimport {\n BlackKey,\n defaultBlackKeyWidth,\n defaultWhiteKeyWidth,\n KeyMethods,\n WhiteKey,\n} from './key'\nimport { KeyboardShortcuts } from './keyboardShortcuts'\nimport { KeyLabel } from './KeyLabel'\n\n/**\n * [noteRange.first, noteRange.first + 1 ..., noteRange.last]\n */\nexport function getNoteRangeArray(noteRange: NoteRange) {\n return Array.from(\n { length: noteRange.last - noteRange.first + 1 },\n (_, i) => i + noteRange.first,\n )\n}\n\nexport interface PianoProps {\n noteRange: NoteRange\n\n glissando?: boolean\n midiMax?: number\n keyboardShortcuts?: KeyboardShortcuts\n fill?: boolean\n whiteNoteWidth?: number\n blackNoteWidth?: number\n height?: number | string\n style?: CSSProperties\n\n onPlayNote?: (note: number, velocity?: number) => void\n onStopNote?: (note: 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\nexport interface PianoMethods {\n playNote: (note: number, velocity?: number) => void\n stopNote: (note: number) => void\n}\n\ntype Props = PianoProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof PianoProps>\n\nconst Root = forwardRef<PianoMethods, Props>(\n (\n {\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 },\n forwardedRef,\n ) => {\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)\n ? 1\n : 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 // FIXME\n const { refHandler: touchMoveRefCallback, pointerDownHandler } =\n usePianoDrag<HTMLDivElement>({\n baseElementRef: pianoRef,\n onDrag: onDrag,\n // onDragStart: 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 useImperativeHandle(forwardedRef, () => {\n return {\n playNote(note, velocity) {\n const index = noteRangeArray.indexOf(note)\n if (index != -1) {\n if (!keyRefs.current[index]?.current?.played()) {\n keyRefs.current[index]?.current?.play(velocity)\n }\n } else {\n onPlayNote?.(note, velocity)\n }\n },\n stopNote(note: number) {\n const index = noteRangeArray.indexOf(note)\n if (index != -1) {\n keyRefs.current[index]?.current?.stop()\n } else {\n onStopNote?.(note)\n }\n },\n }\n }, [noteRangeArray, onPlayNote, onStopNote])\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)\n\n/**\n * Customizable piano component.\n */\nexport const Piano = { Root, WhiteKey, BlackKey, KeyLabel }\n\nexport { type KeyboardShortcuts, SHORTCUTS } from './keyboardShortcuts'\nexport { type KeyProps, type KeyMethods } from './key'\nexport { type KeyLabelProps } from './KeyLabel'\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef } from 'react'\n\nexport function Background({\n className,\n children,\n ...props\n}: ComponentPropsWithoutRef<'div'>) {\n return (\n <div\n className={clsx('tremolo-points-editor-background', className)}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import {\n createContext,\n createRef,\n RefObject,\n useContext,\n useEffect,\n useRef,\n} from 'react'\nimport { createStore, useStore } from 'zustand'\n\nimport { Cursor } from '../_util'\n\ntype State = {\n containerElementRef: RefObject<HTMLDivElement | null>\n disabled: boolean\n readonly: boolean\n externalStyles: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n}\n\ntype Action = {\n setContainerElementRef: (\n containerElementRef: RefObject<HTMLDivElement | null>,\n ) => void\n}\n\ntype PointsEditorStore = ReturnType<typeof createPointsEditorStore>\n\nconst createPointsEditorStore = (initProps: Partial<State & Action>) => {\n // const noteRange = initProps.noteRange || { first: 0, last: 127 }\n const DEFAULT_PROPS: State = {\n containerElementRef: createRef(),\n disabled: false,\n readonly: false,\n externalStyles: {\n userSelectNone: true,\n cursor: 'grabbing',\n },\n }\n\n return createStore<State & Action>()((set) => ({\n ...DEFAULT_PROPS,\n ...initProps,\n setContainerElementRef: (containerElementRef) => {\n set(() => ({\n containerElementRef,\n }))\n },\n }))\n}\n\nconst PointsEditorContext = createContext<PointsEditorStore | null>(null)\n\ntype PointsEditorProviderProps = React.PropsWithChildren<\n Partial<State & Action>\n>\n\nexport function PointsEditorProvider({\n children,\n ...props\n}: PointsEditorProviderProps) {\n const storeRef = useRef<PointsEditorStore>(null)\n if (!storeRef.current) {\n storeRef.current = createPointsEditorStore(props)\n }\n\n useEffect(() => {\n if (storeRef.current) {\n storeRef.current.setState(props)\n } else {\n storeRef.current = createPointsEditorStore(props)\n }\n }, [props])\n\n return (\n <PointsEditorContext.Provider value={storeRef.current}>\n {children}\n </PointsEditorContext.Provider>\n )\n}\n\nexport function usePointsEditorContext<T>(\n selector: (state: State & Action) => T,\n): T {\n const store = useContext(PointsEditorContext)\n if (!store)\n throw new Error('Missing PointsEditorContext.Provider in the tree')\n return useStore(store, selector)\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, useRef } from 'react'\n\nimport { usePointsEditorContext } from './context'\n\nexport function Container({\n className,\n children,\n ...props\n}: ComponentPropsWithoutRef<'div'>) {\n const containerElementRef = useRef<HTMLDivElement>(null)\n const setContainerElementRef = usePointsEditorContext(\n (s) => s.setContainerElementRef,\n )\n setContainerElementRef(containerElementRef)\n\n return (\n <div\n ref={containerElementRef}\n className={clsx('tremolo-points-editor-container', className)}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import { useRef, useCallback, RefObject, useState } from 'react'\n\nimport { normalizeValue } from '@tremolo-ui/functions'\n\nimport { useEventListener } from './useEventListener'\nimport { useRefCallbackEvent } from './useRefCallbackEvent'\n\ninterface UseDragWithElement<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\nexport function useDragWithElement<T extends Element>({\n baseElementRef,\n onDrag,\n onDragStart,\n onDragEnd,\n}: UseDragWithElement<T>) {\n const [dragging, setDragging] = useState(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 || !dragging) {\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, dragging],\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 // dragging.current = true\n setDragging(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 (!dragging) return\n // dragging.current = false\n setDragging(false)\n onDragEnd?.(normalizedX.current, normalizedY.current)\n })\n\n return { refHandler, pointerDownHandler, dragging }\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef } from 'react'\n\nimport { clamp } from '@tremolo-ui/functions'\n\nimport { useDragWithElement } from '../../hooks/useDragWithElement'\nimport {\n addUserSelectNone,\n removeUserSelectNone,\n resetCursorStyle,\n setCursorStyle,\n} from '../_util'\n\nimport { usePointsEditorContext } from './context'\n\nexport type PointBaseType = { x: number; y: number }\n\nexport function clampPoint(\n point: PointBaseType,\n min?: Partial<PointBaseType>,\n max?: Partial<PointBaseType>,\n) {\n const { x, y } = point\n const newX = clamp(x, min?.x ?? 0, max?.x ?? 1)\n const newY = clamp(y, min?.y ?? 0, max?.y ?? 1)\n return { x: newX, y: newY }\n}\n\nexport interface PointProps<T extends PointBaseType> {\n value: T\n min?: Partial<PointBaseType>\n max?: Partial<PointBaseType>\n\n size?: number | string\n width?: number | string\n height?: number | string\n color?: string\n\n disabled?: boolean\n readonly?: boolean\n\n onChange?: (value: PointBaseType) => void\n onDragStart?: (value: PointBaseType) => void\n onDragEnd?: (value: PointBaseType) => void\n}\n\nexport function Point<T extends PointBaseType>({\n value,\n min,\n max,\n size,\n width = 16,\n height = 16,\n color,\n\n disabled,\n readonly,\n\n onChange,\n onDragStart,\n onDragEnd,\n\n className,\n style,\n onPointerDown,\n ...props\n}: PointProps<T> & Omit<ComponentPropsWithoutRef<'div'>, keyof PointProps<T>>) {\n const containerElementRef = usePointsEditorContext(\n (s) => s.containerElementRef,\n )\n const externalStyles = usePointsEditorContext((s) => s.externalStyles)\n const __disabled = usePointsEditorContext((s) => s.disabled)\n const __readonly = usePointsEditorContext((s) => s.readonly)\n\n // console.log(value.x, value.y)\n\n // Piano: 値が更新されることで、イベントハンドラがリセットされる\n\n const {\n refHandler: touchMoveRefCallback,\n pointerDownHandler,\n dragging,\n } = useDragWithElement<HTMLDivElement>({\n baseElementRef: containerElementRef,\n onDrag: (x, y) => {\n if (readonly) return\n\n onChange?.(clampPoint({ x, y }, min, max))\n },\n onDragStart: (x, y) => {\n if (readonly) return\n if (externalStyles.userSelectNone) addUserSelectNone()\n if (externalStyles.cursor) setCursorStyle(externalStyles.cursor)\n\n onDragStart?.(clampPoint({ x, y }, min, max))\n },\n onDragEnd: (x, y) => {\n if (readonly) return\n if (externalStyles.userSelectNone) removeUserSelectNone()\n if (externalStyles.cursor) resetCursorStyle()\n\n onDragEnd?.(clampPoint({ x, y }, min, max))\n },\n })\n\n const colors: Record<string, string | undefined> = {\n '--color': color,\n }\n\n return (\n <div\n ref={(div) => {\n // wheelRefCallback(div)\n touchMoveRefCallback(div)\n }}\n className={clsx('tremolo-points-editor-point', className)}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n aria-disabled={disabled != undefined ? disabled : __disabled}\n aria-readonly={readonly != undefined ? readonly : __readonly}\n data-dragging={dragging}\n style={{\n ...colors,\n width: size ?? width,\n height: size ?? height,\n left: `${value.x * 100}%`,\n top: `${value.y * 100}%`,\n ...style,\n }}\n onPointerDown={(event) => {\n pointerDownHandler(event)\n onPointerDown?.(event)\n }}\n {...props}\n />\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, forwardRef } from 'react'\n\nimport { InputEventOption } from '@tremolo-ui/functions'\n\nimport { Cursor } from '../_util'\n\nimport { Background } from './Background'\nimport { Container } from './Container'\nimport { PointsEditorProvider } from './context'\nimport { Point, PointBaseType } from './Point'\n\n/*\nTODO:\n\n- 複数選択\n- modifier\n*/\n\n/*\nimport { useState } from 'react'\n\nexport default function App() {\n const [points, setPoints] = useState(initialPoints)\n\n return (\n <PointsEditor.Root\n onDoubleClick={({ x, y }, _e) => {\n const newPoints = [...points, { x, y }]\n setPoints(newPoints)\n }}\n >\n {points.map((point) => (\n <PointsEditor.Point key={`${point.x}, ${point.y}`} value={point} />\n ))}\n </PointsEditor.Root>\n )\n}\n*/\n\nconst defaultExternalStyles: PointsEditorProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'grabbing',\n}\n\nexport interface PointsEditorProps {\n width?: number | string\n height?: number | string\n\n // TODO\n grid?: number | PointBaseType\n // modifier?:\n\n disabled?: boolean\n readonly?: boolean\n\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n\n // TODO\n /**\n * wheel control option\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n}\n\ntype Props = PointsEditorProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorProps>\n\nconst Root = forwardRef<HTMLDivElement, Props>(\n (\n {\n width = 200,\n height = 100,\n disabled = false,\n readonly = false,\n externalStyles: _externalStyles,\n style,\n className,\n children,\n ...props\n },\n forwardedRef,\n ) => {\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\n\n return (\n <PointsEditorProvider\n disabled={disabled}\n readonly={readonly}\n externalStyles={externalStyles}\n >\n <div\n ref={forwardedRef}\n className={clsx('tremolo-points-editor', className)}\n style={{\n width,\n height,\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n </PointsEditorProvider>\n )\n },\n)\n\n/**\n * Multiple Point Controller\n */\nexport const PointsEditor = {\n Root,\n Background,\n Container,\n Point,\n}\n\nexport { usePointsEditorContext } from './context'\nexport { clampPoint, type PointBaseType, type PointProps } from './Point'\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\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'\n\nimport { useSliderContext } from './context'\nimport { ScaleType } from './type'\n\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\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 { decimalPart, toFixed } from '@tremolo-ui/functions'\n\nexport type ScaleType = 'mark' | 'mark-number' | 'number'\nexport type ScaleOptions = ['step', ScaleType] | [number, ScaleType]\n\nexport function generateOptionsList(\n options: ScaleOptions,\n min: number,\n max: number,\n step: number,\n) {\n const optionsList: {\n value: number\n type: ScaleType\n }[] = []\n const per = options[0] == 'step' ? step : options[0]\n const count = Math.floor(max / per) - Math.ceil(min / per) + 1\n for (let i = 0; i < count; i++) {\n const value = toFixed(\n per * (Math.ceil(min / per) + i),\n decimalPart(per)?.length,\n )\n optionsList.push({ value: value, type: options[1] })\n }\n return optionsList\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport { xor } from '@tremolo-ui/functions'\n\nimport { useSliderContext } from './context'\nimport { ScaleOption } from './ScaleOption'\nimport { generateOptionsList, ScaleOptions } from './type'\n\nexport interface ScaleProps {\n gap?: number | string\n options?: ScaleOptions\n children?: ReactNode\n}\n\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\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\nexport interface SliderThumbMethods {\n focus: () => void\n blur: () => void\n}\n\nexport const defaultThumbSize = 22\n\nexport const Thumb = 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\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\nexport function Track({\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) ${__percent}%, var(--active) ${__percent}%)`\n : `linear-gradient(to ${direction}, var(--active) ${__percent}%, var(--inactive) ${__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 {\n addUserSelectNone,\n Cursor,\n removeUserSelectNone,\n resetCursorStyle,\n setCursorStyle,\n} from '../_util'\n\nimport { SliderProvider } from './context'\nimport { Scale } from './Scale'\nimport { ScaleOption } from './ScaleOption'\nimport { Thumb, SliderThumbMethods, SliderThumbProps } from './Thumb'\nimport { Track, SliderTrackProps } from './Track'\n\nconst defaultExternalStyles: SliderProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'pointer',\n}\n\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 /**\n * slider orientation\n * aria-orientation property is also applied.\n */\n vertical?: boolean\n reverse?: boolean\n\n /** Global style to apply when dragged */\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n /**\n * wheel control option\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n\n /**\n * Only the appearance will change.\n * Please consider using with readonly.\n * aria-disabled property is also applied.\n */\n disabled?: boolean\n /**\n * Make the value unchangeable.\n * aria-readonly property is also applied.\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\nexport interface SliderMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = SliderProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof SliderProps>\n\nconst Root = forwardRef<SliderMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n skew = 1,\n vertical = false,\n reverse = false,\n externalStyles: _externalStyles,\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 forwardedRef,\n ) => {\n // -- state and ref ---\n const trackElementRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<SliderThumbMethods>(null)\n\n // --- interpret props ---\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\n\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 == Thumb) {\n thumbProps = child.props as SliderThumbProps\n } else if (child.type == Track) {\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 { refHandler: touchMoveRefCallback, pointerDownHandler } =\n useDragWithElement<HTMLDivElement>({\n baseElementRef: trackElementRef,\n onDrag: onDrag,\n onDragStart: (nx, ny) => {\n if (readonly) return\n if (externalStyles.userSelectNone) addUserSelectNone()\n if (externalStyles.cursor) setCursorStyle(externalStyles.cursor)\n\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\n if (externalStyles.userSelectNone) removeUserSelectNone()\n if (externalStyles.cursor) resetCursorStyle()\n\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(forwardedRef, () => {\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 <Track\n __percent={percent}\n __thumb={\n <Thumb ref={thumbRef} __percent={percent} {...thumbProps} />\n }\n {...trackProps}\n />\n </div>\n {scaleComponent}\n </div>\n </div>\n </SliderProvider>\n )\n },\n)\n\n/**\n * Customizable slider\n */\nexport const Slider = {\n Root,\n Thumb,\n Track,\n Scale,\n ScaleOption,\n}\n\nexport { useSliderContext } from './context'\nexport { type SliderThumbMethods, type SliderThumbProps } from './Thumb'\nexport { type SliderTrackProps } from './Track'\nexport { type ScaleProps } from './Scale'\nexport { type ScaleOptionProps } from './ScaleOption'\nexport { type ScaleOptions, type ScaleType } from './type'\n","// ref:\n// https://github.com/radix-ui/primitives/blob/2bab24a811e45c7a83198659272097f6cfa5a165/packages/react/compose-refs/src/compose-refs.tsx\n\nimport { useCallback } from 'react'\n\ntype PossibleRef<T> = React.Ref<T> | undefined\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n return ref(value)\n } else if (ref !== null && ref !== undefined) {\n ref.current = value\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node)\n if (!hasCleanup && typeof cleanup == 'function') {\n hasCleanup = true\n }\n return cleanup\n })\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i]\n if (typeof cleanup == 'function') {\n cleanup()\n } else {\n setRef(refs[i], null)\n }\n }\n }\n }\n }\n}\n\n/**\n * A custom hook that composes multiple refs\n * Accepts callback refs and RefObject(s)\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback(composeRefs(...refs), refs)\n}\n\nexport { composeRefs, useComposedRefs }\n","import { ComponentProps, ElementType, ReactNode } from 'react'\n\nimport { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'\nimport { composeRefs } from '../_util/composeRefs'\nimport { Override } from '../_util/type'\n\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/**\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 */\nexport function WheelObserver<T extends ElementType = 'div'>(\n props: Override<WheelObserverProps<T>, ComponentProps<T>>,\n) {\n const { as: Component = 'div', children, onWheel, ref, ...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={composeRefs(ref, wheelRefCallback)} {...attributes}>\n {children}\n </Component>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactElement } from 'react'\n\nexport interface XYPadAreaProps {\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\nexport function Area({\n width = 120,\n height = 120,\n color,\n children,\n className,\n style,\n __thumb,\n ...props\n}: XYPadAreaProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadAreaProps>) {\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\nexport interface XYPadThumbProps {\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 __readonly?: boolean\n /** @internal */\n __css?: CSSProperties\n}\n\nexport interface XYPadThumbMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = XYPadThumbProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadThumbProps>\n\nexport const Thumb = 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 __readonly,\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 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 React, {\n ComponentPropsWithoutRef,\n forwardRef,\n ReactElement,\n Ref,\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 {\n addUserSelectNone,\n Cursor,\n removeUserSelectNone,\n resetCursorStyle,\n setCursorStyle,\n} from '../_util'\nimport { composeRefs } from '../_util/composeRefs'\n\nimport { Area, XYPadAreaProps } from './Area'\nimport { Thumb, XYPadThumbMethods, XYPadThumbProps } from './Thumb'\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\nconst defaultExternalStyles: XYPadProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'pointer',\n}\n\n/**\n * Two-dimensional slider component.\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\nexport interface XYPadProps {\n x: ValueOptions\n y: ValueOptions\n\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n\n disabled?: boolean\n readonly?: boolean\n\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\nexport interface XYPadMethods {\n focus: () => void\n blur: () => void\n original: Ref<HTMLDivElement>\n}\n\ntype Props = XYPadProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadProps>\n\nexport const Root = forwardRef<XYPadMethods, Props>(\n (\n {\n x: _x,\n y: _y,\n className,\n style,\n externalStyles: _externalStyles,\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 forwardedRef,\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 rootRef = useRef<HTMLDivElement>(null)\n const areaElementRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<XYPadThumbMethods>(null)\n\n // --- interpret props ---\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\n\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: XYPadAreaProps = {}\n let thumbProps: XYPadThumbProps = {}\n if (children != undefined) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) {\n if (child.type == Thumb) {\n thumbProps = child.props as XYPadThumbProps\n } else if (child.type == Area) {\n areaProps = child.props as XYPadAreaProps\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 { refHandler: touchMoveRefCallback, pointerDownHandler } =\n useDragWithElement<HTMLDivElement>({\n baseElementRef: areaElementRef,\n onDrag: onDrag,\n onDragStart: (nx, ny) => {\n if (readonly) return\n\n if (externalStyles.userSelectNone) addUserSelectNone()\n if (externalStyles.cursor) setCursorStyle(externalStyles.cursor)\n\n thumbRef.current?.focus()\n\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\n // TODO: ドラッグせず、pointer downだけの場合でも、onChange を発火させるべき\n // onChange()\n onDragStart?.(valueX, valueY)\n },\n onDragEnd: (nx, ny) => {\n if (readonly) return\n\n if (externalStyles.userSelectNone) removeUserSelectNone()\n if (externalStyles.cursor) resetCursorStyle()\n\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(forwardedRef, () => {\n return {\n focus() {\n thumbRef.current?.focus()\n },\n blur() {\n thumbRef.current?.blur()\n },\n original: rootRef,\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={composeRefs(rootRef, wheelRefCallback, touchMoveRefCallback)}\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 <Area\n __thumb={\n <Thumb\n ref={thumbRef}\n __disabled={disabled}\n __readonly={readonly}\n __css={{\n top: `${percentY}%`,\n left: `${percentX}%`,\n }}\n {...thumbProps}\n />\n }\n {...areaProps}\n />\n </div>\n </div>\n )\n },\n)\n\n/**\n * Simple XYPad\n */\nexport const XYPad = {\n Root,\n Thumb,\n Area,\n}\n\nexport { type XYPadThumbProps, type XYPadThumbMethods } from './Thumb'\nexport { type XYPadAreaProps } 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","import { useEffect, useMemo, useSyncExternalStore } from 'react'\n\nimport { createMIDIAccess } from '@tremolo-ui/dom'\n\nexport {\n NOT_SUPPORTED,\n PERMISSION_DENIED,\n type MIDIAccessError,\n} from '@tremolo-ui/dom'\n\n/**\n * Hooks for requesting MIDI access in the browser. The first argument allows you to choose whether to request access on mount.\n */\nexport function useMIDIAccess(requestOnMount = true) {\n const instance = useMemo(() => createMIDIAccess(), [])\n\n const { midiAccess, error } = useSyncExternalStore(\n instance.subscribe,\n instance.getState,\n instance.getServerState,\n )\n\n useEffect(() => {\n if (requestOnMount) instance.request()\n }, [instance, requestOnMount])\n\n useEffect(() => {\n return () => instance.destroy()\n }, [instance])\n\n return { request: instance.request, midiAccess, error }\n}\n","import { useEffect } from 'react'\n\nimport { createMIDIInput } from '@tremolo-ui/dom'\n\n/**\n * Hooks for handling note on/off events. To be used with useMIDIAccess. Internally uses useMIDIMessage.\n */\nexport function useMIDIInput(\n midiAccess: MIDIAccess | null,\n onNoteOnEvent?: (note: number, velocity: number) => void,\n onNoteOffEvent?: (note: number) => void,\n onPitchBendEvent?: (msb: number, lsb: number) => void,\n) {\n useEffect(() => {\n const instance = createMIDIInput(midiAccess, {\n onNoteOnEvent,\n onNoteOffEvent,\n onPitchBendEvent,\n })\n return () => instance.destroy()\n }, [midiAccess, onNoteOnEvent, onNoteOffEvent, onPitchBendEvent])\n}\n","import { useEffect } from 'react'\n\nimport { createMIDIMessage } from '@tremolo-ui/dom'\n\n/**\n * Hooks for when you want to process MIDI events in more detail than useMIDIInput.\n */\nexport function useMIDIMessage(\n midiAccess: MIDIAccess | null,\n onMIDIMessage: (event: MIDIMessageEvent) => void,\n) {\n useEffect(() => {\n const instance = createMIDIMessage(midiAccess, onMIDIMessage)\n return () => instance.destroy()\n }, [midiAccess, onMIDIMessage])\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Thumb","defaultExternalStyles","WHEEL_OPTIONS","Root","Root","Root","Root","Thumb","defaultExternalStyles","WHEEL_OPTIONS","Root"],"sources":["../src/components/AnimationCanvas/index.tsx","../src/hooks/_internal/useCallbackRef.ts","../src/hooks/useDragValue.ts","../src/hooks/useWheel.ts","../src/components/_util/index.ts","../src/components/_util/composeRefs.tsx","../src/components/Knob/context.tsx","../src/components/Knob/ActiveLine.tsx","../src/components/Knob/InactiveLine.tsx","../src/components/Knob/SVGRoot.tsx","../src/components/Knob/Thumb.tsx","../src/components/Knob/index.tsx","../src/components/NumberInput/context.tsx","../src/hooks/useEventListener.ts","../src/hooks/useInterval.ts","../src/hooks/useLongPress.ts","../src/components/NumberInput/stepperButton.tsx","../src/components/NumberInput/DecrementStepper.tsx","../src/components/NumberInput/IncrementStepper.tsx","../src/components/NumberInput/InputField.tsx","../src/hooks/useDrag.ts","../src/components/NumberInput/Stepper.tsx","../src/components/NumberInput/index.tsx","../src/components/Piano/keyboardShortcuts.ts","../src/components/Piano/index.tsx","../src/components/PointsEditor/Background.tsx","../src/components/PointsEditor/context.tsx","../src/components/PointsEditor/Container.tsx","../src/components/PointsEditor/Point.tsx","../src/components/PointsEditor/index.tsx","../src/components/Slider/context.tsx","../src/components/Slider/MarksOption.tsx","../src/components/Slider/type.ts","../src/components/Slider/Marks.tsx","../src/components/Slider/Thumb.tsx","../src/components/Slider/Track.tsx","../src/components/Slider/index.tsx","../src/components/XYPad/context.tsx","../src/components/XYPad/Area.tsx","../src/components/XYPad/Thumb.tsx","../src/components/XYPad/index.tsx","../src/hooks/useAnimationFrame.ts","../src/hooks/useMIDIAccess.ts","../src/hooks/useMIDIInput.ts","../src/hooks/useMIDIMessage.ts"],"sourcesContent":["import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n ReactElement,\n useEffect,\n useRef,\n useState,\n} from 'react'\n\nimport {\n createAnimationCanvas,\n type AnimationCanvasInstance,\n type AnimationFrame,\n} from '@tremolo-ui/dom'\n\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\nexport type DrawFunction = (\n context: CanvasRenderingContext2D,\n option: AnimationFrame,\n) => void\n\nexport interface CommonProps {\n draw: DrawFunction\n init?: InitFunction\n animate?: boolean\n /**\n * Read once, when the 2D context is created, so changing it later has no\n * effect. Passing a fresh object on every render is therefore harmless.\n *\n * @see https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext#contextattributes\n */\n options?: CanvasRenderingContext2DSettings\n}\n\nexport interface AbsoluteSizingProps {\n width?: number\n height?: number\n}\n\nexport interface RelativeSizingProps {\n relativeSize?: boolean\n reduceFlickering?: boolean\n}\n\nexport type AnimationCanvasProps = CommonProps &\n AbsoluteSizingProps &\n RelativeSizingProps\n\n/**\n * A simple animatable canvas with requestAnimationFrame()\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 draw,\n init,\n animate = true,\n options,\n // absolute\n width = 100,\n height = 100,\n // relative\n relativeSize = false,\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 // See useDrag for why the node is held in state rather than a ref: an inline\n // ref would be re-attached on every render and tear the instance down.\n const [node, setNode] = useState<HTMLCanvasElement | null>(null)\n\n // Read when the instance is created. The effect below keeps it current, and\n // runs right after, so a stale handler is replaced within the same commit.\n const latest = useRef({\n draw,\n init,\n animate,\n width,\n height,\n reduceFlickering,\n options,\n })\n const instanceRef = useRef<AnimationCanvasInstance | null>(null)\n /** Set while the instance below is newer than the effect that pushes into it. */\n const justCreated = useRef(false)\n\n useEffect(() => {\n if (!node) return\n\n const current = latest.current\n const instance = createAnimationCanvas(node, {\n draw: (context, frame) => latest.current.draw(context, frame),\n init: (context, size) => latest.current.init?.(context, size),\n animate: current.animate,\n size: { width: current.width, height: current.height },\n reduceFlickering: current.reduceFlickering,\n relativeSize,\n contextAttributes: current.options,\n })\n instanceRef.current = instance\n justCreated.current = true\n\n return () => {\n instanceRef.current = null\n instance.destroy()\n }\n // Only `relativeSize` decides how the instance is wired, so it is the one\n // setting that rebuilds it. `options` is read from the ref above rather\n // than depended on: it is almost always written inline, and depending on\n // it would tear the canvas down on every render.\n }, [node, relativeSize])\n\n // Runs after every render: the handlers come from props and are cheap to\n // push, and updating in place keeps the frame count and elapsed time going.\n useEffect(() => {\n latest.current = {\n draw,\n init,\n animate,\n width,\n height,\n reduceFlickering,\n options,\n }\n // The instance was built from `latest` a moment ago, so there is nothing\n // to push yet. Skipping matters with `animate` off, where `update()` draws\n // a frame and would otherwise paint the same one twice on mount.\n if (justCreated.current) {\n justCreated.current = false\n return\n }\n instanceRef.current?.update({\n animate,\n size: { width, height },\n reduceFlickering,\n })\n })\n\n return (\n <canvas\n className={clsx('tremolo-animation-canvas', className)}\n ref={setNode}\n onContextMenu={onContextMenu}\n {...props}\n />\n )\n}\n","import { DependencyList, useCallback, useInsertionEffect, useRef } from 'react'\n\n/**\n * Internal\n * @private\n */\nexport function useCallbackRef<Args extends unknown[], Return>(\n callback: ((...args: Args) => Return) | undefined,\n deps: 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 { RefObject, useEffect, useRef, useState } from 'react'\n\nimport {\n createDragValue,\n elementMapping,\n relativeMapping,\n type AxisOptions,\n type DragValueInstance,\n type XY,\n type XYInput,\n} from '@tremolo-ui/dom'\n\nimport { useCallbackRef } from './_internal/useCallbackRef'\n\nexport interface UseDragValueOptions {\n /** Scaling of each axis; a single value applies to both. */\n axis: XYInput<AxisOptions>\n\n /**\n * Normalize the pointer against the bounding rect of this element, so that\n * the value *is* the position pointed at.\n *\n * Give either this or `getValue`.\n */\n baseElementRef?: RefObject<Element | null>\n\n /**\n * Move the value away from where it stood when the drag started, by the\n * distance dragged. The pointer position itself carries no meaning.\n *\n * Give either this or `baseElementRef`.\n */\n getValue?: () => XY<number>\n /**\n * Pixels of movement that span the whole range, with `getValue`.\n * @default 100\n */\n pixelRange?: XYInput<number>\n\n /** @see DragValueOptions.updateOnPointerDown */\n updateOnPointerDown?: boolean\n /** @default 0 */\n threshold?: number\n /** CSS cursor to show while dragging. Applied to the element itself. */\n cursor?: string\n\n onChange?: (value: XY<number>) => void\n onDragStart?: (value: XY<number>) => void\n onDragEnd?: (value: XY<number>) => void\n}\n\n/**\n * Drive a value with a pointer drag.\n *\n * @returns a ref callback for the element that starts the drag, and whether a drag is in progress\n */\nexport function useDragValue<T extends Element>(\n options: UseDragValueOptions,\n): { refCallback: (node: T | null) => void; dragging: boolean } {\n const {\n axis,\n baseElementRef,\n pixelRange,\n updateOnPointerDown,\n threshold,\n cursor,\n } = options\n\n if (!baseElementRef && !options.getValue) {\n throw new Error(\n 'useDragValue: give either baseElementRef or getValue, so that the drag has something to move',\n )\n }\n\n const [dragging, setDragging] = useState(false)\n\n const valueGetter = useCallbackRef(options.getValue)\n const changeHandler = useCallbackRef(options.onChange)\n const dragStartHandler = useCallbackRef(options.onDragStart)\n const dragEndHandler = useCallbackRef(options.onDragEnd)\n\n // Read when the instance is created. The effect below keeps it current, and\n // runs right after, so a stale setting is replaced within the same commit.\n const latest = useRef(options)\n\n const instanceRef = useRef<DragValueInstance | null>(null)\n\n // See useDrag for why the node is held in state.\n const [node, setNode] = useState<T | null>(null)\n\n const [pixelRangeX, pixelRangeY] = Array.isArray(pixelRange)\n ? pixelRange\n : [pixelRange, pixelRange]\n\n useEffect(() => {\n if (!node) return\n\n const instance = createDragValue(node, {\n axis: latest.current.axis,\n mapping: baseElementRef\n ? elementMapping(() => baseElementRef.current)\n : relativeMapping({\n pixelRange: [pixelRangeX ?? 100, pixelRangeY ?? 100],\n }),\n getValue: () => valueGetter() ?? [0, 0],\n updateOnPointerDown: latest.current.updateOnPointerDown,\n threshold: latest.current.threshold,\n cursor: latest.current.cursor,\n onChange: (value) => changeHandler(value),\n onDragStart: (value) => {\n setDragging(true)\n dragStartHandler(value)\n },\n onDragEnd: (value) => {\n setDragging(false)\n dragEndHandler(value)\n },\n })\n instanceRef.current = instance\n\n return () => {\n instanceRef.current = null\n instance.destroy()\n }\n }, [\n node,\n baseElementRef,\n pixelRangeX,\n pixelRangeY,\n valueGetter,\n changeHandler,\n dragStartHandler,\n dragEndHandler,\n ])\n\n // Runs after every render: the settings come from props and are cheap to\n // push, and updating in place leaves a drag in progress untouched.\n useEffect(() => {\n latest.current = options\n instanceRef.current?.update({\n axis,\n updateOnPointerDown,\n threshold,\n cursor,\n })\n })\n\n return { refCallback: setNode, dragging }\n}\n","import { RefObject, useEffect, useState } from 'react'\n\nimport { createWheel, type WheelOptions } from '@tremolo-ui/dom'\n\nimport { useCallbackRef } from './_internal/useCallbackRef'\n\nexport interface UseWheelOptions extends WheelOptions {\n /**\n * Listen on this element rather than on the one the returned ref callback is\n * attached to, and ignore that callback.\n *\n * For a control made of several movable parts: a wheel event only reaches\n * what the cursor is over, so a listener per part responds only while the\n * cursor is over that same part. Listening on the element they share lets\n * every part see the event, and each one decide whether it is the one to act.\n *\n * The element is read when the listener is attached, so a ref filled in by a\n * parent is fine as long as the parent is above in the tree.\n */\n target?: RefObject<Element | null>\n}\n\n/**\n * Listen to wheel events on an element.\n *\n * The listener is not passive, so the handler may call `preventDefault()`.\n *\n * @returns a ref callback to attach to the element, unused when `target` is given\n */\nexport function useWheel<T extends Element>(\n onWheel: (event: WheelEvent) => void,\n { requireFocus = false, target }: UseWheelOptions = {},\n): (node: T | null) => void {\n const wheelHandler = useCallbackRef(onWheel)\n\n // See useDrag for why the node is held in state.\n const [node, setNode] = useState<T | null>(null)\n\n useEffect(() => {\n const element = target ? target.current : node\n if (!element) return\n\n const instance = createWheel(element, (event) => wheelHandler(event), {\n requireFocus,\n })\n\n return () => instance.destroy()\n }, [node, target, wheelHandler, requireFocus])\n\n return setNode\n}\n","export function addUserSelectNone() {\n window.document.body.classList.add('tremolo-user-select-none')\n}\n\nexport function removeUserSelectNone() {\n window.document.body.classList.remove('tremolo-user-select-none')\n}\n\nconst cursorStyles = {\n grabbing: 'tremolo-cursor-grabbing',\n grab: 'tremolo-cursor-grab',\n pointer: 'tremolo-cursor-pointer',\n move: 'tremolo-cursor-move',\n none: 'tremolo-cursor-none',\n}\n\nexport type Cursor = keyof typeof cursorStyles\n\nexport function setCursorStyle(type: Cursor) {\n resetCursorStyle()\n window.document.body.classList.add(cursorStyles[type])\n}\n\nexport function resetCursorStyle() {\n Object.values(cursorStyles).forEach((s) => {\n window.document.body.classList.remove(s)\n })\n}\n","// ref:\n// https://github.com/radix-ui/primitives/blob/2bab24a811e45c7a83198659272097f6cfa5a165/packages/react/compose-refs/src/compose-refs.tsx\n\nimport { useCallback } from 'react'\n\ntype PossibleRef<T> = React.Ref<T> | undefined\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n return ref(value)\n } else if (ref !== null && ref !== undefined) {\n ref.current = value\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node)\n if (!hasCleanup && typeof cleanup == 'function') {\n hasCleanup = true\n }\n return cleanup\n })\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i]\n if (typeof cleanup == 'function') {\n cleanup()\n } else {\n setRef(refs[i], null)\n }\n }\n }\n }\n }\n}\n\n/**\n * A custom hook that composes multiple refs\n * Accepts callback refs and RefObject(s)\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback(composeRefs(...refs), refs)\n}\n\nexport { composeRefs, useComposedRefs }\n","import { createContext, useContext } from 'react'\n\nimport { radian, type Scale } from '@tremolo-ui/functions'\n\nexport const viewBoxSize = 100\nexport const center = viewBoxSize / 2\n\nexport type KnobConfig = {\n value: number\n min: number\n max: number\n step: number\n scale: Scale\n startValue: number\n /** angle range [degree] */\n angleRange: number\n}\n\nexport type KnobContextValue = KnobConfig & {\n /** normalized value */\n p: number\n /** ロータリー開始位置 */\n r1: number\n /** activeLine の開始位置 */\n r2: number\n /** activeLine の終了位置 */\n r3: number\n /** ロータリー終了位置 */\n r4: number\n}\n\n/**\n * 角度から円弧上の点を求める。\n *\n * 半径は線の太さの分だけ内側に取る必要があるが、太さは ActiveLine / InactiveLine が\n * それぞれ持つため、座標はストアで先に計算せず各コンポーネント側で求める。\n */\nexport function pointOnArc(angle: number, radius: number) {\n return {\n x: center + radius * Math.cos(radian(angle - 90)),\n y: center + radius * Math.sin(radian(angle - 90)),\n }\n}\n\n/** 線の太さが viewBox からはみ出さないようにした半径 */\nexport function arcRadius(strokeWidth: number | string | undefined) {\n const width =\n typeof strokeWidth === 'number'\n ? strokeWidth\n : Number.parseFloat(String(strokeWidth))\n return Number.isFinite(width) ? center - width / 2 : center\n}\n\n/** 設定から描画に必要な角度を導出する。レンダー中に呼ぶ。 */\nexport function calcAngles({\n value,\n min,\n max,\n scale,\n startValue,\n angleRange,\n}: KnobConfig) {\n const p = scale.normalize(value, min, max)\n const s = scale.normalize(startValue, min, max)\n\n const r1 = -angleRange / 2\n const r2 = r1 + Math.min(p, s) * angleRange\n const r3 = r1 + Math.max(p, s) * angleRange\n const r4 = angleRange / 2\n\n return { p, r1, r2, r3, r4 }\n}\n\nconst KnobContext = createContext<KnobContextValue | null>(null)\n\nexport const KnobProvider = KnobContext.Provider\n\n/**\n * Everything here is derived during render, so there is no state to keep in\n * sync: `value` comes from the props of `Root` and the rest follows from it.\n */\nexport function useKnobContext(): KnobContextValue\nexport function useKnobContext<T>(selector: (state: KnobContextValue) => T): T\nexport function useKnobContext<T>(selector?: (state: KnobContextValue) => T) {\n const context = useContext(KnobContext)\n if (!context) throw new Error('Missing KnobContext.Provider in the tree')\n return selector ? selector(context) : context\n}\n","import clsx from 'clsx'\nimport { SVGProps } from 'react'\n\nimport { arcRadius, pointOnArc, useKnobContext } from './context'\n\nexport function ActiveLine({\n stroke = 'currentColor',\n strokeWidth = 6,\n className,\n ...props\n}: Omit<SVGProps<SVGPathElement>, 'd'>) {\n const r2 = useKnobContext((s) => s.r2)\n const r3 = useKnobContext((s) => s.r3)\n\n const radius = arcRadius(strokeWidth)\n const start = pointOnArc(r2, radius)\n const end = pointOnArc(r3, radius)\n\n return (\n <path\n className={clsx('tremolo-knob-active-line', className)}\n d={`M ${start.x} ${start.y} A ${radius} ${radius} -135 ${r3 - r2 > 180 ? 1 : 0} 1 ${end.x} ${end.y}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n {...props}\n />\n )\n}\n","import clsx from 'clsx'\nimport { SVGProps } from 'react'\n\nimport { arcRadius, pointOnArc, useKnobContext } from './context'\n\nexport function InactiveLine({\n stroke = 'currentColor',\n strokeWidth = 6,\n className,\n ...props\n}: Omit<SVGProps<SVGPathElement>, 'd'>) {\n const min = useKnobContext((s) => s.min)\n const max = useKnobContext((s) => s.max)\n const startValue = useKnobContext((s) => s.startValue)\n\n const r1 = useKnobContext((s) => s.r1)\n const r2 = useKnobContext((s) => s.r2)\n const r3 = useKnobContext((s) => s.r3)\n const r4 = useKnobContext((s) => s.r4)\n\n const radius = arcRadius(strokeWidth)\n const p1 = pointOnArc(r1, radius)\n const p2 = pointOnArc(r2, radius)\n const p3 = pointOnArc(r3, radius)\n const p4 = pointOnArc(r4, radius)\n\n return (\n <>\n {startValue > min && (\n <path\n className={clsx('tremolo-knob-inactive-line', className)}\n d={`M ${p1.x} ${p1.y} A ${radius} ${radius} -135 ${r2 - r1 > 180 ? 1 : 0} 1 ${p2.x} ${p2.y}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n {...props}\n />\n )}\n {startValue < max && (\n <path\n className={clsx('tremolo-knob-inactive-line', className)}\n d={`M ${p3.x} ${p3.y} A ${radius} ${radius} -135 ${r4 - r3 > 180 ? 1 : 0} 1 ${p4.x} ${p4.y}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n {...props}\n />\n )}\n </>\n )\n}\n","import { ReactNode, SVGProps } from 'react'\n\nimport { viewBoxSize } from './context'\n\nexport interface SVGRootProps {\n /**\n * `<Knob.InactiveLine />`, `<Knob.ActiveLine />` and `<Knob.Thumb />` go\n * here, in the order you want them painted.\n */\n children: ReactNode\n}\n\nexport function SVGRoot({\n children,\n style,\n ...props\n}: SVGRootProps & Omit<SVGProps<SVGSVGElement>, keyof SVGRootProps>) {\n return (\n <svg\n viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}\n style={{\n display: 'block',\n ...style,\n }}\n {...props}\n >\n {children}\n </svg>\n )\n}\n","import clsx from 'clsx'\nimport { SVGProps } from 'react'\n\nimport { clamp } from '@tremolo-ui/functions'\n\nimport { useKnobContext, viewBoxSize } from './context'\n\ninterface Props {\n /** color */\n thumb?: string\n /** color */\n thumbLine?: string\n /** percent (0-100) */\n thumbSize?: number\n /** percent (0-100) */\n thumbLineWeight?: number\n /** percent (0-100) */\n thumbLineLength?: number\n\n classes?: {\n thumb?: string\n thumbLine?: string\n }\n}\n\nexport function Thumb({\n className,\n\n thumb = 'currentColor',\n thumbLine = 'currentColor',\n thumbSize = 84,\n thumbLineWeight = 6,\n thumbLineLength = 35,\n classes,\n\n ...props\n}: Props & Omit<SVGProps<SVGSVGElement>, 'd' | keyof Props>) {\n const angleRange = useKnobContext((s) => s.angleRange)\n\n const p = useKnobContext((s) => s.p)\n const r1 = useKnobContext((s) => s.r1)\n\n return (\n <svg className={clsx('tremolo-knob-thumb', classes?.thumb)} {...props}>\n <circle cx=\"50%\" cy=\"50%\" r={`${thumbSize / 2}%`} fill={thumb} />\n <line\n className={clsx('tremolo-knob-thumb-line', classes?.thumbLine)}\n x1=\"50%\"\n y1={`${(viewBoxSize - clamp(thumbSize, 0, 100)) / 2}%`}\n x2=\"50%\"\n y2={`${thumbLineLength}%`}\n stroke={thumbLine}\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(${r1 + p * angleRange}deg)`,\n transformOrigin: '50% 50%',\n }}\n />\n </svg>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n ReactNode,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react'\n\nimport type { AxisOptions, XY } from '@tremolo-ui/dom'\nimport {\n applyDelta,\n InputEventOption,\n linearScale,\n type Scale,\n type ValueRange,\n} from '@tremolo-ui/functions'\n\nimport { useDragValue } from '../../hooks/useDragValue'\nimport { useWheel } from '../../hooks/useWheel'\nimport { addUserSelectNone, Cursor, removeUserSelectNone } from '../_util'\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { ActiveLine } from './ActiveLine'\nimport { calcAngles, KnobProvider } from './context'\nimport { InactiveLine } from './InactiveLine'\nimport { SVGRoot } from './SVGRoot'\nimport { Thumb } from './Thumb'\n\nconst defaultExternalStyles: KnobProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'grabbing',\n}\n\nexport interface KnobProps {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n /**\n * How the value is distributed across the travel.\n *\n * Pick one of the scales from `@tremolo-ui/functions`: `linearScale`,\n * `exponentialScale`, `curveScale(n)`, `symmetricSkewScale(n)`, or\n * `skewScale(n)` for a value that has to match a JUCE parameter.\n *\n * @default linearScale\n */\n scale?: Scale\n /**\n * value set when double-clicking\n * restriction: enableDoubleClickDefault = true\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 /** width and height */\n /**\n * Width and height of the knob.\n * Defaults to the `--knob-size` CSS variable (50px).\n */\n size?: number | string\n\n /**\n * Global style to apply when dragged\n * @default defaultExternalStyles\n */\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n /**\n * wheel control option\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n enableDoubleClickDefault?: boolean\n\n disabled?: boolean\n readonly?: boolean\n\n /** angle range [degree] */\n angleRange?: number\n\n onChange?: (value: number) => void\n\n /**\n * The knob renders exactly what you compose here; there is no default\n * markup to fall back to.\n *\n * @example\n * <Knob.Root value={value} min={0} max={100} onChange={setValue}>\n * <Knob.SVGRoot>\n * <Knob.InactiveLine />\n * <Knob.ActiveLine />\n * <Knob.Thumb />\n * </Knob.SVGRoot>\n * </Knob.Root>\n */\n children: ReactNode\n}\n\nexport interface KnobMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = KnobProps & Omit<ComponentPropsWithoutRef<'div'>, keyof KnobProps>\n\n/**\n * The wheel only acts while the focus is inside, so that scrolling a page past\n * the control does not change its value.\n */\nconst WHEEL_OPTIONS = { requireFocus: true }\n\nexport const Root = forwardRef<KnobMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n scale = linearScale,\n defaultValue = min,\n startValue = min,\n size,\n externalStyles: _externalStyles,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n enableDoubleClickDefault = true,\n disabled = false,\n readonly = false,\n angleRange = 270,\n onChange,\n onKeyDown,\n onPointerDown,\n onDoubleClick,\n className,\n style,\n children,\n ...props\n }: Props,\n forwardedRef,\n ) => {\n const elmRef = useRef<HTMLElement | SVGElement>(null)\n\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\n\n // --- internal functions ---\n const range: ValueRange = useMemo(\n () => ({ min, max, step, scale }),\n [min, max, step, scale],\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 direction = key == 'ArrowRight' || key == 'ArrowUp' ? 1 : -1\n onChange(applyDelta(value, direction, keyboard, range))\n }\n },\n [keyboard, onChange, readonly, value, range],\n )\n\n // --- hooks ---\n // The knob has no travel of its own: the value moves away from where it\n // stood when the drag started, 100px of movement spanning the whole range.\n // Only the vertical axis carries a value, reversed so that dragging up\n // raises it.\n const axis = useMemo(\n (): XY<AxisOptions> => [range, { ...range, reverse: true }],\n [range],\n )\n\n const { refCallback: dragRefCallback, dragging } = useDragValue<\n HTMLElement | SVGElement\n >({\n axis,\n getValue: () => [value, value],\n threshold: 1,\n cursor: readonly ? undefined : externalStyles.cursor,\n onChange: (v) => {\n if (readonly) return\n onChange?.(v[1])\n },\n onDragStart: () => {\n if (externalStyles.userSelectNone) addUserSelectNone()\n },\n onDragEnd: () => {\n if (externalStyles.userSelectNone) removeUserSelectNone()\n },\n })\n\n const wheelRefCallback = useWheel<HTMLElement>((event) => {\n if (!wheel || readonly) return\n event.preventDefault()\n if (!onChange || event.deltaY == 0) return\n onChange(applyDelta(value, -Math.sign(event.deltaY), wheel, range))\n }, WHEEL_OPTIONS)\n\n // Composed once, so React attaches the refs a single time instead of\n // detaching and re-attaching on every render.\n const rootRefCallback = useComposedRefs<HTMLElement | SVGElement>(\n elmRef,\n dragRefCallback,\n wheelRefCallback,\n )\n\n const context = useMemo(() => {\n const config = { value, min, max, step, scale, startValue, angleRange }\n return { ...config, ...calcAngles(config) }\n }, [value, min, max, step, scale, startValue, angleRange])\n\n useImperativeHandle(forwardedRef, () => {\n return {\n focus() {\n elmRef.current?.focus()\n },\n blur() {\n elmRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <KnobProvider value={context}>\n <div\n ref={rootRefCallback}\n className={clsx('tremolo-knob', className)}\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 data-dragging={dragging}\n style={{\n width: size,\n height: size,\n ...style,\n }}\n onPointerDown={onPointerDown}\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 {children}\n </div>\n </KnobProvider>\n )\n },\n)\n\n/**\n * Interactive rotary knob component implemented in SVG.\n */\nexport const Knob = {\n Root,\n SVGRoot,\n InactiveLine,\n ActiveLine,\n Thumb,\n}\n\nexport { useKnobContext } from './context'\n","import { createContext, RefObject, useContext } from 'react'\n\nimport type { InputEventOption, Scale, ValueRange } from '@tremolo-ui/functions'\n\nexport type NumberInputContextValue = {\n value: number\n\n /**\n * The range the caller asked for. Left undefined when unbounded, which is\n * what `aria-valuemin` / `aria-valuemax` and the steppers need to tell apart\n * from a range that happens to sit at the edge of the safe integers.\n */\n min?: number\n max?: number\n step: number\n /** How the value is distributed across the travel. */\n scale: Scale\n\n disabled: boolean\n readonly: boolean\n clampValue: boolean\n\n /**\n * The effective scaling for `applyDelta` and for clamping on commit, with the\n * unbounded ends filled in. Ignores `min` / `max` when `clampValue` is off.\n */\n range: ValueRange\n\n keyboard: InputEventOption | null\n /** Pixels of vertical drag on `Stepper` that move the value by one `step`. */\n drag: number | null\n\n /** What the input shows: the draft while editing, the formatted value otherwise. */\n text: string\n editing: boolean\n /** Whether the value sits outside `min` / `max`. Not judged while editing. */\n outOfRange: boolean\n /** Whether a stepper would have no effect, for `aria-disabled`. */\n atMin: boolean\n atMax: boolean\n\n format: (value: number) => string\n parse: (text: string) => number\n\n /** Typing. Replaces the draft and reports the parsed value, unclamped. */\n setDraft: (text: string) => void\n /** Blur or Enter. Clamps the draft, reports it, and drops the draft. */\n commitDraft: () => void\n /** Drops the draft and replaces the value: steppers, wheel, keyboard, drag. */\n changeValue: (next: number) => void\n /** Moves the value by one `option` in `direction`, normally +1 or -1. */\n nudge: (direction: number, option: InputEventOption) => void\n\n /** `InputField` registers itself here; `Root` focuses it through its methods. */\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nconst NumberInputContext = createContext<NumberInputContextValue | null>(null)\n\nexport const NumberInputProvider = NumberInputContext.Provider\n\n/**\n * The only state behind this is the editing draft; `value` comes from the props\n * of `Root` and everything else is derived during render.\n */\nexport function useNumberInputContext(): NumberInputContextValue\nexport function useNumberInputContext<T>(\n selector: (state: NumberInputContextValue) => T,\n): T\nexport function useNumberInputContext<T>(\n selector?: (state: NumberInputContextValue) => T,\n) {\n const context = useContext(NumberInputContext)\n if (!context)\n throw new Error('Missing NumberInputContext.Provider in the tree')\n return selector ? selector(context) : context\n}\n\n/** Set by `Stepper` once a drag has actually moved, so the steppers stand down. */\nexport type StepperContextValue = {\n draggingRef: RefObject<boolean>\n}\n\nconst StepperContext = createContext<StepperContextValue | null>(null)\n\nexport const StepperProvider = StepperContext.Provider\n\nexport function useStepperContext(): StepperContextValue | null {\n return useContext(StepperContext)\n}\n","import { useEffect } from 'react'\n\nimport { useCallbackRef } from './_internal/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,\n options?: Options,\n) {\n const listener = useCallbackRef(handler)\n\n useEffect(() => {\n const node = typeof target === 'function' ? target() : (target ?? document)\n\n if (!node) return\n\n node.addEventListener(event, listener, options)\n return () => {\n node.removeEventListener(event, listener, options)\n }\n }, [event, target, options, listener])\n\n return () => {\n const node = typeof target === 'function' ? target() : (target ?? document)\n node?.removeEventListener(event, listener, options)\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 {\n ComponentPropsWithoutRef,\n CSSProperties,\n ReactNode,\n useCallback,\n} from 'react'\n\nimport { useLongPress } from '../../hooks/useLongPress'\n\nimport { useNumberInputContext, useStepperContext } from './context'\n\nexport interface StepperButtonProps {\n className?: string\n style?: CSSProperties\n /** Replaces the default arrow. Size it with the `--stepper-icon-size` variable. */\n children?: ReactNode\n}\n\ntype Props = StepperButtonProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof StepperButtonProps>\n\n/**\n * Shared body of `IncrementStepper` and `DecrementStepper`: the two differ only\n * in which way they move the value and which arrow they draw.\n */\nexport function StepperButton({\n direction,\n variant,\n icon,\n className,\n style,\n children,\n onPointerDown,\n ...props\n}: Props & {\n direction: 1 | -1\n variant: 'increment' | 'decrement'\n icon: ReactNode\n}) {\n const { step, readonly, atMin, atMax, nudge } = useNumberInputContext()\n const stepper = useStepperContext()\n\n const press = useLongPress(\n useCallback(() => {\n // Once the pointer has actually travelled, the drag on `Stepper` owns the\n // value; repeating on top of it would move it twice.\n if (stepper?.draggingRef.current) return\n nudge(direction, ['raw', step])\n }, [stepper, nudge, direction, step]),\n )\n\n return (\n // eslint-disable-next-line jsx-a11y/role-supports-aria-props\n <div\n className={clsx(`tremolo-number-input-${variant}-stepper`, className)}\n role=\"button\"\n tabIndex={-1}\n // A bare arrow has no accessible name of its own. Overridable, since a\n // caller may need it in their own language.\n aria-label={direction > 0 ? 'Increment' : 'Decrement'}\n aria-disabled={direction > 0 ? atMax : atMin}\n aria-readonly={readonly}\n style={style}\n onPointerDown={(event) => {\n if (!readonly) press()\n onPointerDown?.(event)\n }}\n {...props}\n >\n {children ?? icon}\n </div>\n )\n}\n\nexport function StepperArrow({ up }: { up: boolean }) {\n return (\n <svg\n className=\"tremolo-number-input-stepper-icon\"\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={up ? '18 15 12 9 6 15' : '6 9 12 15 18 9'} />\n </svg>\n )\n}\n","import { ComponentPropsWithoutRef } from 'react'\n\nimport {\n StepperArrow,\n StepperButton,\n StepperButtonProps,\n} from './stepperButton'\n\nexport type DecrementStepperProps = StepperButtonProps\n\n/** Lowers the value by one `step`, repeating while held. */\nexport function DecrementStepper(\n props: DecrementStepperProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof DecrementStepperProps>,\n) {\n return (\n <StepperButton\n direction={-1}\n variant=\"decrement\"\n icon={<StepperArrow up={false} />}\n {...props}\n />\n )\n}\n","import { ComponentPropsWithoutRef } from 'react'\n\nimport {\n StepperArrow,\n StepperButton,\n StepperButtonProps,\n} from './stepperButton'\n\nexport type IncrementStepperProps = StepperButtonProps\n\n/** Raises the value by one `step`, repeating while held. */\nexport function IncrementStepper(\n props: IncrementStepperProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof IncrementStepperProps>,\n) {\n return (\n <StepperButton\n direction={1}\n variant=\"increment\"\n icon={<StepperArrow up />}\n {...props}\n />\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, Ref } from 'react'\n\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { useNumberInputContext } from './context'\n\nexport interface NumberInputFieldProps {\n /**\n * Select the text when the input takes focus. `'number'` selects the leading\n * number, leaving whatever the format appended to it.\n * @default 'none'\n */\n selectOnFocus?: 'all' | 'number' | 'none'\n /**\n * Commit and leave the input when Enter is pressed. Enter commits either way.\n * @default true\n */\n blurOnEnter?: boolean\n\n className?: string\n style?: CSSProperties\n ref?: Ref<HTMLInputElement>\n}\n\n/** The leading number of the displayed text, whatever the format put around it. */\nconst NUMBER_PREFIX = /^\\s*-?[\\d.,]*/\n\n/**\n * The text field of a `NumberInput`, and the only place the value can be typed.\n *\n * While the user types, their own text stands rather than `format(value)`, so\n * that a half-finished entry is not rewritten under the caret.\n */\nexport function InputField({\n selectOnFocus = 'none',\n blurOnEnter = true,\n className,\n style,\n ref,\n onFocus,\n onBlur,\n onKeyDown,\n ...props\n}: NumberInputFieldProps &\n Omit<\n ComponentPropsWithoutRef<'input'>,\n keyof NumberInputFieldProps | 'type' | 'value' | 'defaultValue'\n >) {\n const {\n value,\n min,\n max,\n step,\n disabled,\n readonly,\n keyboard,\n text,\n outOfRange,\n setDraft,\n commitDraft,\n nudge,\n inputRef,\n } = useNumberInputContext()\n\n const composedRef = useComposedRefs<HTMLInputElement>(ref, inputRef)\n\n return (\n <input\n ref={composedRef}\n className={clsx('tremolo-number-input-field', className)}\n // Not type=\"number\": that brings native spinners and a value the browser\n // parses itself, neither of which survives a unit suffix.\n type=\"text\"\n inputMode=\"decimal\"\n role=\"spinbutton\"\n value={text}\n readOnly={readonly}\n aria-disabled={disabled}\n aria-readonly={readonly}\n aria-valuenow={value}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuetext={text}\n step={step}\n data-out-of-range={outOfRange}\n style={style}\n onChange={(event) => setDraft(event.currentTarget.value)}\n onFocus={(event) => {\n const input = event.currentTarget\n if (selectOnFocus == 'all') {\n input.setSelectionRange(0, input.value.length)\n } else if (selectOnFocus == 'number') {\n input.setSelectionRange(\n 0,\n input.value.match(NUMBER_PREFIX)?.[0].length ?? 0,\n )\n }\n onFocus?.(event)\n }}\n onBlur={(event) => {\n commitDraft()\n onBlur?.(event)\n }}\n onKeyDown={(event) => {\n const key = event.key\n if (key == 'Enter') {\n commitDraft()\n if (blurOnEnter) event.currentTarget.blur()\n } else if (\n keyboard &&\n !readonly &&\n (key == 'ArrowUp' || key == 'ArrowDown')\n ) {\n event.preventDefault()\n nudge(key == 'ArrowUp' ? 1 : -1, keyboard)\n }\n onKeyDown?.(event)\n }}\n {...props}\n />\n )\n}\n","import { useEffect, useState } from 'react'\n\nimport { createDrag } from '@tremolo-ui/dom'\n\nimport { useCallbackRef } from './_internal/useCallbackRef'\n\ninterface UseDragProps {\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 /** CSS cursor to show while dragging. Applied to the element itself. */\n cursor?: string\n\n onDrag?: (x: number, y: number, deltaX: number, deltaY: number) => void\n onDragStart?: () => void\n onDragEnd?: () => void\n}\n\n/**\n * Track a pointer drag on an element.\n *\n * @returns a ref callback to attach to the element being dragged\n */\nexport function useDrag<T extends Element>({\n threshold = 1,\n cursor,\n onDrag,\n onDragStart,\n onDragEnd,\n}: UseDragProps): (node: T | null) => void {\n const dragHandler = useCallbackRef(onDrag)\n const dragStartHandler = useCallbackRef(onDragStart)\n const dragEndHandler = useCallbackRef(onDragEnd)\n\n // The node is held in state rather than bound in the ref callback itself, so\n // that re-attaching the ref with the same node does not restart the drag.\n // React re-attaches on every render when the caller passes an inline ref.\n const [node, setNode] = useState<T | null>(null)\n\n useEffect(() => {\n if (!node) return\n\n const instance = createDrag(node, {\n threshold,\n cursor,\n onDragStart: () => dragStartHandler(),\n onDrag: ({ x, y, deltaX, deltaY }) => dragHandler(x, y, deltaX, deltaY),\n onDragEnd: () => dragEndHandler(),\n })\n\n return () => instance.destroy()\n }, [node, threshold, cursor, dragHandler, dragStartHandler, dragEndHandler])\n\n return setNode\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n CSSProperties,\n ReactNode,\n Ref,\n useMemo,\n useRef,\n} from 'react'\n\nimport { applyDelta } from '@tremolo-ui/functions'\n\nimport { useDrag } from '../../hooks/useDrag'\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { StepperProvider, useNumberInputContext } from './context'\n\nexport interface StepperProps {\n className?: string\n style?: CSSProperties\n /** `<NumberInput.IncrementStepper />` and `<NumberInput.DecrementStepper />` go here. */\n children?: ReactNode\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * The area the steppers sit in, and a drag handle in its own right: dragging it\n * up and down moves the value one `step` every `drag` pixels.\n *\n * The drag lives here rather than on `InputField` because `createDrag` turns\n * off text selection on whatever element it is attached to.\n */\nexport function Stepper({\n className,\n style,\n children,\n ref,\n ...props\n}: StepperProps & Omit<ComponentPropsWithoutRef<'div'>, keyof StepperProps>) {\n const { value, step, readonly, drag, range, changeValue } =\n useNumberInputContext()\n\n /**\n * Set once the drag has actually moved the value, so that the press-and-hold\n * repeat of a stepper stands down and leaves the value to the drag. A ref,\n * because it is read from inside the repeat rather than rendered.\n */\n const draggingRef = useRef(false)\n /**\n * Where the drag started, taken on the first move rather than on pointer\n * down: the steppers act on pointer down, so by then the value may already\n * have been nudged once, and the drag should carry on from there.\n */\n const originRef = useRef<{ y: number; value: number } | null>(null)\n\n const dragRefCallback = useDrag<HTMLDivElement>({\n threshold: 1,\n cursor: readonly ? undefined : 'ns-resize',\n onDragStart: () => {\n originRef.current = null\n draggingRef.current = false\n },\n onDrag: (_x, y) => {\n if (readonly || drag == null) return\n if (!originRef.current) {\n originRef.current = { y, value }\n return\n }\n // Dragging up raises the value, as on a knob.\n const steps = Math.round(-(y - originRef.current.y) / drag)\n if (steps == 0) return\n draggingRef.current = true\n // The same pipeline the wheel and the arrow keys use. Counting from where\n // the drag started keeps it from accumulating a rounding error.\n changeValue(\n applyDelta(originRef.current.value, steps, ['raw', step], range),\n )\n },\n onDragEnd: () => {\n draggingRef.current = false\n },\n })\n\n const composedRef = useComposedRefs<HTMLDivElement>(\n ref,\n drag != null && !readonly ? dragRefCallback : undefined,\n )\n\n const context = useMemo(() => ({ draggingRef }), [])\n\n return (\n <StepperProvider value={context}>\n <div\n ref={composedRef}\n className={clsx('tremolo-number-input-stepper', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n </StepperProvider>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n CSSProperties,\n forwardRef,\n ReactNode,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport {\n applyDelta,\n clamp,\n formatValue,\n InputEventOption,\n linearScale,\n parseValue,\n type Scale,\n type Units,\n type ValueRange,\n} from '@tremolo-ui/functions'\n\nimport { useWheel } from '../../hooks/useWheel'\n\nimport { NumberInputProvider } from './context'\nimport { DecrementStepper } from './DecrementStepper'\nimport { IncrementStepper } from './IncrementStepper'\nimport { InputField } from './InputField'\nimport { Stepper } from './Stepper'\n\nexport interface NumberInputProps {\n /**\n * The value. What the input shows is `format(value)`, except while the user\n * is typing, when their own text stands until it is committed.\n */\n value: number\n\n min?: number\n max?: number\n step?: number\n /**\n * How the value is distributed across the travel of a drag or a\n * `'normalized'` wheel / keyboard nudge.\n *\n * @default linearScale\n */\n scale?: Scale\n\n /**\n * Unit to display the value in, or a list to pick from by magnitude.\n * Builds the default `format` and `parse`.\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 * Digits after the decimal point, for the default `format`.\n *\n * @example\n * // units={[['Hz', 1], ['kHz', 1000]]} digit={2}\n * // 100 -> 100.00Hz, 1600 -> 1.60kHz\n */\n digit?: number\n /** Render the value as text. Takes precedence over `units` / `digit`. */\n format?: (value: number) => string\n /** Read a value back out of the text. Takes precedence over `units`. */\n parse?: (text: string) => number\n\n /**\n * Keep the value within `min` and `max` when it is committed or stepped.\n * Typing is never clamped, so that a value can be entered digit by digit.\n * @default true\n */\n clampValue?: boolean\n\n /**\n * Wheel control option. Only applies while the focus is inside, so that\n * scrolling past the input does not change it.\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n /**\n * Pixels of vertical drag on `Stepper` that move the value by one `step`.\n * If null, no event will be triggered\n * @default 1\n */\n drag?: number | null\n\n /**\n * Only the appearance will change.\n * Please consider using with readonly.\n * aria-disabled property is also applied.\n */\n disabled?: boolean\n /**\n * Make the value unchangeable.\n * aria-readonly property is also applied.\n */\n readonly?: boolean\n\n className?: string\n style?: CSSProperties\n onChange?: (value: number) => void\n\n /**\n * The input renders exactly what you compose here; there is no default\n * markup to fall back to.\n *\n * @example\n * <NumberInput.Root value={value} min={0} max={100} onChange={setValue}>\n * <NumberInput.InputField />\n * <NumberInput.Stepper>\n * <NumberInput.IncrementStepper />\n * <NumberInput.DecrementStepper />\n * </NumberInput.Stepper>\n * </NumberInput.Root>\n */\n children: ReactNode\n}\n\nexport interface NumberInputMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = NumberInputProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof NumberInputProps>\n\nexport const Root = forwardRef<NumberInputMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n scale = linearScale,\n units,\n digit,\n format: formatProp,\n parse: parseProp,\n clampValue = true,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n drag = 1,\n disabled = false,\n readonly = false,\n className,\n style,\n onChange,\n children,\n ...props\n }: Props,\n forwardedRef,\n ) => {\n // --- state and ref ---\n const inputRef = useRef<HTMLInputElement>(null)\n /**\n * The text being typed. The only state here: it is not a copy of `value`,\n * but the half-finished entry that has no value to be derived from yet.\n */\n const [draft, setDraft] = useState<string | null>(null)\n\n // --- interpret props ---\n const format = useCallback(\n (v: number) =>\n formatProp ? formatProp(v) : formatValue(v, units, digit),\n [formatProp, units, digit],\n )\n const parse = useCallback(\n (t: string) => (parseProp ? parseProp(t) : parseValue(t, units)),\n [parseProp, units],\n )\n\n // An unbounded end, and a range the caller opted out of enforcing, both\n // become the widest range the value pipeline can express.\n const range: ValueRange = useMemo(\n () => ({\n min: (clampValue ? min : undefined) ?? Number.MIN_SAFE_INTEGER,\n max: (clampValue ? max : undefined) ?? Number.MAX_SAFE_INTEGER,\n step,\n scale,\n }),\n [clampValue, min, max, step, scale],\n )\n\n const text = draft ?? format(value)\n const editing = draft != null\n const outOfRange =\n !editing &&\n ((min != undefined && value < min) || (max != undefined && value > max))\n\n // --- internal functions ---\n const handleDraft = useCallback(\n (next: string) => {\n if (readonly) return\n setDraft(next)\n // Deliberately unclamped: clamping here would make \"1500\" impossible\n // to type into an input whose max is 100.\n const parsed = parse(next)\n if (Number.isFinite(parsed)) onChange?.(parsed)\n },\n [readonly, parse, onChange],\n )\n\n const changeValue = useCallback(\n (next: number) => {\n if (readonly) return\n setDraft(null)\n if (next != value) onChange?.(next)\n },\n [readonly, value, onChange],\n )\n\n const commitDraft = useCallback(() => {\n if (draft == null || readonly) return\n // `range` is already the widest possible range when clampValue is off.\n changeValue(clamp(parse(draft), range.min, range.max))\n }, [draft, readonly, parse, range, changeValue])\n\n const nudge = useCallback(\n (direction: number, option: InputEventOption) => {\n changeValue(applyDelta(value, direction, option, range))\n },\n [changeValue, value, range],\n )\n\n // --- hooks ---\n const wheelRefCallback = useWheel<HTMLDivElement>(\n (event) => {\n if (!wheel || readonly || event.deltaY == 0) return\n event.preventDefault()\n nudge(-Math.sign(event.deltaY), wheel)\n },\n { requireFocus: true },\n )\n\n const context = useMemo(\n () => ({\n value,\n min,\n max,\n step,\n scale,\n disabled,\n readonly,\n clampValue,\n range,\n keyboard,\n text,\n editing,\n outOfRange,\n atMin: clampValue && min != undefined && value <= min,\n atMax: clampValue && max != undefined && value >= max,\n drag,\n format,\n parse,\n setDraft: handleDraft,\n commitDraft,\n changeValue,\n nudge,\n inputRef,\n }),\n [\n value,\n min,\n max,\n step,\n scale,\n disabled,\n readonly,\n clampValue,\n range,\n keyboard,\n text,\n editing,\n outOfRange,\n drag,\n format,\n parse,\n handleDraft,\n commitDraft,\n changeValue,\n nudge,\n ],\n )\n\n useImperativeHandle(forwardedRef, () => {\n return {\n focus() {\n inputRef.current?.focus()\n },\n blur() {\n inputRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <NumberInputProvider value={context}>\n <div\n ref={wheelRefCallback}\n className={clsx('tremolo-number-input', className)}\n aria-disabled={disabled}\n aria-readonly={readonly}\n style={style}\n {...props}\n >\n {children}\n </div>\n </NumberInputProvider>\n )\n },\n)\n\n/**\n * Input with some useful functions for entering numerical values.\n */\nexport const NumberInput = {\n Root,\n InputField,\n Stepper,\n IncrementStepper,\n DecrementStepper,\n}\n\nexport { useNumberInputContext } from './context'\nexport { type NumberInputFieldProps } from './InputField'\nexport { type StepperProps } from './Stepper'\nexport { type IncrementStepperProps } from './IncrementStepper'\nexport { type DecrementStepperProps } from './DecrementStepper'\n","export type KeyboardShortcuts = {\n /**\n * Keys laid out from `noteRange.first`, one entry per semitone.\n *\n * An empty string leaves that note without a shortcut: `KeyboardEvent.key` is\n * never empty, so the entry can never match. Use it to skip the black keys\n * (see {@link SHORTCUTS.HOME_ROW_NATURAL}) and keep the remaining entries\n * lined up with the notes.\n */\n keys: string[]\n}\n\n/**\n * Ready-made keyboard layouts. Both assume `noteRange.first` is a C.\n */\nexport const SHORTCUTS = {\n /** Every semitone from C, over the two rows of a QWERTY keyboard. */\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 /** The white keys only, on the home row. Black keys have no shortcut. */\n HOME_ROW_NATURAL: {\n keys: [\n 'a',\n '',\n 's',\n '',\n 'd',\n 'f',\n '',\n 'g',\n '',\n 'h',\n '',\n 'j',\n 'k',\n '',\n 'l',\n '',\n ';',\n ],\n },\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n CSSProperties,\n forwardRef,\n ReactNode,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport { createPianoInput, type PianoInputInstance } from '@tremolo-ui/dom'\nimport {\n blackKeyWidth,\n getNoteRangeArray,\n isWhiteKey,\n noteKey,\n notePosition,\n pianoWidth,\n type NoteRange,\n type PianoLayout,\n} from '@tremolo-ui/functions'\n\nimport { useEventListener } from '../../hooks/useEventListener'\n\nimport { KeyboardShortcuts } from './keyboardShortcuts'\n\n/**\n * `style` that also takes CSS custom properties, which is how a key's colours\n * are set: see `index.css` for the ones each key type reads.\n */\nexport type CSSVariables = Record<`--${string}`, string | number | undefined>\n\n/**\n * What {@link PianoProps.keyProps} may return for one key.\n *\n * `data-*` attributes are spelled out because TypeScript only allows them on\n * JSX syntax, not on an object type, and selecting on one is the usual way to\n * mark a key out.\n */\nexport type KeyAttributes = Omit<ComponentPropsWithoutRef<'div'>, 'style'> & {\n style?: CSSProperties & CSSVariables\n} & Record<`data-${string}`, string | number | boolean | undefined>\n\n/** What a key is, when {@link PianoProps.label} or `keyProps` is asked about it. */\nexport interface KeyState {\n /** Position in the note range, counting from `noteRange.first`. */\n index: number\n keyType: 'white' | 'black'\n /** Whether the note is currently sounding. */\n active: boolean\n /** Whether the note is above {@link PianoProps.midiMax} and cannot sound. */\n disabled: boolean\n}\n\nexport interface PianoProps {\n noteRange: NoteRange\n\n /**\n * Let a pointer slide from one key to the next while it is down.\n *\n * @default true\n */\n glissando?: boolean\n\n /**\n * Highest note that can sound. Keys above it are drawn `aria-disabled`.\n *\n * @default 127\n */\n midiMax?: number\n\n keyboardShortcuts?: KeyboardShortcuts\n\n /**\n * Fill the parent element, deriving the width of a white key from it.\n * {@link PianoProps.whiteKeyWidth} is ignored.\n *\n * @default false\n */\n fill?: boolean\n\n /** @default 40 */\n whiteKeyWidth?: number\n /**\n * Space between two white keys.\n * @default 1\n */\n keyGap?: number\n /**\n * Width of a black key, as a fraction of {@link PianoProps.whiteKeyWidth}.\n * @default 0.65\n */\n blackKeyWidthRatio?: number\n /**\n * Height of a black key, as a fraction of the height of the keyboard.\n * @default 0.6\n */\n blackKeyHeightRatio?: number\n\n /** @default `fill ? '100%' : 160` */\n height?: number | string\n\n style?: CSSProperties & CSSVariables\n\n /**\n * What to draw inside a key. `''`, `null` and `undefined` leave it bare, so\n * a layout with gaps — {@link SHORTCUTS.HOME_ROW_NATURAL}, say — needs no\n * special casing.\n */\n label?: (note: number, state: KeyState) => ReactNode\n\n /**\n * Extra props for one key, by note: a class, a style, a `data-*` attribute\n * to select on.\n *\n * The geometry of the key (`left`, `width`, `height`) is applied after the\n * returned `style` and cannot be overridden, so a key cannot be drawn\n * somewhere other than where it responds.\n *\n * @example highlight the notes of a scale\n * ```tsx\n * keyProps={(note) => ({ 'data-in-scale': inScale(note, root, 'major') })}\n * ```\n */\n keyProps?: (note: number, state: KeyState) => KeyAttributes\n\n onPlayNote?: (note: number, velocity?: number) => void\n onStopNote?: (note: number) => void\n}\n\nexport interface PianoMethods {\n playNote: (note: number, velocity?: number) => void\n stopNote: (note: number) => void\n}\n\ntype Props = PianoProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof PianoProps>\n\nexport const Root = forwardRef<PianoMethods, Props>(function Root(\n {\n noteRange,\n glissando = true,\n midiMax = 127,\n keyboardShortcuts,\n fill = false,\n whiteKeyWidth = 40,\n keyGap = 1,\n blackKeyWidthRatio = 0.65,\n blackKeyHeightRatio = 0.6,\n height = fill ? '100%' : 160,\n style,\n className,\n label,\n keyProps,\n onPlayNote,\n onStopNote,\n ...props\n },\n forwardedRef,\n) {\n // See useDrag for why the node is held in state rather than a ref: an inline\n // ref would be re-attached on every render and tear the instance down.\n const [node, setNode] = useState<HTMLDivElement | null>(null)\n const [activeNotes, setActiveNotes] = useState<number[]>([])\n /** Set while `fill` is on, measured from the parent. */\n const [filledKeyWidth, setFilledKeyWidth] = useState(whiteKeyWidth)\n\n const notes = useMemo(() => getNoteRangeArray(noteRange), [noteRange])\n const whiteKeyCount = useMemo(() => notes.filter(isWhiteKey).length, [notes])\n\n const layout: PianoLayout = useMemo(\n () => ({\n noteRange,\n whiteKeyWidth: fill ? filledKeyWidth : whiteKeyWidth,\n keyGap,\n blackKeyWidthRatio,\n blackKeyHeightRatio,\n }),\n [\n noteRange,\n fill,\n filledKeyWidth,\n whiteKeyWidth,\n keyGap,\n blackKeyWidthRatio,\n blackKeyHeightRatio,\n ],\n )\n\n // Read when the instance is created. The effect below keeps it current, and\n // runs right after, so a stale handler is replaced within the same commit.\n const latest = useRef({ layout, glissando, midiMax, onPlayNote, onStopNote })\n const instanceRef = useRef<PianoInputInstance | null>(null)\n\n useEffect(() => {\n if (!node) return\n\n const instance = createPianoInput(node, {\n layout: latest.current.layout,\n glissando: latest.current.glissando,\n midiMax: latest.current.midiMax,\n onPlayNote: (note, velocity) =>\n latest.current.onPlayNote?.(note, velocity),\n onStopNote: (note) => latest.current.onStopNote?.(note),\n onActiveNotesChange: setActiveNotes,\n })\n instanceRef.current = instance\n\n return () => {\n instanceRef.current = null\n instance.destroy()\n }\n // Only the element decides how the instance is wired. Everything else is\n // pushed with update() below, so that changing the layout mid-drag — the\n // parent being resized under `fill`, say — does not abort the drag.\n }, [node])\n\n // Runs after every render.\n useEffect(() => {\n latest.current = { layout, glissando, midiMax, onPlayNote, onStopNote }\n instanceRef.current?.update({ layout, glissando, midiMax })\n })\n\n useEffect(() => {\n if (!fill || !node) return\n const parent = node.parentElement\n if (!parent) throw new Error(\"doesn't have a parent element.\")\n\n const resizeObserver = new ResizeObserver(() => {\n setFilledKeyWidth(node.clientWidth / whiteKeyCount - keyGap)\n })\n resizeObserver.observe(parent)\n return () => resizeObserver.disconnect()\n }, [fill, node, whiteKeyCount, keyGap])\n\n /** The note a shortcut key plays, or null when it has none. */\n function shortcutNote(key: string) {\n if (!keyboardShortcuts || key === '') return null\n const index = keyboardShortcuts.keys.indexOf(key)\n return index === -1 ? null : noteRange.first + index\n }\n\n useEventListener(globalThis.window, 'keydown', (e) => {\n if (e.repeat) return\n const note = shortcutNote(e.key)\n if (note !== null) instanceRef.current?.noteOn(note, { source: 'keyboard' })\n })\n\n useEventListener(globalThis.window, 'keyup', (e) => {\n const note = shortcutNote(e.key)\n if (note !== null)\n instanceRef.current?.noteOff(note, { source: 'keyboard' })\n })\n\n useImperativeHandle(\n forwardedRef,\n () => ({\n playNote: (note, velocity) =>\n instanceRef.current?.noteOn(note, { source: 'api', velocity }),\n stopNote: (note) => instanceRef.current?.noteOff(note, { source: 'api' }),\n }),\n [],\n )\n\n return (\n <div\n ref={setNode}\n className={clsx('tremolo-piano', className)}\n style={{\n width: fill ? '100%' : pianoWidth(layout),\n height,\n ...style,\n }}\n {...props}\n >\n {notes.map((note, index) => {\n const keyType = isWhiteKey(note) ? 'white' : 'black'\n const state: KeyState = {\n index,\n keyType,\n active: activeNotes.includes(note),\n disabled: note > midiMax,\n }\n\n const {\n className: keyClassName,\n style: keyStyle,\n ...rest\n } = keyProps?.(note, state) ?? {}\n\n const content = label?.(note, state)\n\n return (\n <div\n key={note}\n className={clsx(`tremolo-piano-${keyType}-key`, keyClassName)}\n data-note={note}\n data-note-key={noteKey(note)}\n data-active={state.active}\n aria-disabled={state.disabled}\n {...rest}\n style={{\n ...keyStyle,\n left: notePosition(note, layout),\n width:\n keyType === 'white'\n ? layout.whiteKeyWidth\n : blackKeyWidth(layout),\n height:\n keyType === 'white' ? '100%' : `${blackKeyHeightRatio * 100}%`,\n }}\n >\n {content !== '' && content !== null && content !== undefined && (\n <div className=\"tremolo-piano-key-label-wrapper\">\n <div className=\"tremolo-piano-key-label\">{content}</div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )\n})\n\n/**\n * Customizable piano component.\n */\nexport const Piano = { Root }\n\nexport { type KeyboardShortcuts, SHORTCUTS } from './keyboardShortcuts'\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nexport interface PointsEditorBackgroundProps {\n /** Whatever the points are placed over: a graph, a canvas, an image. */\n children?: ReactNode\n}\n\nexport function Background({\n className,\n children,\n ...props\n}: PointsEditorBackgroundProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorBackgroundProps>) {\n return (\n <div\n className={clsx('tremolo-points-editor-background', className)}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import { createContext, RefObject, useContext } from 'react'\n\nimport type { InputEventOption } from '@tremolo-ui/functions'\n\nimport { Cursor } from '../_util'\n\nexport type PointsEditorContextValue = {\n disabled: boolean\n readonly: boolean\n /** Inherited by every `Point`; `null` turns the wheel off. */\n wheel: InputEventOption | null\n /** Inherited by every `Point`; `null` turns the keyboard off. */\n keyboard: InputEventOption | null\n externalStyles: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n\n /**\n * `Container` registers its element here; `Point` normalizes the pointer\n * against it, so a point is placed by its position within the container.\n */\n containerRef: RefObject<HTMLDivElement | null>\n}\n\nconst PointsEditorContext = createContext<PointsEditorContextValue | null>(null)\n\nexport const PointsEditorProvider = PointsEditorContext.Provider\n\n/**\n * The settings `Root` was given, for the subcomponents to read. There is no\n * state to keep in sync: a point's value belongs to the `Point` that draws it.\n */\nexport function usePointsEditorContext(): PointsEditorContextValue\nexport function usePointsEditorContext<T>(\n selector: (state: PointsEditorContextValue) => T,\n): T\nexport function usePointsEditorContext<T>(\n selector?: (state: PointsEditorContextValue) => T,\n) {\n const context = useContext(PointsEditorContext)\n if (!context)\n throw new Error('Missing PointsEditorContext.Provider in the tree')\n return selector ? selector(context) : context\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode, Ref } from 'react'\n\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { usePointsEditorContext } from './context'\n\nexport interface PointsEditorContainerProps {\n /** `<PointsEditor.Point />` goes here. */\n children?: ReactNode\n ref?: Ref<HTMLDivElement>\n}\n\nexport function Container({\n children,\n className,\n ref,\n ...props\n}: PointsEditorContainerProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorContainerProps>) {\n const containerRef = usePointsEditorContext((s) => s.containerRef)\n\n // The container is what the pointer position is normalized against, so the\n // context ref is composed with any ref the caller passed.\n const composedRef = useComposedRefs<HTMLDivElement>(ref, containerRef)\n\n return (\n <div\n ref={composedRef}\n className={clsx('tremolo-points-editor-container', className)}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, useCallback, useState } from 'react'\n\nimport { applyDelta, clamp, InputEventOption } from '@tremolo-ui/functions'\n\nimport { useDragValue } from '../../hooks/useDragValue'\nimport { useWheel } from '../../hooks/useWheel'\nimport { addUserSelectNone, removeUserSelectNone } from '../_util'\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { usePointsEditorContext } from './context'\n\nexport type PointBaseType = { x: number; y: number }\n\nexport function clampPoint(\n point: PointBaseType,\n min?: Partial<PointBaseType>,\n max?: Partial<PointBaseType>,\n) {\n const { x, y } = point\n const newX = clamp(x, min?.x ?? 0, max?.x ?? 1)\n const newY = clamp(y, min?.y ?? 0, max?.y ?? 1)\n return { x: newX, y: newY }\n}\n\nexport interface PointProps<T extends PointBaseType> {\n value: T\n min?: Partial<PointBaseType>\n max?: Partial<PointBaseType>\n\n size?: number | string\n width?: number | string\n height?: number | string\n color?: string\n\n /** Overrides the `disabled` of `PointsEditor.Root`. */\n disabled?: boolean\n /** Overrides the `readonly` of `PointsEditor.Root`. */\n readonly?: boolean\n\n /** Overrides the `wheel` of `PointsEditor.Root`. */\n wheel?: InputEventOption | null\n /** Overrides the `keyboard` of `PointsEditor.Root`. */\n keyboard?: InputEventOption | null\n\n onChange?: (value: PointBaseType) => void\n onDragStart?: (value: PointBaseType) => void\n onDragEnd?: (value: PointBaseType) => void\n}\n\n/**\n * A point is placed by its position within the container, so its value is a\n * position: 0..1 on each axis, with y growing downwards.\n */\nconst AXIS = { min: 0, max: 1 }\n\nexport function Point<T extends PointBaseType>({\n value,\n min,\n max,\n size,\n width = 16,\n height = 16,\n color,\n\n disabled: _disabled,\n readonly: _readonly,\n wheel: _wheel,\n keyboard: _keyboard,\n\n onChange,\n onDragStart,\n onDragEnd,\n\n className,\n style,\n onPointerDown,\n onKeyDown,\n ...props\n}: PointProps<T> & Omit<ComponentPropsWithoutRef<'div'>, keyof PointProps<T>>) {\n const {\n containerRef,\n externalStyles,\n disabled: rootDisabled,\n readonly: rootReadonly,\n wheel: rootWheel,\n keyboard: rootKeyboard,\n } = usePointsEditorContext()\n\n const disabled = _disabled ?? rootDisabled\n const readonly = _readonly ?? rootReadonly\n // `null` means \"no event\" and has to survive the fallback, so `??` is not\n // enough: only an omitted prop inherits from the root.\n const wheel = _wheel === undefined ? rootWheel : _wheel\n const keyboard = _keyboard === undefined ? rootKeyboard : _keyboard\n\n // Compared against the focus below, so the point needs its own element.\n const [element, setElement] = useState<HTMLDivElement | null>(null)\n\n // The value is the position itself: no scaling, and no rounding to a step.\n const { refCallback: dragRefCallback, dragging } =\n useDragValue<HTMLDivElement>({\n axis: AXIS,\n baseElementRef: containerRef,\n cursor: readonly ? undefined : externalStyles.cursor,\n onChange: ([x, y]) => {\n if (readonly) return\n\n onChange?.(clampPoint({ x, y }, min, max))\n },\n onDragStart: ([x, y]) => {\n if (readonly) return\n if (externalStyles.userSelectNone) addUserSelectNone()\n\n onDragStart?.(clampPoint({ x, y }, min, max))\n },\n onDragEnd: ([x, y]) => {\n if (readonly) return\n if (externalStyles.userSelectNone) removeUserSelectNone()\n\n onDragEnd?.(clampPoint({ x, y }, min, max))\n },\n })\n\n const nudge = useCallback(\n (axis: 'x' | 'y', direction: number, option: InputEventOption) => {\n const next = applyDelta(value[axis], direction, option, AXIS)\n onChange?.(clampPoint({ ...value, [axis]: next }, min, max))\n },\n [value, min, max, onChange],\n )\n\n // The listener sits on the container rather than on the point: a wheel event\n // only reaches what the cursor is over, and a point is a 16px target. Every\n // point sees the event and the focused one acts, so the wheel works anywhere\n // over the editor, the way it does for Slider and XYPad.\n //\n // The focus test is an identity check, not `contains`: with `contains` every\n // point would match the container's focus and they would all move at once.\n useWheel(\n (event) => {\n if (!onChange || readonly || !wheel) return\n if (!element || element.ownerDocument.activeElement !== element) return\n event.preventDefault()\n // Scrolling up moves the point towards y = 0; shift switches to x.\n const axis = event.shiftKey ? 'x' : 'y'\n const direction = event.deltaY < 0 ? -1 : 1\n nudge(axis, direction, wheel)\n },\n { target: containerRef },\n )\n\n const refCallback = useComposedRefs<HTMLDivElement>(\n dragRefCallback,\n setElement,\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onChange || readonly || !keyboard) return\n const key = event.key\n if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {\n event.preventDefault()\n // y grows downwards, so ArrowUp moves the point towards 0.\n const axis = key === 'ArrowRight' || key === 'ArrowLeft' ? 'x' : 'y'\n const direction = key === 'ArrowLeft' || key === 'ArrowUp' ? -1 : 1\n nudge(axis, direction, keyboard)\n }\n }\n\n const colors: Record<string, string | undefined> = {\n '--color': color,\n }\n\n return (\n // The point is a drag handle rather than a control of a known kind: it has\n // no single value to announce, so there is no role that fits it.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n ref={refCallback}\n className={clsx('tremolo-points-editor-point', className)}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n aria-disabled={disabled}\n aria-readonly={readonly}\n data-dragging={dragging}\n style={{\n ...colors,\n width: size ?? width,\n height: size ?? height,\n left: `${value.x * 100}%`,\n top: `${value.y * 100}%`,\n ...style,\n }}\n onPointerDown={onPointerDown}\n onKeyDown={(event) => {\n handleKeyDown(event)\n onKeyDown?.(event)\n }}\n {...props}\n />\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n ReactNode,\n useMemo,\n useRef,\n} from 'react'\n\nimport { InputEventOption } from '@tremolo-ui/functions'\n\nimport { Cursor } from '../_util'\n\nimport { Background } from './Background'\nimport { Container } from './Container'\nimport { PointsEditorProvider } from './context'\nimport { Point } from './Point'\n\n/*\nTODO:\n\n- 複数選択\n- modifier\n- grid\n*/\n\n/**\n * A point moves over 0..1 in both axes, so a nudge of 0.01 crosses the editor\n * in a hundred steps whatever its pixel size.\n */\nconst DEFAULT_INPUT_EVENT_OPTION: InputEventOption = ['normalized', 0.01]\n\nexport interface PointsEditorProps {\n width?: number | string\n height?: number | string\n\n /**\n * Only the appearance will change.\n * Please consider using with readonly.\n * aria-disabled property is also applied.\n */\n disabled?: boolean\n /**\n * Make the points unmovable.\n * aria-readonly property is also applied.\n */\n readonly?: boolean\n\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n\n /**\n * wheel control option for every `Point`. Shift selects the x axis.\n * If null, no event will be triggered\n *\n * A `Point` can override it with a `wheel` of its own.\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option for every `Point`, on the arrow keys.\n * If null, no event will be triggered\n *\n * A `Point` can override it with a `keyboard` of its own.\n */\n keyboard?: InputEventOption | null\n\n /**\n * The editor renders exactly what you compose here; there is no default\n * markup to fall back to.\n *\n * @example\n * <PointsEditor.Root>\n * <PointsEditor.Background>\n * <svg viewBox=\"0 0 200 100\">...</svg>\n * </PointsEditor.Background>\n * <PointsEditor.Container>\n * {points.map((point, i) => (\n * <PointsEditor.Point key={i} value={point} onChange={...} />\n * ))}\n * </PointsEditor.Container>\n * </PointsEditor.Root>\n */\n children: ReactNode\n}\n\ntype Props = PointsEditorProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorProps>\n\nexport const Root = forwardRef<HTMLDivElement, Props>(\n (\n {\n width = 200,\n height = 100,\n disabled = false,\n readonly = false,\n wheel = DEFAULT_INPUT_EVENT_OPTION,\n keyboard = DEFAULT_INPUT_EVENT_OPTION,\n externalStyles,\n style,\n className,\n children,\n ...props\n },\n forwardedRef,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n // Picked apart so that the memo below depends on values rather than on the\n // object literal a caller writes inline, which is new on every render.\n const { userSelectNone = true, cursor = 'grabbing' } = externalStyles ?? {}\n\n const context = useMemo(\n () => ({\n disabled,\n readonly,\n wheel,\n keyboard,\n externalStyles: { userSelectNone, cursor },\n containerRef,\n }),\n [disabled, readonly, wheel, keyboard, userSelectNone, cursor],\n )\n\n return (\n <PointsEditorProvider value={context}>\n <div\n ref={forwardedRef}\n className={clsx('tremolo-points-editor', className)}\n aria-disabled={disabled}\n aria-readonly={readonly}\n style={{\n width,\n height,\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n </PointsEditorProvider>\n )\n },\n)\n\n/**\n * Multiple Point Controller\n */\nexport const PointsEditor = {\n Root,\n Background,\n Container,\n Point,\n}\n\nexport {\n usePointsEditorContext,\n type PointsEditorContextValue,\n} from './context'\nexport { type PointsEditorBackgroundProps } from './Background'\nexport { type PointsEditorContainerProps } from './Container'\nexport { clampPoint, type PointBaseType, type PointProps } from './Point'\n","import { createContext, RefObject, useContext } from 'react'\n\nimport type { Scale } from '@tremolo-ui/functions'\n\nimport type { SliderThumbMethods } from './Thumb'\n\nexport type SliderContextValue = {\n value: number\n min: number\n max: number\n step: number\n /** How the value is distributed across the travel. */\n scale: Scale\n vertical: boolean\n reverse: boolean\n disabled: boolean\n readonly: boolean\n\n /**\n * Position of the thumb, 0-100, already accounting for the display direction\n * implied by `vertical` and `reverse`.\n */\n percent: number\n\n /** `Track` registers its element here; `Root` normalizes the pointer against it. */\n trackRef: RefObject<HTMLDivElement | null>\n /** `Thumb` registers itself here; `Root` focuses it when a drag starts. */\n thumbRef: RefObject<SliderThumbMethods | null>\n}\n\nconst SliderContext = createContext<SliderContextValue | null>(null)\n\nexport const SliderProvider = SliderContext.Provider\n\n/**\n * Everything here is derived during render, so there is no state to keep in\n * sync: `value` comes from the props of `Root` and the rest follows from it.\n */\nexport function useSliderContext(): SliderContextValue\nexport function useSliderContext<T>(\n selector: (state: SliderContextValue) => T,\n): T\nexport function useSliderContext<T>(\n selector?: (state: SliderContextValue) => T,\n) {\n const context = useContext(SliderContext)\n if (!context) throw new Error('Missing SliderContext.Provider in the tree')\n return selector ? selector(context) : context\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, useCallback } from 'react'\n\nimport { toFixed, xor } from '@tremolo-ui/functions'\n\nimport { useSliderContext } from './context'\nimport { MarksType } from './type'\n\nexport interface MarksOptionProps {\n // required\n value: number\n\n // optional\n type?: MarksType\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\nexport function MarksOption({\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}: MarksOptionProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof MarksOptionProps>) {\n const min = useSliderContext((s) => s.min)\n const max = useSliderContext((s) => s.max)\n const scale = useSliderContext((s) => s.scale)\n const vertical = useSliderContext((s) => s.vertical)\n const reverse = useSliderContext((s) => s.reverse)\n\n const calcPercent = useCallback(\n (value: number) => {\n // The marks have to sit on the same curve the thumb runs along.\n const percent = scale.normalize(value, min, max) * 100\n return toFixed(xor(vertical, reverse) ? 100 - percent : percent)\n },\n [vertical, reverse, max, min, scale],\n )\n\n return (\n <div\n className={clsx('tremolo-slider-marks-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-marks-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-marks-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 { decimalPart, toFixed } from '@tremolo-ui/functions'\n\nexport type MarksType = 'mark' | 'mark-number' | 'number'\nexport type MarksOptions = ['step', MarksType] | [number, MarksType]\n\nexport function generateOptionsList(\n options: MarksOptions,\n min: number,\n max: number,\n step: number,\n) {\n const optionsList: {\n value: number\n type: MarksType\n }[] = []\n const per = options[0] == 'step' ? step : options[0]\n const count = Math.floor(max / per) - Math.ceil(min / per) + 1\n for (let i = 0; i < count; i++) {\n const value = toFixed(\n per * (Math.ceil(min / per) + i),\n decimalPart(per)?.length,\n )\n optionsList.push({ value: value, type: options[1] })\n }\n return optionsList\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport { xor } from '@tremolo-ui/functions'\n\nimport { useSliderContext } from './context'\nimport { MarksOption } from './MarksOption'\nimport { generateOptionsList, MarksOptions } from './type'\n\nexport interface MarksProps {\n gap?: number | string\n options?: MarksOptions\n children?: ReactNode\n}\n\nexport function Marks({\n gap = 6,\n options,\n children,\n className,\n style,\n ...props\n}: MarksProps & Omit<ComponentPropsWithoutRef<'div'>, keyof MarksProps>) {\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-marks', 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 <MarksOption key={index} value={value} type={type} />\n })\n : children}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport {\n CSSProperties,\n ReactNode,\n Ref,\n useImperativeHandle,\n useRef,\n} from 'react'\n\nimport { useSliderContext } from './context'\n\nexport interface SliderThumbProps {\n /**\n * Size comes from the `--thumb-size` CSS variable on `Slider.Root`, so that\n * the root can reserve the matching amount of space around the track.\n */\n color?: string\n\n className?: string\n style?: CSSProperties\n children?: ReactNode\n ref?: Ref<SliderThumbMethods>\n}\n\nexport interface SliderThumbMethods {\n focus: () => void\n blur: () => void\n}\n\nexport function Thumb({\n color,\n children,\n className,\n style,\n ref,\n}: SliderThumbProps) {\n const elementRef = useRef<HTMLDivElement>(null)\n const { vertical, disabled, readonly, percent, thumbRef } = useSliderContext()\n\n const methods = () => ({\n focus() {\n elementRef.current?.focus()\n },\n blur() {\n elementRef.current?.blur()\n },\n })\n\n useImperativeHandle(ref, methods, [])\n // Root focuses the thumb when a drag starts, wherever the user placed it.\n\n useImperativeHandle(thumbRef, methods, [])\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={elementRef}\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 ...style,\n }}\n ></div>\n )}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode, Ref } from 'react'\n\nimport { styleHelper, xor } from '@tremolo-ui/functions'\n\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { useSliderContext } from './context'\n\nexport const defaultLength = 140\nexport const defaultThickness = 10\n\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 /** `<Slider.Thumb />` goes here. */\n children?: ReactNode\n ref?: Ref<HTMLDivElement>\n}\n\nexport function Track({\n length = defaultLength,\n thickness = defaultThickness,\n active,\n inactive,\n children,\n className,\n style,\n defaultStyle = true,\n ref,\n ...props\n}: SliderTrackProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof SliderTrackProps>) {\n const { vertical, reverse, disabled, percent, trackRef } = useSliderContext()\n\n // The track is what the pointer position is normalized against, so the\n // context ref is composed with any ref the caller passed.\n const composedRef = useComposedRefs<HTMLDivElement>(ref, trackRef)\n\n const direction = vertical ? 'bottom' : 'right'\n const colors = {\n '--active': active,\n '--inactive': inactive,\n }\n\n return (\n <div\n ref={composedRef}\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) ${percent}%, var(--active) ${percent}%)`\n : `linear-gradient(to ${direction}, var(--active) ${percent}%, var(--inactive) ${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 </div>\n )\n}\n","import clsx from 'clsx'\nimport React, {\n ComponentPropsWithoutRef,\n CSSProperties,\n forwardRef,\n ReactNode,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react'\n\nimport type { AxisOptions, XY } from '@tremolo-ui/dom'\nimport {\n applyDelta,\n linearScale,\n toFixed,\n InputEventOption,\n xor,\n type Scale,\n} from '@tremolo-ui/functions'\n\nimport { useDragValue } from '../../hooks/useDragValue'\nimport { useWheel } from '../../hooks/useWheel'\nimport { addUserSelectNone, Cursor, removeUserSelectNone } from '../_util'\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { SliderProvider } from './context'\nimport { Marks } from './Marks'\nimport { MarksOption } from './MarksOption'\nimport { Thumb, SliderThumbMethods } from './Thumb'\nimport { Track } from './Track'\n\nconst defaultExternalStyles: SliderProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'pointer',\n}\n\nexport interface SliderProps {\n // required\n value: number\n min: number\n max: number\n\n // optional\n step?: number\n /**\n * How the value is distributed across the travel.\n *\n * Pick one of the scales from `@tremolo-ui/functions`: `linearScale`,\n * `exponentialScale`, `curveScale(n)`, `symmetricSkewScale(n)`, or\n * `skewScale(n)` for a value that has to match a JUCE parameter.\n *\n * @default linearScale\n */\n scale?: Scale\n /**\n * slider orientation\n * aria-orientation property is also applied.\n */\n vertical?: boolean\n reverse?: boolean\n\n /** Global style to apply when dragged */\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n /**\n * wheel control option\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n\n /**\n * Only the appearance will change.\n * Please consider using with readonly.\n * aria-disabled property is also applied.\n */\n disabled?: boolean\n /**\n * Make the value unchangeable.\n * aria-readonly property is also applied.\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 /**\n * The slider renders exactly what you compose here; there is no default\n * markup to fall back to.\n *\n * @example\n * <Slider.Root value={value} min={0} max={100} onChange={setValue}>\n * <Slider.Track>\n * <Slider.Thumb />\n * </Slider.Track>\n * </Slider.Root>\n */\n children: ReactNode\n}\n\nexport interface SliderMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = SliderProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof SliderProps>\n\n/**\n * The wheel only acts while the focus is inside, so that scrolling a page past\n * the control does not change its value.\n */\nconst WHEEL_OPTIONS = { requireFocus: true }\n\nexport const Root = forwardRef<SliderMethods, Props>(\n (\n {\n value,\n min,\n max,\n step = 1,\n scale = linearScale,\n vertical = false,\n reverse = false,\n externalStyles: _externalStyles,\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 forwardedRef,\n ) => {\n // -- state and ref ---\n const trackRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<SliderThumbMethods>(null)\n\n // --- interpret props ---\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\n\n const p = toFixed(scale.normalize(value, min, max) * 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 // --- internal functions ---\n // The pointer is normalized against the track on both axes; only the one\n // the slider runs along is read back. `AxisOptions` extends `ValueRange`,\n // so the same object also describes the scaling for `applyDelta`.\n const axis: AxisOptions = useMemo(\n () => ({ min, max, step, scale, reverse: displayReversed }),\n [min, max, step, scale, displayReversed],\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 direction = key == 'ArrowRight' || key == 'ArrowUp' ? 1 : -1\n if (reverse) direction *= -1\n onChange(applyDelta(value, direction, keyboard, axis))\n }\n },\n [keyboard, onChange, readonly, reverse, value, axis],\n )\n\n // --- hooks ---\n const valueOf = (v: XY<number>) => v[vertical ? 1 : 0]\n\n const { refCallback: dragRefCallback } = useDragValue<HTMLDivElement>({\n axis,\n baseElementRef: trackRef,\n cursor: readonly ? undefined : externalStyles.cursor,\n updateOnPointerDown: true,\n onChange: (v) => {\n if (readonly) return\n onChange?.(valueOf(v))\n },\n onDragStart: (v) => {\n if (readonly) return\n if (externalStyles.userSelectNone) addUserSelectNone()\n\n thumbRef.current?.focus()\n onDragStart?.(valueOf(v))\n },\n onDragEnd: (v) => {\n if (readonly) return\n\n if (externalStyles.userSelectNone) removeUserSelectNone()\n\n onDragEnd?.(valueOf(v))\n },\n })\n\n const wheelRefCallback = useWheel<HTMLDivElement>((event) => {\n if (!wheel || !onChange || readonly) return\n event.preventDefault()\n let direction\n if (!vertical && event.deltaX != 0) {\n direction = event.deltaX > 0 ? 1 : -1\n } else {\n if (event.deltaY == 0) return\n direction = event.deltaY > 0 ? -1 : 1\n }\n if (vertical && reverse) direction *= -1\n onChange(applyDelta(value, direction, wheel, axis))\n }, WHEEL_OPTIONS)\n\n // Composed once, so React attaches the refs a single time instead of\n // detaching and re-attaching on every render.\n const rootRefCallback = useComposedRefs<HTMLDivElement>(\n dragRefCallback,\n wheelRefCallback,\n )\n\n const context = useMemo(\n () => ({\n value,\n min,\n max,\n step,\n scale,\n vertical,\n reverse,\n disabled,\n readonly,\n percent,\n trackRef,\n thumbRef,\n }),\n [\n value,\n min,\n max,\n step,\n scale,\n vertical,\n reverse,\n disabled,\n readonly,\n percent,\n ],\n )\n\n useImperativeHandle(forwardedRef, () => {\n return {\n focus() {\n thumbRef.current?.focus()\n },\n blur() {\n thumbRef.current?.blur()\n },\n }\n }, [])\n\n return (\n <SliderProvider value={context}>\n <div\n className={clsx('tremolo-slider', className)}\n ref={rootRefCallback}\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 data-vertical={vertical}\n style={style}\n onPointerDown={onPointerDown}\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 {children}\n </div>\n </SliderProvider>\n )\n },\n)\n\n/**\n * Customizable slider\n */\nexport const Slider = {\n Root,\n Thumb,\n Track,\n Marks,\n MarksOption,\n}\n\nexport { useSliderContext } from './context'\nexport { type SliderThumbMethods, type SliderThumbProps } from './Thumb'\nexport { type SliderTrackProps } from './Track'\nexport { type MarksProps } from './Marks'\nexport { type MarksOptionProps } from './MarksOption'\nexport { type MarksOptions, type MarksType } from './type'\n","import { createContext, RefObject, useContext } from 'react'\n\nimport { toXY, type XY, type XYInput } from '@tremolo-ui/dom'\nimport type { Scale } from '@tremolo-ui/functions'\n\nimport type { XYPadThumbMethods } from './Thumb'\n\nexport { toXY, type XY, type XYInput }\n\nexport type XYPadContextValue = {\n value: XY<number>\n min: XY<number>\n max: XY<number>\n step: XY<number>\n /** How the value of each axis is distributed across the travel. */\n scale: XY<Scale>\n reverse: XY<boolean>\n disabled: boolean\n readonly: boolean\n\n /**\n * Position of the thumb, 0-100 per axis, already accounting for `reverse`.\n */\n percent: XY<number>\n\n /** `Area` registers its element here; `Root` normalizes the pointer against it. */\n areaRef: RefObject<HTMLDivElement | null>\n /** `Thumb` registers itself here; `Root` focuses it when a drag starts. */\n thumbRef: RefObject<XYPadThumbMethods | null>\n}\n\nconst XYPadContext = createContext<XYPadContextValue | null>(null)\n\nexport const XYPadProvider = XYPadContext.Provider\n\n/**\n * Everything here is derived during render, so there is no state to keep in\n * sync: `value` comes from the props of `Root` and the rest follows from it.\n */\nexport function useXYPadContext(): XYPadContextValue\nexport function useXYPadContext<T>(selector: (state: XYPadContextValue) => T): T\nexport function useXYPadContext<T>(selector?: (state: XYPadContextValue) => T) {\n const context = useContext(XYPadContext)\n if (!context) throw new Error('Missing XYPadContext.Provider in the tree')\n return selector ? selector(context) : context\n}\n","import clsx from 'clsx'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode, Ref } from 'react'\n\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { useXYPadContext } from './context'\n\nexport interface XYPadAreaProps {\n width?: number | string\n height?: number | string\n color?: string\n className?: string\n style?: CSSProperties\n /** `<XYPad.Thumb />` goes here. */\n children?: ReactNode\n ref?: Ref<HTMLDivElement>\n}\n\nexport function Area({\n width = 120,\n height = 120,\n color,\n children,\n className,\n style,\n ref,\n ...props\n}: XYPadAreaProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadAreaProps>) {\n const { areaRef } = useXYPadContext()\n\n // The area is what the pointer position is normalized against, so the\n // context ref is composed with any ref the caller passed.\n const composedRef = useComposedRefs<HTMLDivElement>(ref, areaRef)\n\n return (\n <div\n ref={composedRef}\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 </div>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n CSSProperties,\n ReactNode,\n Ref,\n useImperativeHandle,\n useRef,\n} from 'react'\n\nimport { useXYPadContext } from './context'\n\nexport interface XYPadThumbProps {\n /**\n * Size comes from the `--thumb-size` CSS variable on `XYPad.Root`, so that\n * the root can reserve the matching amount of space around the area.\n */\n color?: string\n\n wrapperClassName?: string\n wrapperStyle?: CSSProperties\n\n children?: ReactNode\n ref?: Ref<XYPadThumbMethods>\n}\n\nexport interface XYPadThumbMethods {\n focus: () => void\n blur: () => void\n}\n\ntype Props = XYPadThumbProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadThumbProps>\n\nexport function Thumb({\n color,\n children,\n wrapperClassName,\n wrapperStyle,\n className,\n style,\n ref,\n ...props\n}: Props) {\n const elementRef = useRef<HTMLDivElement>(null)\n const { disabled, readonly, percent, thumbRef } = useXYPadContext()\n\n const methods = () => ({\n focus() {\n elementRef.current?.focus()\n },\n blur() {\n elementRef.current?.blur()\n },\n })\n\n useImperativeHandle(ref, methods, [])\n // Root focuses the thumb when a drag starts, wherever the user placed it.\n useImperativeHandle(thumbRef, methods, [])\n\n return (\n <div\n className={clsx('tremolo-xy-pad-thumb-wrapper', wrapperClassName)}\n style={{\n left: `${percent[0]}%`,\n top: `${percent[1]}%`,\n ...wrapperStyle,\n }}\n {...props}\n >\n {children ? (\n children\n ) : (\n // default thumb\n <div\n ref={elementRef}\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 aria-readonly={readonly}\n style={{\n ...{ '--color': color },\n ...style,\n }}\n ></div>\n )}\n </div>\n )\n}\n","import clsx from 'clsx'\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n ReactNode,\n Ref,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react'\n\nimport type { AxisOptions } from '@tremolo-ui/dom'\nimport {\n applyDelta,\n linearScale,\n toFixed,\n InputEventOption,\n type Scale,\n} from '@tremolo-ui/functions'\n\nimport { useDragValue } from '../../hooks/useDragValue'\nimport { useWheel } from '../../hooks/useWheel'\nimport { addUserSelectNone, Cursor, removeUserSelectNone } from '../_util'\nimport { useComposedRefs } from '../_util/composeRefs'\n\nimport { Area } from './Area'\nimport { toXY, XY, XYInput, XYPadProvider } from './context'\nimport { Thumb, XYPadThumbMethods } from './Thumb'\n\nconst defaultExternalStyles: XYPadProps['externalStyles'] = {\n userSelectNone: true,\n cursor: 'pointer',\n}\n\n/**\n * Two-dimensional slider component.\n *\n * The per-axis settings mirror `Slider`, given as `[x, y]` tuples. A plain\n * value applies to both axes.\n */\nexport interface XYPadProps {\n value: XY<number>\n min: XYInput<number>\n max: XYInput<number>\n\n step?: XYInput<number>\n /**\n * How the value of each axis is distributed across the travel.\n *\n * Pick one of the scales from `@tremolo-ui/functions`: `linearScale`,\n * `exponentialScale`, `curveScale(n)`, `symmetricSkewScale(n)`, or\n * `skewScale(n)` for a value that has to match a JUCE parameter.\n *\n * @default linearScale\n */\n scale?: XYInput<Scale>\n reverse?: XYInput<boolean>\n\n /**\n * wheel control option. Shift selects the x axis.\n * If null, no event will be triggered\n */\n wheel?: InputEventOption | null\n /**\n * keyboard control option\n * If null, no event will be triggered\n */\n keyboard?: InputEventOption | null\n\n externalStyles?: {\n userSelectNone?: boolean\n cursor?: Cursor\n }\n\n disabled?: boolean\n readonly?: boolean\n\n onChange?: (value: XY<number>) => void\n onDragStart?: (value: XY<number>) => void\n onDragEnd?: (value: XY<number>) => void\n\n /**\n * The pad renders exactly what you compose here; there is no default\n * markup to fall back to.\n *\n * @example\n * <XYPad.Root value={[x, y]} min={0} max={100} onChange={setValue}>\n * <XYPad.Area>\n * <XYPad.Thumb />\n * </XYPad.Area>\n * </XYPad.Root>\n */\n children: ReactNode\n}\n\nexport interface XYPadMethods {\n focus: () => void\n blur: () => void\n original: Ref<HTMLDivElement>\n}\n\ntype Props = XYPadProps &\n Omit<ComponentPropsWithoutRef<'div'>, keyof XYPadProps>\n\n/**\n * The wheel only acts while the focus is inside, so that scrolling a page past\n * the control does not change its value.\n */\nconst WHEEL_OPTIONS = { requireFocus: true }\n\nexport const Root = forwardRef<XYPadMethods, Props>(\n (\n {\n value,\n min: _min,\n max: _max,\n step: _step = 1,\n scale: _scale = linearScale,\n reverse: _reverse = false,\n wheel = ['raw', 1],\n keyboard = ['raw', 1],\n className,\n style,\n externalStyles: _externalStyles,\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 forwardedRef,\n ) => {\n // -- state and ref ---\n const rootRef = useRef<HTMLDivElement>(null)\n const areaRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<XYPadThumbMethods>(null)\n\n // --- interpret props ---\n const externalStyles = { ...defaultExternalStyles, ..._externalStyles }\n\n const min = useMemo(() => toXY(_min), [_min])\n const max = useMemo(() => toXY(_max), [_max])\n const step = useMemo(() => toXY(_step), [_step])\n const scale = useMemo(() => toXY(_scale), [_scale])\n const reverse = useMemo(() => toXY(_reverse), [_reverse])\n\n const percent = useMemo((): XY<number> => {\n const normalized = [0, 1].map((i) =>\n scale[i].normalize(value[i], min[i], max[i]),\n )\n return [0, 1].map((i) =>\n toFixed((reverse[i] ? 1 - normalized[i] : normalized[i]) * 100),\n ) as XY<number>\n }, [value, min, max, scale, reverse])\n\n // --- internal functions ---\n // `AxisOptions` extends `ValueRange`, so the same pair also describes the\n // scaling for `applyDelta`. Its `reverse` only concerns the drag, where\n // positions follow the screen; the key and wheel handlers below flip the\n // direction themselves.\n const axis = useMemo(\n (): XY<AxisOptions> =>\n [0, 1].map((i) => ({\n min: min[i],\n max: max[i],\n step: step[i],\n scale: scale[i],\n reverse: reverse[i],\n })) as XY<AxisOptions>,\n [min, max, step, scale, reverse],\n )\n\n const withAxis = useCallback(\n (axis: 0 | 1, next: number): XY<number> =>\n axis == 0 ? [next, value[1]] : [value[0], next],\n [value],\n )\n\n /** @param i 0 = x, 1 = y */\n const nudge = useCallback(\n (i: 0 | 1, direction: number, option: InputEventOption): XY<number> =>\n withAxis(i, applyDelta(value[i], direction, option, axis[i])),\n [value, axis, withAxis],\n )\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onChange || readonly || !keyboard) return\n const key = event.key\n if (['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'].includes(key)) {\n const i: 0 | 1 = key == 'ArrowRight' || key == 'ArrowLeft' ? 0 : 1\n event.preventDefault()\n let direction = 1\n if (key == 'ArrowLeft' || key == 'ArrowUp') direction *= -1\n if (reverse[i]) direction *= -1\n onChange(nudge(i, direction, keyboard))\n }\n },\n [onChange, readonly, keyboard, reverse, nudge],\n )\n\n // --- hooks ---\n\n const { refCallback: dragRefCallback } = useDragValue<HTMLDivElement>({\n axis,\n baseElementRef: areaRef,\n updateOnPointerDown: true,\n cursor: readonly ? undefined : externalStyles.cursor,\n onChange: (v) => {\n if (readonly) return\n onChange?.(v)\n },\n onDragStart: (v) => {\n if (readonly) return\n if (externalStyles.userSelectNone) addUserSelectNone()\n thumbRef.current?.focus()\n onDragStart?.(v)\n },\n onDragEnd: (v) => {\n if (readonly) return\n if (externalStyles.userSelectNone) removeUserSelectNone()\n onDragEnd?.(v)\n },\n })\n\n const wheelRefCallback = useWheel<HTMLDivElement>((event) => {\n if (!onChange || readonly || !wheel) return\n const i: 0 | 1 = event.shiftKey ? 0 : 1\n event.preventDefault()\n let direction = 1\n if (event.deltaY < 0) direction *= -1\n if (reverse[i]) direction *= -1\n onChange(nudge(i, direction, wheel))\n }, WHEEL_OPTIONS)\n\n // Composed once, so React attaches the refs a single time instead of\n // detaching and re-attaching on every render.\n const rootRefCallback = useComposedRefs<HTMLDivElement>(\n rootRef,\n dragRefCallback,\n wheelRefCallback,\n )\n\n const context = useMemo(\n () => ({\n value,\n min,\n max,\n step,\n scale,\n reverse,\n disabled,\n readonly,\n percent,\n areaRef,\n thumbRef,\n }),\n [value, min, max, step, scale, reverse, disabled, readonly, percent],\n )\n\n useImperativeHandle(forwardedRef, () => {\n return {\n focus() {\n thumbRef.current?.focus()\n },\n blur() {\n thumbRef.current?.blur()\n },\n original: rootRef,\n }\n }, [])\n\n return (\n <XYPadProvider value={context}>\n {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}\n <div\n className={clsx('tremolo-xy-pad', className)}\n ref={rootRefCallback}\n tabIndex={-1}\n aria-disabled={disabled}\n aria-readonly={readonly}\n style={style}\n onPointerDown={onPointerDown}\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 {children}\n </div>\n </XYPadProvider>\n )\n },\n)\n\n/**\n * Simple XYPad\n */\nexport const XYPad = {\n Root,\n Thumb,\n Area,\n}\n\nexport { type XYPadThumbProps, type XYPadThumbMethods } from './Thumb'\nexport { type XYPadAreaProps } from './Area'\nexport { useXYPadContext, type XY, type XYInput } from './context'\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","import { useEffect, useMemo, useSyncExternalStore } from 'react'\n\nimport { createMIDIAccess } from '@tremolo-ui/dom'\n\nexport {\n NOT_SUPPORTED,\n PERMISSION_DENIED,\n type MIDIAccessError,\n} from '@tremolo-ui/dom'\n\n/**\n * Hooks for requesting MIDI access in the browser. The first argument allows you to choose whether to request access on mount.\n */\nexport function useMIDIAccess(requestOnMount = true) {\n const instance = useMemo(() => createMIDIAccess(), [])\n\n const { midiAccess, error } = useSyncExternalStore(\n instance.subscribe,\n instance.getState,\n instance.getServerState,\n )\n\n useEffect(() => {\n if (requestOnMount) instance.request()\n }, [instance, requestOnMount])\n\n useEffect(() => {\n return () => instance.destroy()\n }, [instance])\n\n return { request: instance.request, midiAccess, error }\n}\n","import { useEffect } from 'react'\n\nimport { createMIDIInput } from '@tremolo-ui/dom'\n\n/**\n * Hooks for handling note on/off events. To be used with useMIDIAccess. Internally uses useMIDIMessage.\n */\nexport function useMIDIInput(\n midiAccess: MIDIAccess | null,\n onNoteOnEvent?: (note: number, velocity: number) => void,\n onNoteOffEvent?: (note: number) => void,\n onPitchBendEvent?: (msb: number, lsb: number) => void,\n) {\n useEffect(() => {\n const instance = createMIDIInput(midiAccess, {\n onNoteOnEvent,\n onNoteOffEvent,\n onPitchBendEvent,\n })\n return () => instance.destroy()\n }, [midiAccess, onNoteOnEvent, onNoteOffEvent, onPitchBendEvent])\n}\n","import { useEffect } from 'react'\n\nimport { createMIDIMessage } from '@tremolo-ui/dom'\n\n/**\n * Hooks for when you want to process MIDI events in more detail than useMIDIInput.\n */\nexport function useMIDIMessage(\n midiAccess: MIDIAccess | null,\n onMIDIMessage: (event: MIDIMessageEvent) => void,\n) {\n useEffect(() => {\n const instance = createMIDIMessage(midiAccess, onMIDIMessage)\n return () => instance.destroy()\n }, [midiAccess, onMIDIMessage])\n}\n"],"mappings":"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"}