@tremolo-ui/react 0.1.5 → 0.2.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.
- package/dist/index.cjs +325 -239
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +149 -64
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +229 -199
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +229 -199
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +314 -223
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Knob/index.css +50 -25
- package/src/components/Knob/index.tsx +37 -32
- package/src/components/NumberInput/index.css +31 -15
- package/src/components/NumberInput/index.tsx +22 -14
- package/src/components/Piano/context.tsx +1 -1
- package/src/components/Piano/index.css +17 -8
- package/src/components/Piano/index.tsx +259 -220
- package/src/components/Piano/key.tsx +3 -3
- package/src/components/Slider/Thumb.tsx +1 -1
- package/src/components/Slider/Track.tsx +3 -3
- package/src/components/Slider/index.css +33 -8
- package/src/components/Slider/index.tsx +25 -25
- package/src/components/XYPad/Area.tsx +4 -3
- package/src/components/XYPad/Thumb.tsx +8 -4
- package/src/components/XYPad/index.css +18 -4
- package/src/components/XYPad/index.tsx +25 -19
- package/src/hooks/useAnimationFrame.ts +3 -0
- package/src/hooks/useCallbackRef.ts +2 -2
- package/src/hooks/useDrag.ts +2 -1
- package/src/hooks/useDragWithElement.ts +2 -1
- package/src/hooks/useEventListener.ts +3 -0
- package/src/hooks/useInterval.ts +3 -0
- package/src/hooks/useLongPress.ts +3 -0
- package/src/hooks/useMIDIAccess.ts +40 -0
- package/src/hooks/useMIDIInput.ts +50 -0
- package/src/hooks/useMIDIMessage.ts +24 -0
- package/src/hooks/useRefCallbackEvent.ts +4 -0
- package/src/index.ts +30 -35
- package/src/styles/global.css +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tremolo-ui/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "React component library for audio app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"react-dom": "^18 || ^19"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@tremolo-ui/functions": "^0.1.
|
|
49
|
+
"@tremolo-ui/functions": "^0.1.6",
|
|
50
50
|
"clsx": "^2.1.1",
|
|
51
51
|
"zustand": "^5.0.3"
|
|
52
52
|
},
|
|
@@ -4,45 +4,70 @@
|
|
|
4
4
|
overflow: visible;
|
|
5
5
|
outline: 0;
|
|
6
6
|
|
|
7
|
-
&:focus,
|
|
8
|
-
&:hover {
|
|
9
|
-
> .tremolo-knob-active-line {
|
|
10
|
-
color: #4e76e6;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
> .tremolo-knob-inactive-line {
|
|
14
|
-
color: #ddd;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
> .tremolo-knob-thumb {
|
|
18
|
-
color: #ccc;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
7
|
&[aria-readonly='true'] {
|
|
23
8
|
cursor: not-allowed;
|
|
24
9
|
}
|
|
25
|
-
|
|
26
|
-
&[aria-disabled='true'] {
|
|
27
|
-
> .tremolo-knob-active-line {
|
|
28
|
-
color: #5d6478;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
10
|
}
|
|
32
11
|
|
|
33
12
|
.tremolo-knob-active-line {
|
|
34
13
|
overflow: visible;
|
|
35
|
-
color:
|
|
14
|
+
color: oklch(69.2% 0.17548 266.373);
|
|
15
|
+
|
|
16
|
+
:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
|
|
17
|
+
color: oklch(59.5% 0.17548 266.373);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:where(.tremolo-knob[aria-disabled='true']) & {
|
|
21
|
+
color: oklch(50.5% 0.03307 270.021);
|
|
22
|
+
}
|
|
36
23
|
}
|
|
37
24
|
|
|
38
25
|
.tremolo-knob-inactive-line {
|
|
39
|
-
color:
|
|
26
|
+
color: oklch(95% 0 0);
|
|
27
|
+
|
|
28
|
+
:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
|
|
29
|
+
color: oklch(90% 0 0);
|
|
30
|
+
}
|
|
40
31
|
}
|
|
41
32
|
|
|
42
33
|
.tremolo-knob-thumb {
|
|
43
|
-
color:
|
|
34
|
+
color: oklch(85.7% 0 0);
|
|
35
|
+
|
|
36
|
+
:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
|
|
37
|
+
color: oklch(84.5% 0 0);
|
|
38
|
+
}
|
|
44
39
|
}
|
|
45
40
|
|
|
46
41
|
.tremolo-knob-thumb-line {
|
|
47
|
-
color:
|
|
42
|
+
color: oklch(94.2% 0 0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:where(.dark, [data-theme='dark']) {
|
|
46
|
+
.tremolo-knob-active-line {
|
|
47
|
+
color: oklch(59.5% 0.17548 266.373);
|
|
48
|
+
|
|
49
|
+
:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
|
|
50
|
+
color: oklch(65.2% 0.17548 266.373);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.tremolo-knob-inactive-line {
|
|
55
|
+
color: oklch(41.7% 0 0);
|
|
56
|
+
|
|
57
|
+
:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
|
|
58
|
+
color: oklch(44.59% 0 0);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.tremolo-knob-thumb {
|
|
63
|
+
color: oklch(48.6% 0 0);
|
|
64
|
+
|
|
65
|
+
:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
|
|
66
|
+
color: oklch(51.7% 0 0);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.tremolo-knob-thumb-line {
|
|
71
|
+
color: oklch(84.2% 0 0);
|
|
72
|
+
}
|
|
48
73
|
}
|
|
@@ -43,8 +43,8 @@ export interface KnobProps {
|
|
|
43
43
|
*/
|
|
44
44
|
startValue?: number
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
size?: number
|
|
46
|
+
/** width and height */
|
|
47
|
+
size?: number | string
|
|
48
48
|
|
|
49
49
|
/** Whether to apply `{use-select: none}` when dragging */
|
|
50
50
|
bodyNoSelect?: boolean
|
|
@@ -69,15 +69,16 @@ export interface KnobProps {
|
|
|
69
69
|
thumb?: string
|
|
70
70
|
/** color */
|
|
71
71
|
thumbLine?: string
|
|
72
|
-
|
|
73
72
|
/** percent (0-100) */
|
|
74
73
|
thumbSize?: number
|
|
75
74
|
/** percent (0-100) */
|
|
76
75
|
thumbLineWeight?: number
|
|
77
76
|
/** percent (0-100) */
|
|
78
77
|
thumbLineLength?: number
|
|
79
|
-
/**
|
|
78
|
+
/** line weight [px] */
|
|
80
79
|
lineWeight?: number
|
|
80
|
+
/** angle range [degree] */
|
|
81
|
+
angleRange?: number
|
|
81
82
|
|
|
82
83
|
classes?: {
|
|
83
84
|
activeLine?: string
|
|
@@ -125,6 +126,11 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
125
126
|
inactiveLine,
|
|
126
127
|
thumb,
|
|
127
128
|
thumbLine,
|
|
129
|
+
thumbSize = 84,
|
|
130
|
+
thumbLineWeight = 6,
|
|
131
|
+
thumbLineLength = 35,
|
|
132
|
+
lineWeight = 6,
|
|
133
|
+
angleRange = 270,
|
|
128
134
|
onChange,
|
|
129
135
|
onKeyDown,
|
|
130
136
|
onPointerDown,
|
|
@@ -133,26 +139,18 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
133
139
|
classes,
|
|
134
140
|
...props
|
|
135
141
|
}: Props,
|
|
136
|
-
|
|
142
|
+
forwardedRef,
|
|
137
143
|
) => {
|
|
138
144
|
const valueRef = useRef(0)
|
|
139
145
|
const elmRef = useRef<HTMLOrSVGElement>(null)
|
|
140
146
|
|
|
141
|
-
// --- interpret props ---
|
|
142
|
-
const padding = 8 // %
|
|
143
|
-
const thumbLineWeight = 6 // %
|
|
144
|
-
const thumbLineLength = 35 // %
|
|
145
|
-
const lineWeight = size * 0.06 // px
|
|
146
|
-
const p = normalizeValue(value, min, max, skew)
|
|
147
|
-
const s = normalizeValue(startValue, min, max, skew)
|
|
148
|
-
|
|
149
147
|
// --- internal functions ---
|
|
150
148
|
const onDrag = useCallback(
|
|
151
149
|
(_x: number, y: number) => {
|
|
152
150
|
if (!onChange || readonly) return
|
|
153
151
|
const v = rawValue(valueRef.current - y / 100, min, max, skew)
|
|
154
|
-
const
|
|
155
|
-
onChange(
|
|
152
|
+
const clamped = clamp(stepValue(v, step), min, max)
|
|
153
|
+
onChange(clamped)
|
|
156
154
|
},
|
|
157
155
|
[max, min, onChange, readonly, skew, step],
|
|
158
156
|
)
|
|
@@ -210,7 +208,7 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
210
208
|
[wheel, onChange, readonly, updateValueByEvent],
|
|
211
209
|
)
|
|
212
210
|
|
|
213
|
-
useImperativeHandle(
|
|
211
|
+
useImperativeHandle(forwardedRef, () => {
|
|
214
212
|
return {
|
|
215
213
|
focus() {
|
|
216
214
|
elmRef.current?.focus()
|
|
@@ -221,11 +219,17 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
221
219
|
}
|
|
222
220
|
}, [])
|
|
223
221
|
|
|
224
|
-
const
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
const
|
|
228
|
-
const
|
|
222
|
+
const viewBoxSize = 100
|
|
223
|
+
const center = viewBoxSize / 2
|
|
224
|
+
const padding = (viewBoxSize - clamp(thumbSize, 0, 100)) / 2 // %
|
|
225
|
+
const p = normalizeValue(value, min, max, skew)
|
|
226
|
+
const s = normalizeValue(startValue, min, max, skew)
|
|
227
|
+
|
|
228
|
+
// 時計回りで描画していく
|
|
229
|
+
const r1 = -angleRange / 2 // ロータリー開始位置
|
|
230
|
+
const r2 = r1 + Math.min(p, s) * angleRange // activeLineの開始位置
|
|
231
|
+
const r3 = r1 + Math.max(p, s) * angleRange // activeLineの終了位置
|
|
232
|
+
const r4 = angleRange / 2 // ロータリー終了位置
|
|
229
233
|
const x1 = center + center * Math.cos(radian(r1 - 90))
|
|
230
234
|
const y1 = center + center * Math.sin(radian(r1 - 90))
|
|
231
235
|
const x2 = center + center * Math.cos(radian(r2 - 90))
|
|
@@ -237,12 +241,13 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
237
241
|
|
|
238
242
|
return (
|
|
239
243
|
<svg
|
|
240
|
-
className={clsx('tremolo-knob', className)}
|
|
241
244
|
ref={(div) => {
|
|
242
245
|
elmRef.current = div
|
|
243
246
|
wheelRefCallback(div)
|
|
244
247
|
touchMoveRefCallback(div)
|
|
245
248
|
}}
|
|
249
|
+
className={clsx('tremolo-knob', className)}
|
|
250
|
+
viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
|
|
246
251
|
width={size}
|
|
247
252
|
height={size}
|
|
248
253
|
tabIndex={0}
|
|
@@ -268,7 +273,7 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
268
273
|
}}
|
|
269
274
|
{...props}
|
|
270
275
|
>
|
|
271
|
-
{/*
|
|
276
|
+
{/* lines */}
|
|
272
277
|
{startValue > min && (
|
|
273
278
|
<path
|
|
274
279
|
className={clsx(
|
|
@@ -281,13 +286,6 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
281
286
|
strokeWidth={lineWeight}
|
|
282
287
|
/>
|
|
283
288
|
)}
|
|
284
|
-
<path
|
|
285
|
-
className={clsx('tremolo-knob-active-line', classes?.activeLine)}
|
|
286
|
-
d={`M ${x2} ${y2} A ${center} ${center} -135 ${r3 - r2 > 180 ? 1 : 0} 1 ${x3}, ${y3}`}
|
|
287
|
-
fill="none"
|
|
288
|
-
stroke={activeLine || 'currentColor'}
|
|
289
|
-
strokeWidth={lineWeight}
|
|
290
|
-
/>
|
|
291
289
|
{startValue < max && (
|
|
292
290
|
<path
|
|
293
291
|
className={clsx(
|
|
@@ -300,12 +298,19 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
300
298
|
strokeWidth={lineWeight}
|
|
301
299
|
/>
|
|
302
300
|
)}
|
|
301
|
+
<path
|
|
302
|
+
className={clsx('tremolo-knob-active-line', classes?.activeLine)}
|
|
303
|
+
d={`M ${x2} ${y2} A ${center} ${center} -135 ${r3 - r2 > 180 ? 1 : 0} 1 ${x3}, ${y3}`}
|
|
304
|
+
fill="none"
|
|
305
|
+
stroke={activeLine || 'currentColor'}
|
|
306
|
+
strokeWidth={lineWeight}
|
|
307
|
+
/>
|
|
303
308
|
{/* thumb */}
|
|
304
309
|
<svg className={clsx('tremolo-knob-thumb', classes?.thumb)}>
|
|
305
310
|
<circle
|
|
306
311
|
cx="50%"
|
|
307
312
|
cy="50%"
|
|
308
|
-
r={`${
|
|
313
|
+
r={`${thumbSize / 2}%`}
|
|
309
314
|
fill={thumb || 'currentColor'}
|
|
310
315
|
/>
|
|
311
316
|
<line
|
|
@@ -320,7 +325,7 @@ export const Knob = forwardRef<KnobMethods, Props>(
|
|
|
320
325
|
// https://bugs.webkit.org/show_bug.cgi?id=201854
|
|
321
326
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/transform-origin#browser_compatibility
|
|
322
327
|
style={{
|
|
323
|
-
transform: `rotate(${
|
|
328
|
+
transform: `rotate(${r1 + p * angleRange}deg)`,
|
|
324
329
|
transformOrigin: '50% 50%',
|
|
325
330
|
}}
|
|
326
331
|
/>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
.tremolo-number-input-wrapper {
|
|
2
2
|
--border-radius: 4px;
|
|
3
3
|
--stepper-width: 20px;
|
|
4
|
-
--active-color:
|
|
4
|
+
--active-color: oklch(59.5% 0.17548 266.373);
|
|
5
|
+
--border-color: oklch(81% 0 0);
|
|
5
6
|
|
|
6
7
|
display: inline-flex;
|
|
7
8
|
flex-direction: row;
|
|
@@ -9,13 +10,13 @@
|
|
|
9
10
|
width: 140px;
|
|
10
11
|
height: min-content;
|
|
11
12
|
border-style: solid;
|
|
12
|
-
border-color:
|
|
13
|
+
border-color: var(--border-color);
|
|
13
14
|
border-width: 0px;
|
|
14
15
|
outline: none;
|
|
15
16
|
transition: all 0.1s;
|
|
16
17
|
|
|
17
18
|
&:not(:focus-within):has(> .tremolo-number-input[data-error='true']) {
|
|
18
|
-
border-color:
|
|
19
|
+
border-color: oklch(64.245% 0.21266 25.499);
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
&[data-variant='outline'] {
|
|
@@ -23,29 +24,30 @@
|
|
|
23
24
|
border-radius: var(--border-radius);
|
|
24
25
|
|
|
25
26
|
&:hover {
|
|
26
|
-
border-color:
|
|
27
|
+
--border-color: oklch(65.335% 0 0);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
&:focus-within {
|
|
30
|
-
border-color: var(--active-color);
|
|
31
|
+
--border-color: var(--active-color);
|
|
31
32
|
box-shadow: 0px 0px 0px 2px
|
|
32
33
|
color-mix(in srgb, var(--active-color) 10%, transparent);
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
&[data-variant='filled'] {
|
|
38
|
+
--bg: oklch(95.88% 0 0);
|
|
37
39
|
border-width: 1px;
|
|
38
40
|
border-radius: var(--border-radius);
|
|
39
41
|
border-color: transparent;
|
|
40
|
-
background-color:
|
|
42
|
+
background-color: var(--bg);
|
|
41
43
|
|
|
42
44
|
&:hover {
|
|
43
|
-
|
|
45
|
+
--bg: oklch(93.166% 0 0);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
&:focus-within {
|
|
47
49
|
background-color: inherit;
|
|
48
|
-
border-color: var(--active-color);
|
|
50
|
+
--border-color: var(--active-color);
|
|
49
51
|
box-shadow: 0px 0px 0px 2px
|
|
50
52
|
color-mix(in srgb, var(--active-color) 10%, transparent);
|
|
51
53
|
}
|
|
@@ -55,11 +57,11 @@
|
|
|
55
57
|
border-bottom-width: 1px;
|
|
56
58
|
|
|
57
59
|
&:hover {
|
|
58
|
-
border-color:
|
|
60
|
+
--border-color: oklch(65.335% 0 0);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
&:focus-within {
|
|
62
|
-
border-color: var(--active-color);
|
|
64
|
+
--border-color: var(--active-color);
|
|
63
65
|
box-shadow: 0px 2px 0px 0px
|
|
64
66
|
color-mix(in srgb, var(--active-color) 10%, transparent);
|
|
65
67
|
}
|
|
@@ -116,7 +118,7 @@
|
|
|
116
118
|
.tremolo-number-input-increment-stepper {
|
|
117
119
|
border-inline-start-width: 1px;
|
|
118
120
|
border-inline-start-style: solid;
|
|
119
|
-
border-inline-start-color:
|
|
121
|
+
border-inline-start-color: oklch(84.522% 0 0);
|
|
120
122
|
font-size: calc(0.75rem);
|
|
121
123
|
display: flex;
|
|
122
124
|
justify-content: center;
|
|
@@ -128,7 +130,7 @@
|
|
|
128
130
|
border-top-right-radius: var(--border-radius);
|
|
129
131
|
|
|
130
132
|
&[aria-disabled='false']:active {
|
|
131
|
-
background-color:
|
|
133
|
+
background-color: oklch(37.798% 0.03812 254.612 / 0.055);
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
&[aria-disabled='true'] {
|
|
@@ -143,8 +145,8 @@
|
|
|
143
145
|
.tremolo-number-input-decrement-stepper {
|
|
144
146
|
border-inline-start-width: 1px;
|
|
145
147
|
border-inline-start-style: solid;
|
|
146
|
-
border-inline-start-color:
|
|
147
|
-
border-top: 1px solid
|
|
148
|
+
border-inline-start-color: oklch(84.522% 0 0);
|
|
149
|
+
border-top: 1px solid oklch(84.522% 0 0);
|
|
148
150
|
font-size: calc(0.75rem);
|
|
149
151
|
display: flex;
|
|
150
152
|
justify-content: center;
|
|
@@ -156,7 +158,7 @@
|
|
|
156
158
|
border-bottom-right-radius: var(--border-radius);
|
|
157
159
|
|
|
158
160
|
&[aria-disabled='false']:active {
|
|
159
|
-
background-color:
|
|
161
|
+
background-color: oklch(37.798% 0.03812 254.612 / 0.055);
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
&[aria-disabled='true'] {
|
|
@@ -167,3 +169,17 @@
|
|
|
167
169
|
cursor: not-allowed;
|
|
168
170
|
}
|
|
169
171
|
}
|
|
172
|
+
|
|
173
|
+
:where(.dark, [data-theme='dark']) {
|
|
174
|
+
.tremolo-number-input-wrapper {
|
|
175
|
+
--border-color: oklch(52% 0 0);
|
|
176
|
+
|
|
177
|
+
&[data-variant='filled'] {
|
|
178
|
+
--bg: oklch(43.5% 0 0);
|
|
179
|
+
|
|
180
|
+
&:hover {
|
|
181
|
+
--bg: oklch(46.6% 0 0);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -4,7 +4,10 @@ import { ComponentPropsWithoutRef, forwardRef, ReactNode } from 'react'
|
|
|
4
4
|
import { InputEventOption } from '@tremolo-ui/functions'
|
|
5
5
|
|
|
6
6
|
import { NumberInputProvider } from './context'
|
|
7
|
+
import { DecrementStepper } from './DecrementStepper'
|
|
8
|
+
import { IncrementStepper } from './IncrementStepper'
|
|
7
9
|
import { InternalInput } from './InternalInput'
|
|
10
|
+
import { Stepper } from './Stepper'
|
|
8
11
|
import { Units } from './type'
|
|
9
12
|
|
|
10
13
|
/*
|
|
@@ -18,11 +21,11 @@ export interface NumberInputProps {
|
|
|
18
21
|
value: number | string
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
|
-
*
|
|
24
|
+
* Number.MIN_SAFE_INTEGER
|
|
22
25
|
*/
|
|
23
26
|
min?: number
|
|
24
27
|
/**
|
|
25
|
-
*
|
|
28
|
+
* Number.MAX_SAFE_INTEGER
|
|
26
29
|
*/
|
|
27
30
|
max?: number
|
|
28
31
|
step?: number
|
|
@@ -55,7 +58,6 @@ export interface NumberInputProps {
|
|
|
55
58
|
keepWithinRange?: boolean
|
|
56
59
|
clampValueOnBlur?: boolean
|
|
57
60
|
|
|
58
|
-
// TODO
|
|
59
61
|
/**
|
|
60
62
|
* wheel control option
|
|
61
63
|
*/
|
|
@@ -95,11 +97,7 @@ export interface NumberInputMethods {
|
|
|
95
97
|
type Props = NumberInputProps &
|
|
96
98
|
Omit<ComponentPropsWithoutRef<'input'>, keyof NumberInputProps | 'type'>
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
* Input with some useful functions for entering numerical values.
|
|
100
|
-
* @category NumberInput
|
|
101
|
-
*/
|
|
102
|
-
export const NumberInput = forwardRef<NumberInputMethods, Props>(
|
|
100
|
+
const NumberInputImpl = forwardRef<NumberInputMethods, Props>(
|
|
103
101
|
(
|
|
104
102
|
{
|
|
105
103
|
value,
|
|
@@ -126,9 +124,9 @@ export const NumberInput = forwardRef<NumberInputMethods, Props>(
|
|
|
126
124
|
children,
|
|
127
125
|
...props
|
|
128
126
|
}: Props,
|
|
129
|
-
|
|
127
|
+
forwardedRef,
|
|
130
128
|
) => {
|
|
131
|
-
const colors:
|
|
129
|
+
const colors: Record<string, string | undefined> = {
|
|
132
130
|
'--active-color': activeColor,
|
|
133
131
|
}
|
|
134
132
|
return (
|
|
@@ -154,7 +152,7 @@ export const NumberInput = forwardRef<NumberInputMethods, Props>(
|
|
|
154
152
|
data-variant={variant}
|
|
155
153
|
>
|
|
156
154
|
<InternalInput
|
|
157
|
-
ref={
|
|
155
|
+
ref={forwardedRef}
|
|
158
156
|
readonly={readonly}
|
|
159
157
|
disabled={disabled}
|
|
160
158
|
selectWithFocus={selectWithFocus}
|
|
@@ -175,7 +173,17 @@ export const NumberInput = forwardRef<NumberInputMethods, Props>(
|
|
|
175
173
|
},
|
|
176
174
|
)
|
|
177
175
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Input with some useful functions for entering numerical values.
|
|
178
|
+
* @category NumberInput
|
|
179
|
+
*/
|
|
180
|
+
export const NumberInput = Object.assign(NumberInputImpl, {
|
|
181
|
+
Stepper,
|
|
182
|
+
IncrementStepper,
|
|
183
|
+
DecrementStepper,
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
export { type StepperProps } from './Stepper'
|
|
187
|
+
export { type IncrementStepperProps } from './IncrementStepper'
|
|
188
|
+
export { type DecrementStepperProps } from './DecrementStepper'
|
|
181
189
|
export { type Units } from './type'
|
|
@@ -12,7 +12,7 @@ type State = {
|
|
|
12
12
|
glissando: boolean
|
|
13
13
|
midiMax: number
|
|
14
14
|
fill: boolean
|
|
15
|
-
onPlayNote: (noteNumber: number) => void
|
|
15
|
+
onPlayNote: (noteNumber: number, velocity?: number) => void
|
|
16
16
|
onStopNote: (noteNumber: number) => void
|
|
17
17
|
label: (note: number, index: number) => ReactNode
|
|
18
18
|
}
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.tremolo-piano-white-key {
|
|
10
|
-
--bg:
|
|
11
|
-
--color:
|
|
12
|
-
--active-bg:
|
|
13
|
-
--active-color:
|
|
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
14
|
|
|
15
15
|
box-sizing: border-box;
|
|
16
16
|
position: absolute;
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.tremolo-piano-black-key {
|
|
36
|
-
--color:
|
|
37
|
-
--bg:
|
|
38
|
-
--active-color:
|
|
39
|
-
--active-bg:
|
|
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
40
|
|
|
41
41
|
box-sizing: border-box;
|
|
42
42
|
position: absolute;
|
|
@@ -79,3 +79,12 @@
|
|
|
79
79
|
aspect-ratio: 1;
|
|
80
80
|
max-width: calc(100% - 16px);
|
|
81
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
|
+
}
|