@tremolo-ui/react 0.5.0 → 0.7.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 (86) hide show
  1. package/dist/compose-refs.cjs +72 -0
  2. package/dist/compose-refs.cjs.map +1 -0
  3. package/dist/compose-refs.d.cts +43 -0
  4. package/dist/compose-refs.d.cts.map +1 -0
  5. package/dist/compose-refs.d.ts +43 -0
  6. package/dist/compose-refs.d.ts.map +1 -0
  7. package/dist/compose-refs.js +70 -0
  8. package/dist/compose-refs.js.map +1 -0
  9. package/dist/index.cjs +1669 -541
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +1571 -486
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.ts +1571 -486
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1640 -538
  16. package/dist/index.js.map +1 -1
  17. package/package.json +29 -27
  18. package/src/components/AnimationCanvas/index.tsx +115 -76
  19. package/src/components/DropZone/index.tsx +100 -0
  20. package/src/components/FileInput/Trigger.tsx +39 -0
  21. package/src/components/FileInput/context.tsx +24 -0
  22. package/src/components/FileInput/index.tsx +144 -0
  23. package/src/components/Knob/ActiveLine.tsx +7 -6
  24. package/src/components/Knob/InactiveLine.tsx +9 -10
  25. package/src/components/Knob/SVGRoot.tsx +5 -3
  26. package/src/components/Knob/Thumb.tsx +33 -11
  27. package/src/components/Knob/context.tsx +17 -1
  28. package/src/components/Knob/index.tsx +156 -60
  29. package/src/components/NumberInput/DecrementStepper.tsx +3 -10
  30. package/src/components/NumberInput/IncrementStepper.tsx +3 -10
  31. package/src/components/NumberInput/InputField.tsx +185 -108
  32. package/src/components/NumberInput/Stepper.tsx +120 -84
  33. package/src/components/NumberInput/StepperButton.tsx +100 -0
  34. package/src/components/NumberInput/context.tsx +34 -8
  35. package/src/components/NumberInput/index.tsx +270 -82
  36. package/src/components/Piano/index.tsx +363 -200
  37. package/src/components/PointsEditor/Background.tsx +13 -10
  38. package/src/components/PointsEditor/Container.tsx +83 -29
  39. package/src/components/PointsEditor/Point.tsx +241 -79
  40. package/src/components/PointsEditor/SelectionBox.tsx +48 -0
  41. package/src/components/PointsEditor/context.tsx +78 -10
  42. package/src/components/PointsEditor/index.tsx +440 -41
  43. package/src/components/Slider/Marks.tsx +48 -19
  44. package/src/components/Slider/MarksOption.tsx +64 -45
  45. package/src/components/Slider/Thumb.tsx +107 -55
  46. package/src/components/Slider/Track.tsx +66 -62
  47. package/src/components/Slider/context.tsx +4 -2
  48. package/src/components/Slider/index.tsx +136 -77
  49. package/src/components/Slider/type.ts +29 -9
  50. package/src/components/XYPad/Area.tsx +46 -41
  51. package/src/components/XYPad/Thumb.tsx +131 -64
  52. package/src/components/XYPad/context.tsx +4 -1
  53. package/src/components/XYPad/index.tsx +183 -53
  54. package/src/components/_util/Placement.tsx +68 -0
  55. package/src/components/_util/VisuallyHiddenRangeInput.tsx +12 -0
  56. package/src/components/_util/css-length.ts +13 -0
  57. package/src/components/_util/decimal-digits.ts +23 -0
  58. package/src/components/_util/visually-hidden.ts +25 -0
  59. package/src/{components/_util/composeRefs.tsx → compose-refs/index.tsx} +33 -5
  60. package/src/css-variables.ts +23 -0
  61. package/src/hooks/_internal/useCallbackRef.ts +3 -1
  62. package/src/hooks/_internal/useCheckSteps.ts +169 -0
  63. package/src/hooks/useAnimationFrame.ts +17 -7
  64. package/src/hooks/useDrag.ts +51 -12
  65. package/src/hooks/useDragValue.ts +71 -11
  66. package/src/hooks/useDropZone.ts +78 -0
  67. package/src/hooks/useEventListener.ts +10 -6
  68. package/src/hooks/useLongPress.ts +42 -8
  69. package/src/hooks/useMIDIAccess.ts +82 -11
  70. package/src/hooks/useMIDIInput.ts +45 -13
  71. package/src/hooks/useMIDIMessage.ts +23 -5
  72. package/src/hooks/useWheel.ts +4 -1
  73. package/src/index.ts +45 -25
  74. package/src/input-event.ts +32 -0
  75. package/dist/index.css +0 -501
  76. package/src/Globals.d.ts +0 -3
  77. package/src/components/Knob/index.css +0 -81
  78. package/src/components/NumberInput/index.css +0 -121
  79. package/src/components/NumberInput/stepperButton.tsx +0 -90
  80. package/src/components/Piano/index.css +0 -90
  81. package/src/components/PointsEditor/index.css +0 -35
  82. package/src/components/Slider/index.css +0 -125
  83. package/src/components/XYPad/index.css +0 -60
  84. package/src/components/_util/index.ts +0 -28
  85. package/src/styles/global.css +0 -19
  86. /package/src/components/Piano/{keyboardShortcuts.ts → keyboard-shortcuts.ts} +0 -0
@@ -1,90 +0,0 @@
1
- import clsx from 'clsx'
2
- import {
3
- ComponentPropsWithoutRef,
4
- CSSProperties,
5
- ReactNode,
6
- useCallback,
7
- } from 'react'
8
-
9
- import { useLongPress } from '../../hooks/useLongPress'
10
-
11
- import { useNumberInputContext, useStepperContext } from './context'
12
-
13
- export interface StepperButtonProps {
14
- className?: string
15
- style?: CSSProperties
16
- /** Replaces the default arrow. Size it with the `--stepper-icon-size` variable. */
17
- children?: ReactNode
18
- }
19
-
20
- type Props = StepperButtonProps &
21
- Omit<ComponentPropsWithoutRef<'div'>, keyof StepperButtonProps>
22
-
23
- /**
24
- * Shared body of `IncrementStepper` and `DecrementStepper`: the two differ only
25
- * in which way they move the value and which arrow they draw.
26
- */
27
- export function StepperButton({
28
- direction,
29
- variant,
30
- icon,
31
- className,
32
- style,
33
- children,
34
- onPointerDown,
35
- ...props
36
- }: Props & {
37
- direction: 1 | -1
38
- variant: 'increment' | 'decrement'
39
- icon: ReactNode
40
- }) {
41
- const { step, readonly, atMin, atMax, nudge } = useNumberInputContext()
42
- const stepper = useStepperContext()
43
-
44
- const press = useLongPress(
45
- useCallback(() => {
46
- // Once the pointer has actually travelled, the drag on `Stepper` owns the
47
- // value; repeating on top of it would move it twice.
48
- if (stepper?.draggingRef.current) return
49
- nudge(direction, ['raw', step])
50
- }, [stepper, nudge, direction, step]),
51
- )
52
-
53
- return (
54
- // eslint-disable-next-line jsx-a11y/role-supports-aria-props
55
- <div
56
- className={clsx(`tremolo-number-input-${variant}-stepper`, className)}
57
- role="button"
58
- tabIndex={-1}
59
- // A bare arrow has no accessible name of its own. Overridable, since a
60
- // caller may need it in their own language.
61
- aria-label={direction > 0 ? 'Increment' : 'Decrement'}
62
- aria-disabled={direction > 0 ? atMax : atMin}
63
- aria-readonly={readonly}
64
- style={style}
65
- onPointerDown={(event) => {
66
- if (!readonly) press()
67
- onPointerDown?.(event)
68
- }}
69
- {...props}
70
- >
71
- {children ?? icon}
72
- </div>
73
- )
74
- }
75
-
76
- export function StepperArrow({ up }: { up: boolean }) {
77
- return (
78
- <svg
79
- className="tremolo-number-input-stepper-icon"
80
- viewBox="0 0 24 24"
81
- fill="none"
82
- stroke="currentColor"
83
- strokeWidth="2"
84
- strokeLinecap="round"
85
- strokeLinejoin="round"
86
- >
87
- <polyline points={up ? '18 15 12 9 6 15' : '6 9 12 15 18 9'} />
88
- </svg>
89
- )
90
- }
@@ -1,90 +0,0 @@
1
- .tremolo-piano {
2
- display: inline-block;
3
- box-sizing: border-box;
4
- user-select: none;
5
- touch-action: none;
6
- position: relative;
7
- }
8
-
9
- .tremolo-piano-white-key {
10
- --bg: oklch(100% 0 0);
11
- --color: oklch(0% 0 0);
12
- --active-bg: oklch(92% 0 0);
13
- --active-color: oklch(0% 0 0);
14
-
15
- box-sizing: border-box;
16
- position: absolute;
17
- background-color: var(--bg);
18
- -webkit-tap-highlight-color: transparent;
19
- color: var(--color);
20
- border: 1px solid #555;
21
- border-radius: 0px 0px 8px 8px;
22
- cursor: pointer;
23
- z-index: 1;
24
-
25
- &[data-active='true'] {
26
- background-color: var(--active-bg);
27
- color: var(--active-color);
28
- }
29
-
30
- &[aria-disabled='true'] {
31
- cursor: not-allowed;
32
- }
33
- }
34
-
35
- .tremolo-piano-black-key {
36
- --color: oklch(100% 0 0);
37
- --bg: oklch(32% 0 0);
38
- --active-color: oklch(100% 0 0);
39
- --active-bg: oklch(44% 0 0);
40
-
41
- box-sizing: border-box;
42
- position: absolute;
43
- background-color: var(--bg);
44
- -webkit-tap-highlight-color: transparent;
45
- color: var(--color);
46
- border: 1px solid #555;
47
- border-radius: 0px 0px 8px 8px;
48
- cursor: pointer;
49
- z-index: 2;
50
-
51
- &[data-active='true'] {
52
- background-color: var(--active-bg);
53
- color: var(--active-color);
54
- }
55
-
56
- &[aria-disabled='true'] {
57
- cursor: not-allowed;
58
- }
59
- }
60
-
61
- .tremolo-piano-key-label-wrapper {
62
- display: flex;
63
- justify-content: center;
64
- align-items: end;
65
- height: 100%;
66
- }
67
-
68
- .tremolo-piano-key-label {
69
- box-sizing: content-box;
70
- display: flex;
71
- justify-content: center;
72
- align-items: center;
73
- font-size: 0.6rem;
74
- height: 10px;
75
- margin-bottom: 10px;
76
- padding: 4px;
77
- border-radius: 4px;
78
- border: 1px solid #888;
79
- aspect-ratio: 1;
80
- max-width: calc(100% - 16px);
81
- }
82
-
83
- :where(.dark, [data-theme='dark']) {
84
- .tremolo-piano-white-key {
85
- --bg: oklch(80% 0 0);
86
- --color: oklch(0% 0 0);
87
- --active-bg: oklch(72% 0 0);
88
- --active-color: oklch(0% 0 0);
89
- }
90
- }
@@ -1,35 +0,0 @@
1
- .tremolo-points-editor {
2
- position: relative;
3
- }
4
-
5
- .tremolo-points-editor-background {
6
- position: absolute;
7
- inset: 0;
8
- z-index: 0;
9
- }
10
-
11
- .tremolo-points-editor-container {
12
- position: absolute;
13
- inset: 0;
14
- z-index: 10;
15
- }
16
-
17
- .tremolo-points-editor-point {
18
- --color: oklch(59.5% 0.17548 266.373);
19
-
20
- position: absolute;
21
- border-radius: 50%;
22
- outline: none;
23
- cursor: grab;
24
- background-color: var(--color);
25
- translate: -50% -50%;
26
-
27
- &[data-dragging='true'] {
28
- cursor: inherit;
29
- }
30
-
31
- /* Dragging does nothing while readonly, so do not offer to. */
32
- &[aria-readonly='true'] {
33
- cursor: default;
34
- }
35
- }
@@ -1,125 +0,0 @@
1
- .tremolo-slider {
2
- /* Half the thumb size. The thumb overhangs the ends of the track, so the
3
- slider reserves room for it. Override this when using a different size. */
4
- --thumb-size: 22px;
5
-
6
- display: inline-flex;
7
- flex-direction: column;
8
- margin: calc(var(--thumb-size) / 2);
9
- cursor: pointer;
10
- outline: 0;
11
- -webkit-tap-highlight-color: transparent;
12
-
13
- &[data-vertical='true'] {
14
- flex-direction: row;
15
- }
16
-
17
- &[aria-readonly='true'] {
18
- cursor: not-allowed;
19
- }
20
- }
21
-
22
- .tremolo-slider-thumb-wrapper {
23
- position: absolute;
24
- translate: -50% -50%;
25
- z-index: 100;
26
- }
27
-
28
- .tremolo-slider-thumb {
29
- --color: oklch(59.5% 0.17548 266.373);
30
-
31
- width: var(--thumb-size);
32
- height: var(--thumb-size);
33
-
34
- background: var(--color);
35
- border-radius: 50%;
36
- outline: none;
37
-
38
- &[aria-disabled='true'] {
39
- background: oklch(50.462% 0.03307 270.021);
40
- }
41
-
42
- &[aria-readonly='false']:focus {
43
- box-shadow: 0px 0px 0px 3px
44
- color-mix(in srgb, var(--color) 20%, transparent);
45
- }
46
- }
47
-
48
- .tremolo-slider-track {
49
- --active: oklch(69.212% 0.12903 267.633);
50
- --inactive: oklch(95% 0 0);
51
-
52
- position: relative;
53
-
54
- &[data-vertical='false'] {
55
- min-width: 50px;
56
- }
57
-
58
- &[data-vertical='true'] {
59
- min-height: 50px;
60
- }
61
-
62
- &:hover {
63
- --active: oklch(64.276% 0.15244 266.932);
64
- --inactive: #e0e0e0;
65
- }
66
-
67
- &[aria-disabled='true'] {
68
- --active: oklch(75.327% 0.01237 264.547);
69
- --inactive: oklch(89.755% 0.0001 271.152);
70
- }
71
- }
72
-
73
- .tremolo-slider-marks {
74
- display: block;
75
- position: relative;
76
- }
77
-
78
- .tremolo-slider-marks-option {
79
- display: flex;
80
- color: oklch(25.197% 0.00003 271.152);
81
- flex-direction: column;
82
- justify-content: center;
83
- align-items: center;
84
- position: absolute;
85
- translate: -50% 0;
86
- z-index: 10;
87
-
88
- &[data-vertical='true'] {
89
- flex-direction: row;
90
- translate: 0 -50%;
91
- }
92
- }
93
-
94
- .tremolo-slider-marks-option-mark {
95
- background-color: currentColor;
96
- }
97
-
98
- .tremolo-slider-marks-option-label {
99
- text-align: right;
100
- }
101
-
102
- :where(.dark, [data-theme='dark']) {
103
- .tremolo-slider-thumb {
104
- --color: oklch(64.5% 0.17548 266.373);
105
-
106
- &:hover {
107
- --color: oklch(67.5% 0.17548 266.373);
108
- }
109
- }
110
-
111
- .tremolo-slider-track {
112
- --active: oklch(59.5% 0.17548 266.373);
113
- --inactive: oklch(41.7% 0 0);
114
-
115
- &:hover {
116
- --active: oklch(62.5% 0.17548 266.373);
117
- --inactive: oklch(44.7% 0 0);
118
- }
119
-
120
- &[aria-disabled='true'] {
121
- --active: oklch(75.327% 0.01237 264.547);
122
- --inactive: oklch(89.755% 0.0001 271.152);
123
- }
124
- }
125
- }
@@ -1,60 +0,0 @@
1
- .tremolo-xy-pad {
2
- /* Half the thumb size. The thumb overhangs the edges of the area, so the
3
- pad reserves room for it. Override this when using a different size. */
4
- --thumb-size: 22px;
5
-
6
- display: inline-block;
7
- margin: calc(var(--thumb-size) / 2);
8
- cursor: pointer;
9
- -webkit-tap-highlight-color: transparent;
10
-
11
- &[aria-readonly='true'] {
12
- cursor: not-allowed;
13
- }
14
- }
15
-
16
- .tremolo-xy-pad-area {
17
- --color: oklch(95% 0 0);
18
-
19
- position: relative;
20
- background-color: var(--color);
21
- }
22
-
23
- .tremolo-xy-pad-thumb-wrapper {
24
- position: absolute;
25
- translate: -50% -50%;
26
- z-index: 100;
27
- }
28
-
29
- .tremolo-xy-pad-thumb {
30
- --color: oklch(59.5% 0.17548 266.373);
31
-
32
- width: var(--thumb-size);
33
- height: var(--thumb-size);
34
- border-radius: 50%;
35
- outline: none;
36
- background-color: var(--color);
37
-
38
- &[aria-disabled='true'] {
39
- background-color: oklch(50.462% 0.03307 270.021);
40
- }
41
-
42
- &[aria-readonly='false']:focus {
43
- box-shadow: 0px 0px 0px 3px
44
- color-mix(in srgb, var(--color) 20%, transparent);
45
- }
46
- }
47
-
48
- :where(.dark, [data-theme='dark']) {
49
- .tremolo-xy-pad-area {
50
- --color: oklch(41.7% 0 0);
51
- }
52
-
53
- .tremolo-xy-pad-thumb {
54
- --color: oklch(64.5% 0.17548 266.373);
55
-
56
- &:hover {
57
- --color: oklch(67.5% 0.17548 266.373);
58
- }
59
- }
60
- }
@@ -1,28 +0,0 @@
1
- export function addUserSelectNone() {
2
- window.document.body.classList.add('tremolo-user-select-none')
3
- }
4
-
5
- export function removeUserSelectNone() {
6
- window.document.body.classList.remove('tremolo-user-select-none')
7
- }
8
-
9
- const cursorStyles = {
10
- grabbing: 'tremolo-cursor-grabbing',
11
- grab: 'tremolo-cursor-grab',
12
- pointer: 'tremolo-cursor-pointer',
13
- move: 'tremolo-cursor-move',
14
- none: 'tremolo-cursor-none',
15
- }
16
-
17
- export type Cursor = keyof typeof cursorStyles
18
-
19
- export function setCursorStyle(type: Cursor) {
20
- resetCursorStyle()
21
- window.document.body.classList.add(cursorStyles[type])
22
- }
23
-
24
- export function resetCursorStyle() {
25
- Object.values(cursorStyles).forEach((s) => {
26
- window.document.body.classList.remove(s)
27
- })
28
- }
@@ -1,19 +0,0 @@
1
- .tremolo-user-select-none {
2
- user-select: none;
3
- }
4
-
5
- .tremolo-cursor-pointer {
6
- cursor: pointer;
7
- }
8
-
9
- .tremolo-cursor-move {
10
- cursor: move;
11
- }
12
-
13
- .tremolo-cursor-grabbing {
14
- cursor: grabbing;
15
- }
16
-
17
- .tremolo-cursor-none {
18
- cursor: none;
19
- }