@tremolo-ui/react 0.7.0 → 0.8.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 (47) hide show
  1. package/dist/index.cjs +346 -1015
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +76 -221
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.ts +76 -221
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +333 -978
  8. package/dist/index.js.map +1 -1
  9. package/package.json +3 -3
  10. package/src/components/DropZone/index.tsx +2 -1
  11. package/src/components/FileInput/index.tsx +8 -13
  12. package/src/components/Knob/ActiveLine.tsx +5 -3
  13. package/src/components/Knob/InactiveLine.tsx +6 -4
  14. package/src/components/Knob/SVGRoot.tsx +3 -3
  15. package/src/components/Knob/Thumb.tsx +3 -2
  16. package/src/components/Knob/context.tsx +3 -74
  17. package/src/components/Knob/index.tsx +19 -16
  18. package/src/components/NumberInput/InputField.tsx +12 -27
  19. package/src/components/NumberInput/Stepper.tsx +49 -97
  20. package/src/components/NumberInput/StepperButton.tsx +3 -4
  21. package/src/components/NumberInput/context.tsx +2 -1
  22. package/src/components/NumberInput/index.tsx +40 -71
  23. package/src/components/Piano/index.tsx +35 -142
  24. package/src/components/PointsEditor/Container.tsx +15 -26
  25. package/src/components/PointsEditor/Point.tsx +38 -85
  26. package/src/components/PointsEditor/context.tsx +5 -56
  27. package/src/components/PointsEditor/index.tsx +29 -311
  28. package/src/components/Slider/Marks.tsx +3 -5
  29. package/src/components/Slider/MarksOption.tsx +7 -18
  30. package/src/components/Slider/Track.tsx +2 -1
  31. package/src/components/Slider/index.tsx +29 -28
  32. package/src/components/XYPad/Area.tsx +27 -49
  33. package/src/components/XYPad/Thumb.tsx +3 -1
  34. package/src/components/XYPad/context.tsx +1 -3
  35. package/src/components/XYPad/index.tsx +33 -46
  36. package/src/components/_util/VisuallyHiddenRangeInput.tsx +1 -1
  37. package/src/hooks/_internal/useCheckSteps.ts +9 -146
  38. package/src/hooks/useLongPress.ts +35 -51
  39. package/src/hooks/useMIDIAccess.ts +0 -8
  40. package/src/hooks/useMIDIInput.ts +0 -3
  41. package/src/index.ts +2 -27
  42. package/src/components/Piano/keyboard-shortcuts.ts +0 -61
  43. package/src/components/Slider/type.ts +0 -46
  44. package/src/components/_util/css-length.ts +0 -13
  45. package/src/components/_util/decimal-digits.ts +0 -23
  46. package/src/components/_util/visually-hidden.ts +0 -25
  47. package/src/input-event.ts +0 -32
@@ -1,61 +0,0 @@
1
- export type KeyboardShortcuts = {
2
- /**
3
- * Keys laid out from `noteRange.first`, one entry per semitone.
4
- *
5
- * An empty string leaves that note without a shortcut: `KeyboardEvent.key` is
6
- * never empty, so the entry can never match. Use it to skip the black keys
7
- * (see {@link SHORTCUTS.HOME_ROW_NATURAL}) and keep the remaining entries
8
- * lined up with the notes.
9
- */
10
- keys: string[]
11
- }
12
-
13
- /**
14
- * Ready-made keyboard layouts. Both assume `noteRange.first` is a C.
15
- */
16
- export const SHORTCUTS = {
17
- /** Every semitone from C, over the two rows of a QWERTY keyboard. */
18
- HOME_ROW: {
19
- keys: [
20
- 'a',
21
- 'w',
22
- 's',
23
- 'e',
24
- 'd',
25
- 'f',
26
- 't',
27
- 'g',
28
- 'y',
29
- 'h',
30
- 'u',
31
- 'j',
32
- 'k',
33
- 'o',
34
- 'l',
35
- 'p',
36
- ';',
37
- ],
38
- },
39
- /** The white keys only, on the home row. Black keys have no shortcut. */
40
- HOME_ROW_NATURAL: {
41
- keys: [
42
- 'a',
43
- '',
44
- 's',
45
- '',
46
- 'd',
47
- 'f',
48
- '',
49
- 'g',
50
- '',
51
- 'h',
52
- '',
53
- 'j',
54
- 'k',
55
- '',
56
- 'l',
57
- '',
58
- ';',
59
- ],
60
- },
61
- }
@@ -1,46 +0,0 @@
1
- import { toFixed } from '@tremolo-ui/functions'
2
-
3
- import { decimalDigits } from '../_util/decimal-digits'
4
-
5
- /**
6
- * How `Slider.Marks` fills itself in when it is given no children: one option
7
- * every `per`, or every `step` of the slider. The object form turns off the
8
- * mark or the label for the whole set; a single option is customized by
9
- * writing `Slider.MarksOption` out instead.
10
- */
11
- export type MarksOptions =
12
- | 'step'
13
- | number
14
- | {
15
- per: 'step' | number
16
- mark?: boolean
17
- label?: boolean
18
- }
19
-
20
- export function generateOptionsList(
21
- options: MarksOptions,
22
- min: number,
23
- max: number,
24
- step: number,
25
- ) {
26
- const {
27
- per,
28
- mark = true,
29
- label = true,
30
- } = typeof options === 'object' ? options : { per: options }
31
- const optionsList: {
32
- value: number
33
- mark: boolean
34
- label: boolean
35
- }[] = []
36
- const interval = per === 'step' ? step : per
37
- const count = Math.floor(max / interval) - Math.ceil(min / interval) + 1
38
- for (let i = 0; i < count; i++) {
39
- const value = toFixed(
40
- interval * (Math.ceil(min / interval) + i),
41
- decimalDigits(interval),
42
- )
43
- optionsList.push({ value: value, mark: mark, label: label })
44
- }
45
- return optionsList
46
- }
@@ -1,13 +0,0 @@
1
- /**
2
- * A number as a CSS length, for a custom property.
3
- *
4
- * React appends `px` to a bare number for the properties it knows take a
5
- * length, and a custom property is never one of them: `--size: 50` would come
6
- * out as the invalid `50`. Anything already a string is passed through, so
7
- * `'3rem'` and `'100%'` still work.
8
- */
9
- export function cssLength(
10
- value: number | string | undefined,
11
- ): string | undefined {
12
- return typeof value === 'number' ? `${value}px` : value
13
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * How many digits a number carries after the decimal point.
3
- *
4
- * `Slider.Marks` builds its labels by multiplying an interval, which leaves
5
- * binary debris in the last digits (`0.1 * 3` is `0.30000000000000004`). The
6
- * count is what tells `toFixed` how far to round that back.
7
- *
8
- * The exponent form has to be handled separately: `String(1e-7)` is `'1e-7'`,
9
- * which has no decimal point at all, so reading the text after the point
10
- * reports no digits and the interval rounds away to whole numbers.
11
- */
12
- export function decimalDigits(x: number): number {
13
- if (!Number.isFinite(x)) return 0
14
-
15
- const text = String(x)
16
- const e = text.indexOf('e')
17
- if (e === -1) return text.split('.')[1]?.length ?? 0
18
-
19
- const fraction = text.slice(0, e).split('.')[1]?.length ?? 0
20
- // A negative exponent pushes the point further right, a positive one pulls
21
- // it back past the digits that are there.
22
- return Math.max(0, fraction - Number(text.slice(e + 1)))
23
- }
@@ -1,25 +0,0 @@
1
- import type { CSSProperties } from 'react'
2
-
3
- /**
4
- * Take an element out of sight while leaving it in the accessibility tree and
5
- * in the tab order.
6
- *
7
- * `display: none` and `visibility: hidden` would remove it from both, and the
8
- * native control underneath a headless component is what carries the ARIA and
9
- * the keyboard behaviour. `pointer-events: none` is safe because nothing is
10
- * ever clicked here directly: a `<label>` forwards its click, and a drag is
11
- * handled by the part that is visible.
12
- */
13
- export const visuallyHiddenStyle: CSSProperties = {
14
- position: 'absolute',
15
- width: 1,
16
- height: 1,
17
- padding: 0,
18
- margin: -1,
19
- overflow: 'hidden',
20
- clip: 'rect(0, 0, 0, 0)',
21
- clipPath: 'inset(50%)',
22
- whiteSpace: 'nowrap',
23
- border: 0,
24
- pointerEvents: 'none',
25
- }
@@ -1,32 +0,0 @@
1
- import { type InputEventOption, type ModifierValue } from '@tremolo-ui/dom'
2
-
3
- /**
4
- * The keyboard amount used by Knob, NumberInput, Slider, and XYPad by default:
5
- * 1 per press in the units of the value, and 0.1 with shift held. That is one
6
- * `step` only while `step` is 1; a coarser `step` rounds 1 straight back, which
7
- * `useCheckSteps` warns about.
8
- *
9
- * A modifier entry is not snapped to `step`, which is what lets the finer
10
- * amount move at all — see `applyDelta` in `@tremolo-ui/dom`.
11
- */
12
- export const DEFAULT_KEYBOARD_OPTIONS: ModifierValue<InputEventOption> = {
13
- default: ['raw', 1],
14
- shift: ['raw', 0.1],
15
- }
16
-
17
- /**
18
- * The wheel amount used by Knob, NumberInput, Slider, and XYPad by default.
19
- *
20
- * Browsers turn shift+wheel into horizontal scrolling, which empties `deltaY`
21
- * and fills `deltaX`, so no modifier is bound here.
22
- */
23
- export const DEFAULT_WHEEL_OPTIONS: ModifierValue<InputEventOption> = ['raw', 1]
24
-
25
- /**
26
- * The drag sensitivity used by value controls by default. Shift makes the
27
- * same movement cover a tenth of the range, matching the arrow keys.
28
- */
29
- export const DEFAULT_DRAG_SENSITIVITY: ModifierValue<number> = {
30
- default: 1,
31
- shift: 0.1,
32
- }