@tremolo-ui/react 0.7.0 → 0.9.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 (55) hide show
  1. package/dist/index.cjs +666 -1171
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +316 -315
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.ts +316 -315
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +643 -1123
  8. package/dist/index.js.map +1 -1
  9. package/package.json +9 -9
  10. package/src/components/AnimationCanvas/index.tsx +4 -18
  11. package/src/components/DropZone/index.tsx +2 -1
  12. package/src/components/FileInput/index.tsx +11 -13
  13. package/src/components/Knob/ActiveLine.tsx +5 -3
  14. package/src/components/Knob/InactiveLine.tsx +6 -4
  15. package/src/components/Knob/SVGRoot.tsx +3 -3
  16. package/src/components/Knob/Thumb.tsx +21 -20
  17. package/src/components/Knob/context.tsx +3 -74
  18. package/src/components/Knob/index.tsx +99 -52
  19. package/src/components/NumberInput/InputField.tsx +20 -33
  20. package/src/components/NumberInput/Stepper.tsx +76 -100
  21. package/src/components/NumberInput/StepperButton.tsx +15 -8
  22. package/src/components/NumberInput/context.tsx +26 -3
  23. package/src/components/NumberInput/index.tsx +175 -91
  24. package/src/components/Piano/index.tsx +54 -144
  25. package/src/components/PointsEditor/Container.tsx +15 -26
  26. package/src/components/PointsEditor/Point.tsx +94 -110
  27. package/src/components/PointsEditor/context.tsx +8 -60
  28. package/src/components/PointsEditor/index.tsx +41 -324
  29. package/src/components/Slider/Marks.tsx +5 -6
  30. package/src/components/Slider/MarksOption.tsx +9 -19
  31. package/src/components/Slider/Thumb.tsx +20 -11
  32. package/src/components/Slider/Track.tsx +16 -13
  33. package/src/components/Slider/context.tsx +3 -3
  34. package/src/components/Slider/index.tsx +110 -72
  35. package/src/components/XYPad/Area.tsx +27 -49
  36. package/src/components/XYPad/Thumb.tsx +20 -8
  37. package/src/components/XYPad/context.tsx +2 -4
  38. package/src/components/XYPad/index.tsx +102 -83
  39. package/src/components/_util/VisuallyHiddenRangeInput.tsx +1 -1
  40. package/src/hooks/_internal/useChangeGesture.ts +93 -0
  41. package/src/hooks/_internal/useCheckSteps.ts +9 -146
  42. package/src/hooks/useAnimationFrame.ts +37 -15
  43. package/src/hooks/useEventListener.ts +93 -22
  44. package/src/hooks/useLongPress.ts +35 -51
  45. package/src/hooks/useMIDIAccess.ts +0 -8
  46. package/src/hooks/useMIDIInput.ts +0 -3
  47. package/src/hooks/useWheel.ts +4 -4
  48. package/src/index.ts +11 -32
  49. package/src/components/Piano/keyboard-shortcuts.ts +0 -61
  50. package/src/components/Slider/type.ts +0 -46
  51. package/src/components/_util/css-length.ts +0 -13
  52. package/src/components/_util/decimal-digits.ts +0 -23
  53. package/src/components/_util/visually-hidden.ts +0 -25
  54. package/src/hooks/useInterval.ts +0 -27
  55. package/src/input-event.ts +0 -32
package/dist/index.d.ts CHANGED
@@ -1,14 +1,7 @@
1
- import React, { AriaAttributes, CSSProperties, ComponentPropsWithoutRef, DependencyList, ReactNode, Ref, RefObject, SVGProps } from "react";
2
- import { AnimationFrame, AxisOptions, DragState, DropZoneOptions, InputEventOption, MIDIAccessError, MIDIAccessOptions, MIDIAccessOptions as MIDIAccessOptions$1, MIDIInputHandlers, ModifierState, ModifierValue, NOT_SUPPORTED, NoteRange, PERMISSION_DENIED, PITCH_BEND_CENTER, SelectionBoxRect, UNAVAILABLE, WheelOptions, XY, XY as XY$1, XYInput, XYInput as XYInput$1 } from "@tremolo-ui/dom";
1
+ import React, { AriaAttributes, CSSProperties, ComponentPropsWithoutRef, ReactNode, Ref, RefObject, SVGProps } from "react";
2
+ import { AxisOptions, CanvasDrawFunction, CanvasInitFunction, ChangeSource, DragState, DropZoneOptions, InputEventOption, KeyboardShortcuts, KeyboardShortcutsScope, KnobAngles, MIDIAccessOptions, MIDIInputHandlers, MarksOptions, ModifierState, ModifierValue, NoteRange, PointPosition, PointsEditorInstance, SelectionBoxRect, WheelOptions, XY, XYInput } from "@tremolo-ui/dom";
3
3
  import { Scale, ValueRange } from "@tremolo-ui/functions";
4
4
  //#region src/components/AnimationCanvas/index.d.ts
5
- type InitFunction = (context: CanvasRenderingContext2D, option: {
6
- /** current canvas width */
7
- width: number;
8
- /** current canvas height */
9
- height: number;
10
- }) => void;
11
- type DrawFunction = (context: CanvasRenderingContext2D, option: AnimationFrame) => void;
12
5
  interface AnimationCanvasCommonProps {
13
6
  /**
14
7
  * Draw one frame. It is given the 2D context and the frame: the size in CSS
@@ -17,12 +10,12 @@ interface AnimationCanvasCommonProps {
17
10
  * A new function replaces the old one in place, so writing it inline does
18
11
  * not restart anything.
19
12
  */
20
- draw: DrawFunction;
13
+ draw: CanvasDrawFunction;
21
14
  /**
22
15
  * Called once before the first frame, with the context and the size in CSS
23
16
  * pixels. Set up what every frame shares here.
24
17
  */
25
- init?: InitFunction;
18
+ init?: CanvasInitFunction;
26
19
  /**
27
20
  * Redraw on every animation frame. Turn it off to draw only when there is a
28
21
  * reason to: when the canvas mounts, when it is resized, and when the
@@ -120,7 +113,8 @@ interface DropZoneProps {
120
113
  onDrop?: (files: File[], event: DragEvent) => void;
121
114
  /**
122
115
  * Called with the dropped files that do not match `accept`, so that the
123
- * reason can be shown.
116
+ * reason can be shown. It comes after `onDrop` for the same drop, so a list
117
+ * of rejected files can be cleared in `onDrop` and filled here.
124
118
  */
125
119
  onReject?: (files: File[], event: DragEvent) => void;
126
120
  /** What the zone shows. */
@@ -181,7 +175,8 @@ interface FileInputProps {
181
175
  /**
182
176
  * Called with the files that were picked and do not match `accept`, so that
183
177
  * the reason can be shown. Given alongside `onChange` when a selection held
184
- * both.
178
+ * both, and after it, so a list of rejected files can be cleared in
179
+ * `onChange` and filled here.
185
180
  */
186
181
  onReject?: (files: File[]) => void;
187
182
  /** Normally a `FileInput.Trigger`, and whatever shows what was picked. */
@@ -217,37 +212,37 @@ interface KnobThumbProps {
217
212
  * Fill colour of the circle.
218
213
  * @default 'currentColor'
219
214
  */
220
- thumb?: string;
215
+ color?: string;
221
216
  /**
222
217
  * Colour of the line that points at the value.
223
218
  * @default 'currentColor'
224
219
  */
225
- thumbLine?: string;
220
+ lineColor?: string;
226
221
  /**
227
222
  * Diameter of the circle, as a percentage of the knob.
228
223
  * @default 84
229
224
  */
230
- thumbSize?: number;
225
+ size?: number;
231
226
  /**
232
227
  * Thickness of the line, as a percentage of the knob.
233
228
  * @default 6
234
229
  */
235
- thumbLineWeight?: number;
230
+ lineWeight?: number;
236
231
  /**
237
232
  * How far down the line reaches, as a percentage of the knob from its top.
238
233
  * The line starts at the edge of the circle.
239
234
  * @default 35
240
235
  */
241
- thumbLineLength?: number;
236
+ lineLength?: number;
242
237
  /**
243
- * Classes for what the thumb draws inside itself: `thumbLine` is the line
244
- * that points at the value.
238
+ * Classes for what the thumb draws inside itself: `line` is the line that
239
+ * points at the value.
245
240
  */
246
241
  classes?: {
247
- thumbLine?: string;
242
+ line?: string;
248
243
  };
249
244
  }
250
- declare function Thumb({ className, thumb, thumbLine, thumbSize, thumbLineWeight, thumbLineLength, classes, ...props }: KnobThumbProps & Omit<SVGProps<SVGSVGElement>, 'd' | keyof KnobThumbProps>): import("react").JSX.Element;
245
+ declare function Thumb({ className, color, lineColor, size, lineWeight, lineLength, classes, ...props }: KnobThumbProps & Omit<SVGProps<SVGSVGElement>, 'd' | keyof KnobThumbProps>): import("react").JSX.Element;
251
246
  //#endregion
252
247
  //#region src/css-variables.d.ts
253
248
  /**
@@ -281,18 +276,7 @@ type KnobConfig = {
281
276
  /** angle range [degree] */
282
277
  angleRange: number;
283
278
  };
284
- type KnobContextValue = KnobConfig & {
285
- /** normalized value */
286
- p: number;
287
- /** ロータリー開始位置 */
288
- r1: number;
289
- /** activeLine の開始位置 */
290
- r2: number;
291
- /** activeLine の終了位置 */
292
- r3: number;
293
- /** ロータリー終了位置 */
294
- r4: number;
295
- };
279
+ type KnobContextValue = KnobConfig & KnobAngles;
296
280
  /**
297
281
  * Everything here is derived during render, so there is no state to keep in
298
282
  * sync: `value` comes from the props of `Root` and the rest follows from it.
@@ -326,10 +310,10 @@ interface KnobProps {
326
310
  */
327
311
  scale?: Scale;
328
312
  /**
329
- * The value a double click restores, while `enableDoubleClickDefault` is on.
330
- * @default min
313
+ * The value a double click restores. `null` turns the double click off.
314
+ * @default startValue
331
315
  */
332
- defaultValue?: number;
316
+ resetValue?: number | null;
333
317
  /**
334
318
  * Where the active arc starts. Put it at the centre of a bipolar control,
335
319
  * such as a pan knob, so that the arc grows from there either way.
@@ -345,11 +329,9 @@ interface KnobProps {
345
329
  * The cursor to show while dragging. It is set on the dragged element, so it
346
330
  * stays while the pointer is outside the knob.
347
331
  *
348
- * @default { cursor: 'grabbing' }
332
+ * @default 'grabbing'
349
333
  */
350
- externalStyles?: {
351
- cursor?: CSSProperties['cursor'];
352
- };
334
+ dragCursor?: CSSProperties['cursor'];
353
335
  /**
354
336
  * How much one notch of the wheel moves the value. It only acts while the
355
337
  * focus is inside, so that scrolling the page past the knob leaves it alone.
@@ -410,11 +392,6 @@ interface KnobProps {
410
392
  * @default { default: ['raw', 1], shift: ['raw', 0.1] }
411
393
  */
412
394
  keyboard?: ModifierValue<InputEventOption> | null;
413
- /**
414
- * Restore `defaultValue` on a double click.
415
- * @default true
416
- */
417
- enableDoubleClickDefault?: boolean;
418
395
  /**
419
396
  * Make the knob unchangeable and remove it from the tab order.
420
397
  * The parts carry `data-disabled` while it is set.
@@ -424,7 +401,7 @@ interface KnobProps {
424
401
  * Make the knob unchangeable while leaving it focusable.
425
402
  * The parts carry `data-readonly` while it is set.
426
403
  */
427
- readonly?: boolean;
404
+ readOnly?: boolean;
428
405
  /**
429
406
  * How far the knob turns from `min` to `max`, in degrees, centred on the
430
407
  * top.
@@ -436,6 +413,25 @@ interface KnobProps {
436
413
  * click moves it.
437
414
  */
438
415
  onChange?: (value: number) => void;
416
+ /**
417
+ * Called when a change of the value starts — a drag, a double click, the first wheel notch
418
+ * or arrow key — with the value
419
+ * before it and what it is made with. A host recording automation can treat
420
+ * the control as touched from here until `onChangeEnd`.
421
+ */
422
+ onChangeStart?: (value: number, source: ChangeSource) => void;
423
+ /**
424
+ * Called when the change ends, with the value it ended on: on release, or
425
+ * `changeEndDelay` after the last wheel notch or arrow key.
426
+ */
427
+ onChangeEnd?: (value: number, source: ChangeSource) => void;
428
+ /**
429
+ * How long after the last wheel notch or arrow key the change counts as
430
+ * over, in milliseconds. Neither has an event that says it is done.
431
+ *
432
+ * @default 500
433
+ */
434
+ changeEndDelay?: number;
439
435
  /**
440
436
  * The knob renders exactly what you compose here; there is no default
441
437
  * markup to fall back to.
@@ -451,6 +447,12 @@ interface KnobProps {
451
447
  */
452
448
  children: ReactNode;
453
449
  style?: CSSProperties & CSSVariables<'knob-size'>;
450
+ /**
451
+ * Receives `focus` and `blur`. They do nothing while the knob is disabled,
452
+ * where the element's own `focus()` would still focus it. `ref` reaches the
453
+ * root element itself.
454
+ */
455
+ actionsRef?: Ref<KnobMethods>;
454
456
  }
455
457
  interface KnobMethods {
456
458
  focus: () => void;
@@ -460,7 +462,7 @@ interface KnobMethods {
460
462
  * Interactive rotary knob component implemented in SVG.
461
463
  */
462
464
  export declare const Knob: {
463
- Root: import("react").ForwardRefExoticComponent<KnobProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof KnobProps> & import("react").RefAttributes<KnobMethods>>;
465
+ Root: import("react").ForwardRefExoticComponent<KnobProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof KnobProps> & import("react").RefAttributes<HTMLDivElement>>;
464
466
  SVGRoot: typeof SVGRoot;
465
467
  InactiveLine: typeof InactiveLine;
466
468
  ActiveLine: typeof ActiveLine;
@@ -498,7 +500,7 @@ type NumberInputContextValue = {
498
500
  /** How the value is distributed across the travel. */
499
501
  scale: Scale;
500
502
  disabled: boolean;
501
- readonly: boolean;
503
+ readOnly: boolean;
502
504
  clampValue: boolean;
503
505
  /**
504
506
  * The effective scaling for `applyDelta`, with unbounded ends filled in.
@@ -514,6 +516,8 @@ type NumberInputContextValue = {
514
516
  dragSensitivity: ModifierValue<number>;
515
517
  /** Whether a `Stepper` drag hides the pointer and reads its movement. */
516
518
  pointerLock: boolean;
519
+ /** The cursor shown while a `Stepper` is dragged. */
520
+ dragCursor: CSSProperties['cursor'];
517
521
  /** What `InputField` selects when it takes focus. */
518
522
  selectOnFocus: 'all' | 'number' | 'none';
519
523
  /** Whether `InputField` shows the plain value while it has focus. */
@@ -600,6 +604,9 @@ interface NumberInputProps {
600
604
  * Read a value back out of the text. Has to undo `format`.
601
605
  *
602
606
  * Text with no number in it reads as `NaN`, which leaves the value alone.
607
+ * The default, `parseNumberText` from `@tremolo-ui/dom`, reads the number
608
+ * with the unit around it left out, and is `NaN` for one it cannot read
609
+ * whole: `1,000`, `1:30`, or a number with a unit in front, such as `L 30`.
603
610
  */
604
611
  parse?: (text: string) => number;
605
612
  /**
@@ -670,9 +677,16 @@ interface NumberInputProps {
670
677
  * @default false
671
678
  */
672
679
  pointerLock?: boolean;
680
+ /**
681
+ * The cursor to show while dragging a `Stepper`. It is set on the stepper
682
+ * being dragged, so it stays while the pointer is outside it.
683
+ *
684
+ * @default 'ns-resize'
685
+ */
686
+ dragCursor?: CSSProperties['cursor'];
673
687
  /**
674
688
  * Select the text when `InputField` takes focus: `'all'` selects all of it,
675
- * `'number'` only the leading number, leaving whatever the format appended,
689
+ * `'number'` only the number, leaving the unit the format put around it,
676
690
  * and `'none'` leaves the caret where the click put it.
677
691
  * @default 'none'
678
692
  */
@@ -725,13 +739,34 @@ interface NumberInputProps {
725
739
  * Make the value unchangeable.
726
740
  * The parts carry `data-readonly` while it is set.
727
741
  */
728
- readonly?: boolean;
742
+ readOnly?: boolean;
729
743
  /**
730
744
  * Called with the new value. While the user types, it is called for every
731
745
  * entry that reads as a number, unclamped; committing the entry calls it
732
746
  * again if clamping changes the value.
733
747
  */
734
748
  onChange?: (value: number) => void;
749
+ /**
750
+ * Called when a change of the value starts — a press on a stepper, the
751
+ * first wheel notch, arrow key or typed character — with the value before
752
+ * it and what it is made with. A host recording automation can treat the
753
+ * input as touched from here until `onChangeEnd`.
754
+ */
755
+ onChangeStart?: (value: number, source: ChangeSource) => void;
756
+ /**
757
+ * Called when the change ends, with the value it ended on: when the stepper
758
+ * is released, when typed text is committed, or `changeEndDelay` after the
759
+ * last wheel notch or arrow key.
760
+ */
761
+ onChangeEnd?: (value: number, source: ChangeSource) => void;
762
+ /**
763
+ * How long after the last wheel notch, arrow key or typed character the
764
+ * change counts as over, in milliseconds. None of them has an event that
765
+ * says it is done.
766
+ *
767
+ * @default 500
768
+ */
769
+ changeEndDelay?: number;
735
770
  /**
736
771
  * The input renders exactly what you compose here; there is no default
737
772
  * markup to fall back to.
@@ -746,6 +781,12 @@ interface NumberInputProps {
746
781
  * </NumberInput.Root>
747
782
  */
748
783
  children: ReactNode;
784
+ /**
785
+ * Receives `focus` and `blur`, which act on the input of `InputField` — the
786
+ * element that takes the focus — and do nothing while
787
+ * the input is disabled. `ref` reaches the root element itself.
788
+ */
789
+ actionsRef?: Ref<NumberInputMethods>;
749
790
  }
750
791
  interface NumberInputMethods {
751
792
  focus: () => void;
@@ -755,16 +796,14 @@ interface NumberInputMethods {
755
796
  * Input with some useful functions for entering numerical values.
756
797
  */
757
798
  export declare const NumberInput: {
758
- Root: import("react").ForwardRefExoticComponent<NumberInputProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof NumberInputProps> & import("react").RefAttributes<NumberInputMethods>>;
799
+ Root: import("react").ForwardRefExoticComponent<NumberInputProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof NumberInputProps> & import("react").RefAttributes<HTMLDivElement>>;
759
800
  InputField: import("react").ForwardRefExoticComponent<{
760
801
  form?: string | undefined | undefined;
761
802
  slot?: string | undefined | undefined;
762
- style?: import("react").CSSProperties | undefined;
803
+ style?: CSSProperties | undefined;
763
804
  title?: string | undefined | undefined;
764
805
  pattern?: string | undefined | undefined;
765
806
  key?: import("react").Key | null | undefined;
766
- height?: number | string | undefined | undefined;
767
- width?: number | string | undefined | undefined;
768
807
  defaultChecked?: boolean | undefined | undefined;
769
808
  suppressContentEditableWarning?: boolean | undefined | undefined;
770
809
  suppressHydrationWarning?: boolean | undefined | undefined;
@@ -772,7 +811,7 @@ export declare const NumberInput: {
772
811
  autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
773
812
  autoFocus?: boolean | undefined | undefined;
774
813
  className?: string | undefined | undefined;
775
- contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
814
+ contentEditable?: "inherit" | (boolean | "true" | "false") | "plaintext-only" | undefined;
776
815
  contextMenu?: string | undefined | undefined;
777
816
  dir?: string | undefined | undefined;
778
817
  draggable?: (boolean | "true" | "false") | undefined;
@@ -1045,7 +1084,10 @@ export declare const NumberInput: {
1045
1084
  max?: number | string | undefined | undefined;
1046
1085
  step?: number | string | undefined | undefined;
1047
1086
  disabled?: boolean | undefined | undefined;
1087
+ readOnly?: boolean | undefined | undefined;
1048
1088
  alt?: string | undefined | undefined;
1089
+ height?: number | string | undefined | undefined;
1090
+ width?: number | string | undefined | undefined;
1049
1091
  accept?: string | undefined | undefined;
1050
1092
  multiple?: boolean | undefined | undefined;
1051
1093
  size?: number | undefined | undefined;
@@ -1062,7 +1104,6 @@ export declare const NumberInput: {
1062
1104
  minLength?: number | undefined | undefined;
1063
1105
  name?: string | undefined | undefined;
1064
1106
  placeholder?: string | undefined | undefined;
1065
- readOnly?: boolean | undefined | undefined;
1066
1107
  required?: boolean | undefined | undefined;
1067
1108
  src?: string | undefined | undefined;
1068
1109
  } & import("react").RefAttributes<HTMLInputElement>>;
@@ -1071,34 +1112,7 @@ export declare const NumberInput: {
1071
1112
  DecrementStepper: typeof DecrementStepper;
1072
1113
  };
1073
1114
  //#endregion
1074
- //#region src/components/Piano/keyboard-shortcuts.d.ts
1075
- type KeyboardShortcuts = {
1076
- /**
1077
- * Keys laid out from `noteRange.first`, one entry per semitone.
1078
- *
1079
- * An empty string leaves that note without a shortcut: `KeyboardEvent.key` is
1080
- * never empty, so the entry can never match. Use it to skip the black keys
1081
- * (see {@link SHORTCUTS.HOME_ROW_NATURAL}) and keep the remaining entries
1082
- * lined up with the notes.
1083
- */
1084
- keys: string[];
1085
- };
1086
- /**
1087
- * Ready-made keyboard layouts. Both assume `noteRange.first` is a C.
1088
- */
1089
- export declare const SHORTCUTS: {
1090
- /** Every semitone from C, over the two rows of a QWERTY keyboard. */
1091
- HOME_ROW: {
1092
- keys: string[];
1093
- };
1094
- /** The white keys only, on the home row. Black keys have no shortcut. */
1095
- HOME_ROW_NATURAL: {
1096
- keys: string[];
1097
- };
1098
- };
1099
- //#endregion
1100
1115
  //#region src/components/Piano/index.d.ts
1101
- type KeyboardShortcutsScope = 'root' | 'window';
1102
1116
  /**
1103
1117
  * What {@link PianoProps.keyProps} may return for one key.
1104
1118
  *
@@ -1106,9 +1120,7 @@ type KeyboardShortcutsScope = 'root' | 'window';
1106
1120
  * JSX syntax, not on an object type, and selecting on one is the usual way to
1107
1121
  * mark a key out.
1108
1122
  */
1109
- type KeyAttributes = Omit<ComponentPropsWithoutRef<'div'>, 'style'> & {
1110
- style?: CSSProperties & CSSVariables<'color' | 'bg' | 'active-color' | 'active-bg'>;
1111
- } & Record<`data-${string}`, string | number | boolean | undefined>;
1123
+ type KeyAttributes = ComponentPropsWithoutRef<'div'> & Record<`data-${string}`, string | number | boolean | undefined>;
1112
1124
  /** What a key is, when {@link PianoProps.label} or `keyProps` is asked about it. */
1113
1125
  interface KeyState {
1114
1126
  /** Position in the note range, counting from `noteRange.first`. */
@@ -1189,15 +1201,9 @@ interface PianoProps {
1189
1201
  * @default 0.6
1190
1202
  */
1191
1203
  blackKeyHeightRatio?: number;
1192
- /**
1193
- * Height of the keyboard. Sets `--height`; when it is omitted, the height
1194
- * the theme gives stands, and the theme can tell `resizable` apart through
1195
- * `data-resizable`.
1196
- */
1197
- height?: number | string;
1198
1204
  /**
1199
1205
  * What to draw inside a key. `''`, `null` and `undefined` leave it bare, so
1200
- * a layout with gaps — {@link SHORTCUTS.HOME_ROW_NATURAL}, say — needs no
1206
+ * a layout with gaps — `SHORTCUTS.HOME_ROW_NATURAL`, say — needs no
1201
1207
  * special casing.
1202
1208
  */
1203
1209
  label?: (note: number, state: KeyState) => ReactNode;
@@ -1224,7 +1230,11 @@ interface PianoProps {
1224
1230
  onPlayNote?: (note: number, velocity?: number) => void;
1225
1231
  /** Called once everything holding a note has let go of it. */
1226
1232
  onStopNote?: (note: number) => void;
1227
- style?: CSSProperties & CSSVariables<'height'>;
1233
+ /**
1234
+ * Receives `playNote` and `stopNote`, which press and release a key as the
1235
+ * pointer or the keyboard would. `ref` reaches the root element itself.
1236
+ */
1237
+ actionsRef?: Ref<PianoMethods>;
1228
1238
  }
1229
1239
  interface PianoMethods {
1230
1240
  playNote: (note: number, velocity?: number) => void;
@@ -1234,22 +1244,14 @@ interface PianoMethods {
1234
1244
  * Customizable piano component.
1235
1245
  */
1236
1246
  export declare const Piano: {
1237
- Root: import("react").ForwardRefExoticComponent<PianoProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof PianoProps> & import("react").RefAttributes<PianoMethods>>;
1247
+ Root: import("react").ForwardRefExoticComponent<PianoProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof PianoProps> & import("react").RefAttributes<HTMLDivElement>>;
1238
1248
  };
1239
1249
  //#endregion
1240
1250
  //#region src/components/PointsEditor/Background.d.ts
1241
1251
  declare function Background({ className, children, style, ...props }: ComponentPropsWithoutRef<'div'>): import("react").JSX.Element;
1242
1252
  //#endregion
1243
1253
  //#region src/components/PointsEditor/Point.d.ts
1244
- type PointBaseType = {
1245
- x: number;
1246
- y: number;
1247
- };
1248
- export declare function clampPoint(point: PointBaseType, min?: Partial<PointBaseType>, max?: Partial<PointBaseType>): {
1249
- x: number;
1250
- y: number;
1251
- };
1252
- interface PointsEditorPointProps<T extends PointBaseType> {
1254
+ interface PointsEditorPointProps<T extends PointPosition> {
1253
1255
  /**
1254
1256
  * Where the point is, as `{ x, y }` from 0 to 1 on each axis, with `y`
1255
1257
  * growing downwards.
@@ -1262,21 +1264,15 @@ interface PointsEditorPointProps<T extends PointBaseType> {
1262
1264
  */
1263
1265
  id?: string;
1264
1266
  /** The lowest position the point can take, per axis. An axis left out is 0. */
1265
- min?: Partial<PointBaseType>;
1267
+ min?: Partial<PointPosition>;
1266
1268
  /** The highest position the point can take, per axis. An axis left out is 1. */
1267
- max?: Partial<PointBaseType>;
1268
- /** Width and height at once. Sets both `--width` and `--height`. */
1269
- size?: number | string;
1270
- /** Sets `--width`; the size the theme gives it stands when omitted. */
1271
- width?: number | string;
1272
- /** Sets `--height`; the size the theme gives it stands when omitted. */
1273
- height?: number | string;
1269
+ max?: Partial<PointPosition>;
1274
1270
  /** Sets `--color`, for the theme to colour the point with. */
1275
1271
  color?: string;
1276
1272
  /** Overrides the `disabled` of `PointsEditor.Root`. */
1277
1273
  disabled?: boolean;
1278
- /** Overrides the `readonly` of `PointsEditor.Root`. */
1279
- readonly?: boolean;
1274
+ /** Overrides the `readOnly` of `PointsEditor.Root`. */
1275
+ readOnly?: boolean;
1280
1276
  /** Overrides the `wheel` of `PointsEditor.Root`. */
1281
1277
  wheel?: ModifierValue<InputEventOption> | null;
1282
1278
  /** Overrides the `keyboard` of `PointsEditor.Root`. */
@@ -1292,14 +1288,29 @@ interface PointsEditorPointProps<T extends PointBaseType> {
1292
1288
  * Called with the new position when the point is dragged or moved by the
1293
1289
  * arrow keys or the wheel, including when it moves along with a selection.
1294
1290
  */
1295
- onChange?: (value: PointBaseType) => void;
1296
- /** Called when a drag on this point starts, with where the point is. */
1297
- onDragStart?: (value: PointBaseType) => void;
1298
- /** Called when that drag ends, with where the point is. */
1299
- onDragEnd?: (value: PointBaseType) => void;
1300
- style?: CSSProperties & CSSVariables<'width' | 'height' | 'color' | 'translate'>;
1291
+ onChange?: (value: PointPosition) => void;
1292
+ /**
1293
+ * Called when a change of this point starts — a drag on it, the first wheel
1294
+ * notch or arrow key while it has the focus — with where it is and what the
1295
+ * change is made with. The points that move along with a selection report
1296
+ * through `onChange` only: the change belongs to the point being operated.
1297
+ */
1298
+ onChangeStart?: (value: PointPosition, source: ChangeSource) => void;
1299
+ /**
1300
+ * Called when that change ends, with where the point is: on release, or
1301
+ * `changeEndDelay` after the last wheel notch or arrow key.
1302
+ */
1303
+ onChangeEnd?: (value: PointPosition, source: ChangeSource) => void;
1304
+ /**
1305
+ * How long after the last wheel notch or arrow key the change counts as
1306
+ * over, in milliseconds. Neither has an event that says it is done.
1307
+ *
1308
+ * @default 500
1309
+ */
1310
+ changeEndDelay?: number;
1311
+ style?: CSSProperties & CSSVariables<'color' | 'translate'>;
1301
1312
  }
1302
- declare function Point<T extends PointBaseType>({ value, children, id: idProp, min, max, size, width, height, color, disabled: _disabled, readonly: _readonly, wheel: _wheel, keyboard: _keyboard, 'aria-label': ariaLabel, 'aria-valuetext': ariaValuetext, onChange, onDragStart, onDragEnd, className, style, onPointerDown, onKeyDown, onFocus, ...props }: PointsEditorPointProps<T> & Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorPointProps<T>>): import("react").JSX.Element;
1313
+ declare function Point<T extends PointPosition>({ value, children, id: idProp, min, max, color, disabled: _disabled, readOnly: _readOnly, wheel: _wheel, keyboard: _keyboard, 'aria-label': ariaLabel, 'aria-valuetext': ariaValuetext, onChange, onChangeStart, onChangeEnd, changeEndDelay, className, style, onPointerDown, onKeyDown, onFocus, ...props }: PointsEditorPointProps<T> & Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorPointProps<T>>): import("react").JSX.Element;
1303
1314
  //#endregion
1304
1315
  //#region src/components/PointsEditor/SelectionBox.d.ts
1305
1316
  /**
@@ -1311,36 +1322,17 @@ declare function Point<T extends PointBaseType>({ value, children, id: idProp, m
1311
1322
  declare function SelectionBox({ children, className, style, ...props }: ComponentPropsWithoutRef<'div'>): import("react").JSX.Element | null;
1312
1323
  //#endregion
1313
1324
  //#region src/components/PointsEditor/context.d.ts
1314
- /**
1315
- * What a `Point` tells the editor about itself, so that a selection can be
1316
- * moved without the editor knowing how the points are stored.
1317
- *
1318
- * Held behind a ref and rewritten on every render: the value changes on every
1319
- * frame of a drag, and a registry keyed on it would be rebuilt just as often.
1320
- */
1321
- interface PointRegistration {
1322
- value: PointBaseType;
1323
- min?: Partial<PointBaseType>;
1324
- max?: Partial<PointBaseType>;
1325
- readonly: boolean;
1326
- onChange?: (value: PointBaseType) => void;
1327
- /** The point's own element, to match the focus against. */
1328
- element: HTMLElement | null;
1329
- /** The wheel option this point resolved, root inheritance applied. */
1330
- wheel: ModifierValue<InputEventOption> | null;
1331
- }
1332
1325
  type PointsEditorContextValue = {
1333
1326
  disabled: boolean;
1334
- readonly: boolean;
1327
+ readOnly: boolean;
1335
1328
  /** Inherited by every `Point`; `null` turns the wheel off. */
1336
1329
  wheel: ModifierValue<InputEventOption> | null;
1337
1330
  /** Inherited by every `Point`; `null` turns the keyboard off. */
1338
1331
  keyboard: ModifierValue<InputEventOption> | null;
1339
1332
  /** Inherited by every `Point`. See `PointsEditorProps.dragSensitivity`. */
1340
1333
  dragSensitivity: ModifierValue<number>;
1341
- externalStyles: {
1342
- cursor?: CSSProperties['cursor'];
1343
- };
1334
+ /** Inherited by every `Point`. See `PointsEditorProps.dragCursor`. */
1335
+ dragCursor: CSSProperties['cursor'];
1344
1336
  /**
1345
1337
  * `Container` registers its element here; `Point` normalizes the pointer
1346
1338
  * against it, so a point is placed by its position within the container.
@@ -1350,37 +1342,14 @@ type PointsEditorContextValue = {
1350
1342
  selectable: boolean;
1351
1343
  /** Ids of the points currently selected. Always empty while `selectable` is off. */
1352
1344
  selection: readonly string[];
1353
- /** Register a point so that a selection can move it with the rest. */
1354
- registerPoint: (id: string, entry: RefObject<PointRegistration>) => () => void;
1355
- /**
1356
- * Whether the element is a point, or inside one. The registry knows which
1357
- * elements the points are, so nothing has to be recognised by a class name.
1358
- */
1359
- isPointElement: (element: Element | null | undefined) => boolean;
1360
- /**
1361
- * A pointer went down on a point: works out the new selection and takes the
1362
- * snapshot the move will be measured against.
1363
- */
1364
- beginPointDrag: (id: string, modifiers: ModifierState) => void;
1365
- /** Move everything the drag picked up, by one amount, clamped as one. */
1366
- movePointDrag: (delta: PointBaseType) => void;
1367
- /**
1368
- * Move the selection by an amount that did not come from a drag — an arrow
1369
- * key or a wheel notch. The current values are the starting point.
1370
- */
1371
- nudgeSelection: (id: string, delta: PointBaseType) => void;
1372
1345
  /**
1373
- * Move the point that currently holds focus by one notch. The wheel listener
1374
- * belongs to `Container` rather than to every `Point`, so the lookup of who
1375
- * has focus happens here, where the registry is. Returns whether a point
1376
- * took it, so the caller knows whether to consume the event.
1346
+ * The selection and the moves, from `createPointsEditor` in
1347
+ * `@tremolo-ui/dom`: every `Point` registers with it, and a press, a drag,
1348
+ * a key or the wheel goes through it so that a selection moves as one.
1377
1349
  */
1378
- nudgeFocusedPoint: (axis: 'x' | 'y', direction: number, modifiers: ModifierState) => boolean;
1350
+ editor: PointsEditorInstance;
1379
1351
  /** The selection box, while one is being dragged. */
1380
1352
  selectionBox: SelectionBoxRect | null;
1381
- beginSelectionBox: (at: PointBaseType, modifiers: ModifierState) => void;
1382
- moveSelectionBox: (to: PointBaseType) => void;
1383
- endSelectionBox: () => void;
1384
1353
  };
1385
1354
  /**
1386
1355
  * The settings `Root` was given, for the subcomponents to read. A point's
@@ -1392,10 +1361,6 @@ export declare function usePointsEditorContext<T>(selector: (state: PointsEditor
1392
1361
  //#endregion
1393
1362
  //#region src/components/PointsEditor/index.d.ts
1394
1363
  interface PointsEditorProps {
1395
- /** Sets `--width`; the size the theme gives it stands when omitted. */
1396
- width?: number | string;
1397
- /** Sets `--height`; the size the theme gives it stands when omitted. */
1398
- height?: number | string;
1399
1364
  /**
1400
1365
  * Make the points unchangeable and remove them from the tab order.
1401
1366
  * The parts carry `data-disabled` while it is set.
@@ -1405,16 +1370,14 @@ interface PointsEditorProps {
1405
1370
  * Make the points unmovable.
1406
1371
  * The parts carry `data-readonly` while it is set.
1407
1372
  */
1408
- readonly?: boolean;
1373
+ readOnly?: boolean;
1409
1374
  /**
1410
1375
  * The cursor to show while dragging a point. It is set on the dragged
1411
1376
  * point, so it stays while the pointer is outside it.
1412
1377
  *
1413
- * @default { cursor: 'grabbing' }
1378
+ * @default 'grabbing'
1414
1379
  */
1415
- externalStyles?: {
1416
- cursor?: CSSProperties['cursor'];
1417
- };
1380
+ dragCursor?: CSSProperties['cursor'];
1418
1381
  /**
1419
1382
  * How much one notch of the wheel moves the focused `Point`. Scrolling
1420
1383
  * sideways, or with shift held, moves x; otherwise it moves y.
@@ -1507,7 +1470,6 @@ interface PointsEditorProps {
1507
1470
  * </PointsEditor.Root>
1508
1471
  */
1509
1472
  children: ReactNode;
1510
- style?: CSSProperties & CSSVariables<'width' | 'height'>;
1511
1473
  }
1512
1474
  /**
1513
1475
  * Multiple Point Controller
@@ -1529,6 +1491,11 @@ interface SliderThumbProps {
1529
1491
  */
1530
1492
  color?: string;
1531
1493
  style?: CSSProperties & CSSVariables<'color' | 'translate'>;
1494
+ /**
1495
+ * Receives `focus` and `blur` for the range input inside, which do nothing
1496
+ * while the slider is disabled. `ref` reaches the thumb element itself.
1497
+ */
1498
+ actionsRef?: Ref<SliderThumbMethods>;
1532
1499
  }
1533
1500
  interface SliderThumbMethods {
1534
1501
  focus: () => void;
@@ -1544,26 +1511,13 @@ interface SliderTrackProps {
1544
1511
  length?: number | string;
1545
1512
  /** How thick the track is across that axis. Sets `--thickness`. */
1546
1513
  thickness?: number | string;
1547
- /** Colour of the part from `min` to the value. Sets `--active`. */
1548
- active?: string;
1549
- /** Colour of the rest of the track. Sets `--inactive`. */
1550
- inactive?: string;
1551
- style?: CSSProperties & CSSVariables<'length' | 'thickness' | 'active' | 'inactive' | 'percent'>;
1514
+ /** Colour of the part from `min` to the value. Sets `--active-color`. */
1515
+ activeColor?: string;
1516
+ /** Colour of the rest of the track. Sets `--inactive-color`. */
1517
+ inactiveColor?: string;
1518
+ style?: CSSProperties & CSSVariables<'length' | 'thickness' | 'active-color' | 'inactive-color' | 'percent'>;
1552
1519
  }
1553
1520
  //#endregion
1554
- //#region src/components/Slider/type.d.ts
1555
- /**
1556
- * How `Slider.Marks` fills itself in when it is given no children: one option
1557
- * every `per`, or every `step` of the slider. The object form turns off the
1558
- * mark or the label for the whole set; a single option is customized by
1559
- * writing `Slider.MarksOption` out instead.
1560
- */
1561
- type MarksOptions = 'step' | number | {
1562
- per: 'step' | number;
1563
- mark?: boolean;
1564
- label?: boolean;
1565
- };
1566
- //#endregion
1567
1521
  //#region src/components/Slider/Marks.d.ts
1568
1522
  interface SliderMarksProps {
1569
1523
  /**
@@ -1604,8 +1558,6 @@ interface SliderMarksOptionProps {
1604
1558
  length?: number | string;
1605
1559
  /** Space between the mark and the label. Sets `--gap`. */
1606
1560
  gap?: number | string;
1607
- /** Width of the label. Sets `--label-width`. */
1608
- labelWidth?: number | string;
1609
1561
  /** Classes for the mark and the label inside the option. */
1610
1562
  classes?: {
1611
1563
  mark?: string;
@@ -1616,9 +1568,9 @@ interface SliderMarksOptionProps {
1616
1568
  mark?: CSSProperties;
1617
1569
  label?: CSSProperties;
1618
1570
  };
1619
- style?: CSSProperties & CSSVariables<'thickness' | 'length' | 'gap' | 'label-width' | 'translate'>;
1571
+ style?: CSSProperties & CSSVariables<'thickness' | 'length' | 'gap' | 'translate'>;
1620
1572
  }
1621
- declare function MarksOption({ value, mark, label, thickness, length, gap, labelWidth, classes, styles, className, style, ...props }: SliderMarksOptionProps & Omit<ComponentPropsWithoutRef<'div'>, keyof SliderMarksOptionProps>): import("react").JSX.Element;
1573
+ declare function MarksOption({ value, mark, label, thickness, length, gap, classes, styles, className, style, ...props }: SliderMarksOptionProps & Omit<ComponentPropsWithoutRef<'div'>, keyof SliderMarksOptionProps>): import("react").JSX.Element;
1622
1574
  //#endregion
1623
1575
  //#region src/components/Slider/context.d.ts
1624
1576
  type SliderContextValue = {
@@ -1628,14 +1580,14 @@ type SliderContextValue = {
1628
1580
  step: number;
1629
1581
  /** How the value is distributed across the travel. */
1630
1582
  scale: Scale;
1631
- vertical: boolean;
1583
+ orientation: 'horizontal' | 'vertical';
1632
1584
  reverse: boolean;
1633
1585
  disabled: boolean;
1634
- readonly: boolean;
1586
+ readOnly: boolean;
1635
1587
  onChange?: (value: number) => void;
1636
1588
  /**
1637
1589
  * Position of the thumb, 0-100, already accounting for the display direction
1638
- * implied by `vertical` and `reverse`.
1590
+ * implied by `orientation` and `reverse`.
1639
1591
  */
1640
1592
  percent: number;
1641
1593
  /** `Track` registers its element here; `Root` normalizes the pointer against it. */
@@ -1676,14 +1628,15 @@ interface SliderProps {
1676
1628
  */
1677
1629
  scale?: Scale;
1678
1630
  /**
1679
- * Run the slider vertically, with the value growing upwards. The range input
1680
- * inside the thumb takes its `aria-orientation` from this.
1631
+ * Which way the slider runs. A vertical slider grows upwards. Every part
1632
+ * carries the same value as `data-orientation`, and the range input inside
1633
+ * the thumb takes its `aria-orientation` from it.
1681
1634
  *
1682
- * @default false
1635
+ * @default 'horizontal'
1683
1636
  */
1684
- vertical?: boolean;
1637
+ orientation?: 'horizontal' | 'vertical';
1685
1638
  /**
1686
- * Grow the value the other way: leftwards, or downwards when `vertical`.
1639
+ * Grow the value the other way: leftwards, or downwards when vertical.
1687
1640
  * The arrow keys follow the direction on screen.
1688
1641
  *
1689
1642
  * @default false
@@ -1693,11 +1646,9 @@ interface SliderProps {
1693
1646
  * The cursor to show while dragging. It is set on the dragged element, so it
1694
1647
  * stays while the pointer is outside the slider.
1695
1648
  *
1696
- * @default { cursor: 'pointer' }
1649
+ * @default 'pointer'
1697
1650
  */
1698
- externalStyles?: {
1699
- cursor?: CSSProperties['cursor'];
1700
- };
1651
+ dragCursor?: CSSProperties['cursor'];
1701
1652
  /**
1702
1653
  * How much one notch of the wheel moves the value. It only acts while the
1703
1654
  * focus is inside, so that scrolling the page past the slider leaves it
@@ -1752,13 +1703,28 @@ interface SliderProps {
1752
1703
  * Make the value unchangeable.
1753
1704
  * The parts carry `data-readonly` while it is set.
1754
1705
  */
1755
- readonly?: boolean;
1706
+ readOnly?: boolean;
1756
1707
  /** Called with the new value when a drag, the wheel or an arrow key moves it. */
1757
1708
  onChange?: (value: number) => void;
1758
- /** Called when a drag starts, with the value where the track was pressed. */
1759
- onDragStart?: (value: number) => void;
1760
- /** Called when the drag ends, with the value it ended on. */
1761
- onDragEnd?: (value: number) => void;
1709
+ /**
1710
+ * Called when a change of the value starts — a press on the track, the first wheel notch
1711
+ * or arrow key — with the value
1712
+ * before it and what it is made with. A host recording automation can treat
1713
+ * the control as touched from here until `onChangeEnd`.
1714
+ */
1715
+ onChangeStart?: (value: number, source: ChangeSource) => void;
1716
+ /**
1717
+ * Called when the change ends, with the value it ended on: on release, or
1718
+ * `changeEndDelay` after the last wheel notch or arrow key.
1719
+ */
1720
+ onChangeEnd?: (value: number, source: ChangeSource) => void;
1721
+ /**
1722
+ * How long after the last wheel notch or arrow key the change counts as
1723
+ * over, in milliseconds. Neither has an event that says it is done.
1724
+ *
1725
+ * @default 500
1726
+ */
1727
+ changeEndDelay?: number;
1762
1728
  /**
1763
1729
  * The slider renders exactly what you compose here; there is no default
1764
1730
  * markup to fall back to.
@@ -1771,6 +1737,12 @@ interface SliderProps {
1771
1737
  * </Slider.Root>
1772
1738
  */
1773
1739
  children: ReactNode;
1740
+ /**
1741
+ * Receives `focus` and `blur`, which act on the range input inside the thumb —
1742
+ * the element that takes the focus — and do nothing while the slider is
1743
+ * disabled. `ref` reaches the root element itself.
1744
+ */
1745
+ actionsRef?: Ref<SliderMethods>;
1774
1746
  }
1775
1747
  interface SliderMethods {
1776
1748
  focus: () => void;
@@ -1780,41 +1752,13 @@ interface SliderMethods {
1780
1752
  * Customizable slider
1781
1753
  */
1782
1754
  export declare const Slider: {
1783
- Root: React.ForwardRefExoticComponent<SliderProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof SliderProps> & React.RefAttributes<SliderMethods>>;
1784
- Thumb: React.ForwardRefExoticComponent<SliderThumbProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof SliderThumbProps> & React.RefAttributes<SliderThumbMethods>>;
1755
+ Root: React.ForwardRefExoticComponent<SliderProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof SliderProps> & React.RefAttributes<HTMLDivElement>>;
1756
+ Thumb: React.ForwardRefExoticComponent<SliderThumbProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof SliderThumbProps> & React.RefAttributes<HTMLDivElement>>;
1785
1757
  Track: React.ForwardRefExoticComponent<SliderTrackProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof SliderTrackProps> & React.RefAttributes<HTMLDivElement>>;
1786
1758
  Marks: typeof Marks;
1787
1759
  MarksOption: typeof MarksOption;
1788
1760
  };
1789
1761
  //#endregion
1790
- //#region src/components/XYPad/context.d.ts
1791
- type XYPadContextValue = {
1792
- value: XY<number>;
1793
- min: XY<number>;
1794
- max: XY<number>;
1795
- step: XY<number>;
1796
- /** How the value of each axis is distributed across the travel. */
1797
- scale: XY<Scale>;
1798
- reverse: XY<boolean>;
1799
- disabled: boolean;
1800
- readonly: boolean;
1801
- onChange?: (value: XY<number>) => void;
1802
- /**
1803
- * Position of the thumb, 0-100 per axis, already accounting for `reverse`.
1804
- */
1805
- percent: XY<number>;
1806
- /** `Area` registers its element here; `Root` normalizes the pointer against it. */
1807
- areaRef: RefObject<HTMLDivElement | null>;
1808
- /** `Thumb` registers itself here; `Root` focuses it when a drag starts. */
1809
- thumbRef: RefObject<XYPadThumbMethods | null>;
1810
- };
1811
- /**
1812
- * Everything here is derived during render, so there is no state to keep in
1813
- * sync: `value` comes from the props of `Root` and the rest follows from it.
1814
- */
1815
- export declare function useXYPadContext(): XYPadContextValue;
1816
- export declare function useXYPadContext<T>(selector: (state: XYPadContextValue) => T): T;
1817
- //#endregion
1818
1762
  //#region src/components/XYPad/Thumb.d.ts
1819
1763
  interface XYPadThumbProps {
1820
1764
  /**
@@ -1839,22 +1783,44 @@ interface XYPadThumbProps {
1839
1783
  */
1840
1784
  'aria-valuetext'?: XYInput<AriaAttributes['aria-valuetext']>;
1841
1785
  style?: CSSProperties & CSSVariables<'color' | 'translate'>;
1786
+ /**
1787
+ * Receives `focus` and `blur` for the range inputs inside, which do nothing
1788
+ * while the pad is disabled. `ref` reaches the thumb element itself.
1789
+ */
1790
+ actionsRef?: Ref<XYPadThumbMethods>;
1842
1791
  }
1843
1792
  interface XYPadThumbMethods {
1844
1793
  focus: () => void;
1845
1794
  blur: () => void;
1846
1795
  }
1847
1796
  //#endregion
1848
- //#region src/components/XYPad/Area.d.ts
1849
- interface XYPadAreaProps {
1850
- /** Sets `--width`; the size the theme gives it stands when omitted. */
1851
- width?: number | string;
1852
- /** Sets `--height`; the size the theme gives it stands when omitted. */
1853
- height?: number | string;
1854
- /** Sets `--color`, for the theme to colour the area with. */
1855
- color?: string;
1856
- style?: CSSProperties & CSSVariables<'width' | 'height' | 'color'>;
1857
- }
1797
+ //#region src/components/XYPad/context.d.ts
1798
+ type XYPadContextValue = {
1799
+ value: XY<number>;
1800
+ min: XY<number>;
1801
+ max: XY<number>;
1802
+ step: XY<number>;
1803
+ /** How the value of each axis is distributed across the travel. */
1804
+ scale: XY<Scale>;
1805
+ reverse: XY<boolean>;
1806
+ disabled: boolean;
1807
+ readOnly: boolean;
1808
+ onChange?: (value: XY<number>) => void;
1809
+ /**
1810
+ * Position of the thumb, 0-100 per axis, already accounting for `reverse`.
1811
+ */
1812
+ percent: XY<number>;
1813
+ /** `Area` registers its element here; `Root` normalizes the pointer against it. */
1814
+ areaRef: RefObject<HTMLDivElement | null>;
1815
+ /** `Thumb` registers itself here; `Root` focuses it when a drag starts. */
1816
+ thumbRef: RefObject<XYPadThumbMethods | null>;
1817
+ };
1818
+ /**
1819
+ * Everything here is derived during render, so there is no state to keep in
1820
+ * sync: `value` comes from the props of `Root` and the rest follows from it.
1821
+ */
1822
+ export declare function useXYPadContext(): XYPadContextValue;
1823
+ export declare function useXYPadContext<T>(selector: (state: XYPadContextValue) => T): T;
1858
1824
  //#endregion
1859
1825
  //#region src/components/XYPad/index.d.ts
1860
1826
  /**
@@ -1945,11 +1911,9 @@ interface XYPadProps {
1945
1911
  * The cursor to show while dragging. It is set on the dragged element, so it
1946
1912
  * stays while the pointer is outside the pad.
1947
1913
  *
1948
- * @default { cursor: 'pointer' }
1914
+ * @default 'pointer'
1949
1915
  */
1950
- externalStyles?: {
1951
- cursor?: CSSProperties['cursor'];
1952
- };
1916
+ dragCursor?: CSSProperties['cursor'];
1953
1917
  /**
1954
1918
  * Make the pad unchangeable and remove its thumb from the tab order.
1955
1919
  * The parts carry `data-disabled` while it is set.
@@ -1959,13 +1923,28 @@ interface XYPadProps {
1959
1923
  * Make the pad unchangeable while leaving its thumb focusable.
1960
1924
  * The parts carry `data-readonly` while it is set.
1961
1925
  */
1962
- readonly?: boolean;
1926
+ readOnly?: boolean;
1963
1927
  /** Called with the new value when a drag, the wheel or an arrow key moves it. */
1964
1928
  onChange?: (value: XY<number>) => void;
1965
- /** Called when a drag starts, with the value where the area was pressed. */
1966
- onDragStart?: (value: XY<number>) => void;
1967
- /** Called when the drag ends, with the value it ended on. */
1968
- onDragEnd?: (value: XY<number>) => void;
1929
+ /**
1930
+ * Called when a change of the value starts — a press on the area, the first wheel notch
1931
+ * or arrow key — with the value
1932
+ * before it and what it is made with. A host recording automation can treat
1933
+ * the control as touched from here until `onChangeEnd`.
1934
+ */
1935
+ onChangeStart?: (value: XY<number>, source: ChangeSource) => void;
1936
+ /**
1937
+ * Called when the change ends, with the value it ended on: on release, or
1938
+ * `changeEndDelay` after the last wheel notch or arrow key.
1939
+ */
1940
+ onChangeEnd?: (value: XY<number>, source: ChangeSource) => void;
1941
+ /**
1942
+ * How long after the last wheel notch or arrow key the change counts as
1943
+ * over, in milliseconds. Neither has an event that says it is done.
1944
+ *
1945
+ * @default 500
1946
+ */
1947
+ changeEndDelay?: number;
1969
1948
  /**
1970
1949
  * The pad renders exactly what you compose here; there is no default
1971
1950
  * markup to fall back to.
@@ -1978,23 +1957,46 @@ interface XYPadProps {
1978
1957
  * </XYPad.Root>
1979
1958
  */
1980
1959
  children: ReactNode;
1960
+ /**
1961
+ * Receives `focus` and `blur`, which act on the range inputs inside the thumb —
1962
+ * the elements that take the focus — and do nothing while
1963
+ * the pad is disabled. `ref` reaches the root element itself.
1964
+ */
1965
+ actionsRef?: Ref<XYPadMethods>;
1981
1966
  }
1982
1967
  interface XYPadMethods {
1983
1968
  focus: () => void;
1984
1969
  blur: () => void;
1985
- original: Ref<HTMLDivElement>;
1986
1970
  }
1987
1971
  /**
1988
1972
  * Simple XYPad
1989
1973
  */
1990
1974
  export declare const XYPad: {
1991
- Root: import("react").ForwardRefExoticComponent<XYPadProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof XYPadProps> & import("react").RefAttributes<XYPadMethods>>;
1992
- Thumb: import("react").ForwardRefExoticComponent<XYPadThumbProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof XYPadThumbProps> & import("react").RefAttributes<XYPadThumbMethods>>;
1993
- Area: import("react").ForwardRefExoticComponent<XYPadAreaProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof XYPadAreaProps> & import("react").RefAttributes<HTMLDivElement>>;
1975
+ Root: import("react").ForwardRefExoticComponent<XYPadProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof XYPadProps> & import("react").RefAttributes<HTMLDivElement>>;
1976
+ Thumb: import("react").ForwardRefExoticComponent<XYPadThumbProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof XYPadThumbProps> & import("react").RefAttributes<HTMLDivElement>>;
1977
+ Area: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
1994
1978
  };
1995
1979
  //#endregion
1996
1980
  //#region src/hooks/useAnimationFrame.d.ts
1997
- export declare function useAnimationFrame(callback?: () => void, deps?: DependencyList): void;
1981
+ interface UseAnimationFrameOptions {
1982
+ /**
1983
+ * Stop the loop. Turning it back on starts a new one, whose first frame has
1984
+ * a `deltaTime` of `0`.
1985
+ * @default false
1986
+ */
1987
+ disabled?: boolean;
1988
+ }
1989
+ /**
1990
+ * Call `callback` on every animation frame for as long as the component is
1991
+ * mounted.
1992
+ *
1993
+ * The callback is read on every frame, so it can be written inline and see
1994
+ * the latest render without restarting the loop.
1995
+ *
1996
+ * @param callback receives the frame's timestamp and the milliseconds since
1997
+ * the previous frame, which is `0` on the first one
1998
+ */
1999
+ export declare function useAnimationFrame(callback: (timestamp: DOMHighResTimeStamp, deltaTime: number) => void, { disabled }?: UseAnimationFrameOptions): void;
1998
2000
  //#endregion
1999
2001
  //#region src/hooks/useDrag.d.ts
2000
2002
  interface UseDragOptions {
@@ -2040,7 +2042,7 @@ export declare function useDrag<T extends Element>({ threshold, cursor, pointerL
2040
2042
  //#region src/hooks/useDragValue.d.ts
2041
2043
  interface UseDragValueOptions {
2042
2044
  /** Scaling of each axis; a single value applies to both. */
2043
- axis: XYInput$1<AxisOptions>;
2045
+ axis: XYInput<AxisOptions>;
2044
2046
  /**
2045
2047
  * Normalize the pointer against the bounding rect of this element, so that
2046
2048
  * the value *is* the position pointed at.
@@ -2054,12 +2056,12 @@ interface UseDragValueOptions {
2054
2056
  *
2055
2057
  * Give either this or `baseElementRef`.
2056
2058
  */
2057
- getValue?: () => XY$1<number>;
2059
+ getValue?: () => XY<number>;
2058
2060
  /**
2059
2061
  * Pixels of movement that span the whole range, with `getValue`.
2060
2062
  * @default 100
2061
2063
  */
2062
- pixelRange?: XYInput$1<number>;
2064
+ pixelRange?: XYInput<number>;
2063
2065
  /**
2064
2066
  * How much the movement counts, read on every move. `0.1` makes the same
2065
2067
  * movement cover a tenth of the range, which is what a fine-adjustment
@@ -2112,11 +2114,11 @@ interface UseDragValueOptions {
2112
2114
  * @param state the whole drag, for anything the value leaves out — the
2113
2115
  * pointer event and its modifier keys, most of all.
2114
2116
  */
2115
- onChange?: (value: XY$1<number>, state: DragState) => void;
2117
+ onChange?: (value: XY<number>, state: DragState) => void;
2116
2118
  /** Called once the drag starts, with the value it starts from. */
2117
- onDragStart?: (value: XY$1<number>, state: DragState) => void;
2119
+ onDragStart?: (value: XY<number>, state: DragState) => void;
2118
2120
  /** Called when the pointer is released, with the value it ends on. */
2119
- onDragEnd?: (value: XY$1<number>, state: DragState) => void;
2121
+ onDragEnd?: (value: XY<number>, state: DragState) => void;
2120
2122
  }
2121
2123
  /**
2122
2124
  * Drive a value with a pointer drag.
@@ -2145,17 +2147,40 @@ export declare function useDropZone<T extends Element>({ accept, multiple, disab
2145
2147
  };
2146
2148
  //#endregion
2147
2149
  //#region src/hooks/useEventListener.d.ts
2148
- type Target = EventTarget | null | (() => EventTarget | null);
2149
- type Options = boolean | AddEventListenerOptions;
2150
- export declare function useEventListener<K extends keyof DocumentEventMap>(target: Target, event: K, handler: (event: DocumentEventMap[K]) => void, options?: Options): VoidFunction;
2151
- export declare function useEventListener<K extends keyof WindowEventMap>(target: Target, event: K, handler: (event: WindowEventMap[K]) => void, options?: Options): VoidFunction;
2152
- export declare function useEventListener<K extends keyof GlobalEventHandlersEventMap>(target: Target, event: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, options?: Options): VoidFunction;
2153
- //#endregion
2154
- //#region src/hooks/useInterval.d.ts
2155
- export declare function useInterval(callback: () => void, delay: number | null): void;
2150
+ /**
2151
+ * What {@link useEventListener} listens on. A function is called after every
2152
+ * render, so it can return an element out of a ref; `null` listens on nothing.
2153
+ */
2154
+ type UseEventListenerTarget = EventTarget | null | (() => EventTarget | null);
2155
+ /**
2156
+ * The options of `addEventListener`, as a boolean for `capture` or as an
2157
+ * object. `signal` is left out: the hook already owns when the listener goes.
2158
+ */
2159
+ type UseEventListenerOptions = boolean | Pick<AddEventListenerOptions, 'capture' | 'once' | 'passive'>;
2160
+ /**
2161
+ * Listen to an event on a target for as long as the component is mounted.
2162
+ *
2163
+ * The handler is read on every event, and the target and the options are
2164
+ * compared by what they resolve to, so all three can be written inline. The
2165
+ * listener is re-attached only when the element, the event or one of the
2166
+ * options actually changes.
2167
+ *
2168
+ * @returns a function that removes the listener. It stays removed until the
2169
+ * target, the event or the options change.
2170
+ */
2171
+ export declare function useEventListener<K extends keyof DocumentEventMap>(target: UseEventListenerTarget, event: K, handler: (event: DocumentEventMap[K]) => void, options?: UseEventListenerOptions): VoidFunction;
2172
+ export declare function useEventListener<K extends keyof WindowEventMap>(target: UseEventListenerTarget, event: K, handler: (event: WindowEventMap[K]) => void, options?: UseEventListenerOptions): VoidFunction;
2173
+ export declare function useEventListener<K extends keyof GlobalEventHandlersEventMap>(target: UseEventListenerTarget, event: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, options?: UseEventListenerOptions): VoidFunction;
2156
2174
  //#endregion
2157
2175
  //#region src/hooks/useLongPress.d.ts
2158
- export declare function useLongPress(callback: () => void, initialDelay?: number, interval?: number): (event?: Pick<PointerEvent, "button" | "pointerId">) => void;
2176
+ /**
2177
+ * Repeat `callback` while a pointer is held down: once on the press, then
2178
+ * every `interval` after `initialDelay`. The repeat itself is
2179
+ * `createLongPress` in `@tremolo-ui/dom`.
2180
+ *
2181
+ * Returns the function that starts a press, for an `onPointerDown`.
2182
+ */
2183
+ export declare function useLongPress(callback: () => void, initialDelay?: number, interval?: number): (event?: Pick<PointerEvent, "button" | "pointerId">) => void | undefined;
2159
2184
  //#endregion
2160
2185
  //#region src/hooks/useMIDIAccess.d.ts
2161
2186
  /**
@@ -2169,7 +2194,7 @@ export declare function useLongPress(callback: () => void, initialDelay?: number
2169
2194
  * ask for it only when it is actually used.
2170
2195
  */
2171
2196
  export declare function useMIDIAccess(requestOnMount?: boolean): {
2172
- request: (options?: MIDIAccessOptions$1) => void;
2197
+ request: (options?: MIDIAccessOptions) => void;
2173
2198
  midiAccess: MIDIAccess | null;
2174
2199
  error: import("@tremolo-ui/dom").MIDIAccessError | null;
2175
2200
  inputs: readonly MIDIInput[];
@@ -2230,29 +2255,5 @@ interface UseWheelOptions extends Omit<WheelOptions, 'onWheel'> {
2230
2255
  */
2231
2256
  export declare function useWheel<T extends Element>(onWheel: (event: WheelEvent) => void, { requireFocus, target }?: UseWheelOptions): (node: T | null) => void;
2232
2257
  //#endregion
2233
- //#region src/input-event.d.ts
2234
- /**
2235
- * The keyboard amount used by Knob, NumberInput, Slider, and XYPad by default:
2236
- * 1 per press in the units of the value, and 0.1 with shift held. That is one
2237
- * `step` only while `step` is 1; a coarser `step` rounds 1 straight back, which
2238
- * `useCheckSteps` warns about.
2239
- *
2240
- * A modifier entry is not snapped to `step`, which is what lets the finer
2241
- * amount move at all — see `applyDelta` in `@tremolo-ui/dom`.
2242
- */
2243
- export declare const DEFAULT_KEYBOARD_OPTIONS: ModifierValue<InputEventOption>;
2244
- /**
2245
- * The wheel amount used by Knob, NumberInput, Slider, and XYPad by default.
2246
- *
2247
- * Browsers turn shift+wheel into horizontal scrolling, which empties `deltaY`
2248
- * and fills `deltaX`, so no modifier is bound here.
2249
- */
2250
- export declare const DEFAULT_WHEEL_OPTIONS: ModifierValue<InputEventOption>;
2251
- /**
2252
- * The drag sensitivity used by value controls by default. Shift makes the
2253
- * same movement cover a tenth of the range, matching the arrow keys.
2254
- */
2255
- export declare const DEFAULT_DRAG_SENSITIVITY: ModifierValue<number>;
2256
- //#endregion
2257
- export { type AnimationCanvasCommonProps, type AnimationCanvasFixedProps, type AnimationCanvasProps, type AnimationCanvasResizableProps, type CSSVariables, type DrawFunction, type DropZoneProps, type FileInputContextValue, type FileInputProps, type FileInputTriggerProps, type InitFunction, type KeyAttributes, type KeyState, type KeyboardShortcuts, type KnobContextValue, type KnobMethods, type KnobProps, type KnobSVGRootProps, type KnobThumbProps, type MIDIAccessError, type MIDIAccessOptions, type MIDIInputHandlers, type MarksOptions, NOT_SUPPORTED, type NumberInputContextValue, type NumberInputMethods, type NumberInputProps, PERMISSION_DENIED, PITCH_BEND_CENTER, type PianoMethods, type PianoProps, type PointBaseType, type PointsEditorContextValue, type PointsEditorPointProps, type PointsEditorProps, type SliderContextValue, type SliderMarksOptionProps, type SliderMarksProps, type SliderMethods, type SliderProps, type SliderThumbMethods, type SliderThumbProps, type SliderTrackProps, UNAVAILABLE, type UseDragOptions, type UseDragValueOptions, type UseDropZoneOptions, type UseWheelOptions, type XY, type XYInput, type XYPadAreaProps, type XYPadContextValue, type XYPadMethods, type XYPadProps, type XYPadThumbMethods, type XYPadThumbProps };
2258
+ export type { AnimationCanvasCommonProps, AnimationCanvasFixedProps, AnimationCanvasProps, AnimationCanvasResizableProps, CSSVariables, DropZoneProps, FileInputContextValue, FileInputProps, FileInputTriggerProps, KeyAttributes, KeyState, KnobContextValue, KnobMethods, KnobProps, KnobSVGRootProps, KnobThumbProps, NumberInputContextValue, NumberInputMethods, NumberInputProps, PianoMethods, PianoProps, PointsEditorContextValue, PointsEditorPointProps, PointsEditorProps, SliderContextValue, SliderMarksOptionProps, SliderMarksProps, SliderMethods, SliderProps, SliderThumbMethods, SliderThumbProps, SliderTrackProps, UseAnimationFrameOptions, UseDragOptions, UseDragValueOptions, UseDropZoneOptions, UseEventListenerOptions, UseEventListenerTarget, UseWheelOptions, XYPadContextValue, XYPadMethods, XYPadProps, XYPadThumbMethods, XYPadThumbProps };
2258
2259
  //# sourceMappingURL=index.d.ts.map