@tremolo-ui/react 0.0.10 → 0.0.12

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 (137) hide show
  1. package/dist/cjs/index.js +435 -203
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/AnimationCanvas/index.d.ts +2 -2
  4. package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +1 -1
  5. package/dist/cjs/types/components/AnimationKnob/index.d.ts +10 -3
  6. package/dist/cjs/types/components/AnimationKnob/index.d.ts.map +1 -1
  7. package/dist/cjs/types/components/Knob/index.d.ts +13 -3
  8. package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
  9. package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts +2 -0
  10. package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts.map +1 -1
  11. package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts +2 -0
  12. package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts.map +1 -1
  13. package/dist/cjs/types/components/NumberInput/InternalInput.d.ts +18 -0
  14. package/dist/cjs/types/components/NumberInput/InternalInput.d.ts.map +1 -0
  15. package/dist/cjs/types/components/NumberInput/Stepper.d.ts +2 -0
  16. package/dist/cjs/types/components/NumberInput/Stepper.d.ts.map +1 -1
  17. package/dist/cjs/types/components/NumberInput/context.d.ts +3 -2
  18. package/dist/cjs/types/components/NumberInput/context.d.ts.map +1 -1
  19. package/dist/cjs/types/components/NumberInput/index.d.ts +12 -3
  20. package/dist/cjs/types/components/NumberInput/index.d.ts.map +1 -1
  21. package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +1 -1
  22. package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +1 -1
  23. package/dist/cjs/types/components/Piano/index.d.ts +7 -4
  24. package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
  25. package/dist/cjs/types/components/Piano/key.d.ts +4 -0
  26. package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
  27. package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +2 -2
  28. package/dist/cjs/types/components/Slider/Scale.d.ts +1 -3
  29. package/dist/cjs/types/components/Slider/Scale.d.ts.map +1 -1
  30. package/dist/cjs/types/components/Slider/Thumb.d.ts +1 -0
  31. package/dist/cjs/types/components/Slider/Thumb.d.ts.map +1 -1
  32. package/dist/cjs/types/components/Slider/Track.d.ts +2 -4
  33. package/dist/cjs/types/components/Slider/Track.d.ts.map +1 -1
  34. package/dist/cjs/types/components/Slider/context.d.ts +2 -10
  35. package/dist/cjs/types/components/Slider/context.d.ts.map +1 -1
  36. package/dist/cjs/types/components/Slider/index.d.ts +5 -1
  37. package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
  38. package/dist/cjs/types/components/WheelObserver/index.d.ts +3 -3
  39. package/dist/cjs/types/components/WheelObserver/index.d.ts.map +1 -1
  40. package/dist/cjs/types/components/XYPad/Area.d.ts +3 -3
  41. package/dist/cjs/types/components/XYPad/Area.d.ts.map +1 -1
  42. package/dist/cjs/types/components/XYPad/Thumb.d.ts +1 -0
  43. package/dist/cjs/types/components/XYPad/Thumb.d.ts.map +1 -1
  44. package/dist/cjs/types/components/XYPad/index.d.ts +6 -1
  45. package/dist/cjs/types/components/XYPad/index.d.ts.map +1 -1
  46. package/dist/cjs/types/hooks/useAnimationFrame.d.ts.map +1 -1
  47. package/dist/cjs/types/hooks/useInterval.d.ts +2 -0
  48. package/dist/cjs/types/hooks/useInterval.d.ts.map +1 -0
  49. package/dist/cjs/types/hooks/useLongPress.d.ts +2 -0
  50. package/dist/cjs/types/hooks/useLongPress.d.ts.map +1 -0
  51. package/dist/cjs/types/index.d.ts +5 -0
  52. package/dist/cjs/types/index.d.ts.map +1 -1
  53. package/dist/esm/index.js +431 -204
  54. package/dist/esm/index.js.map +1 -1
  55. package/dist/esm/types/components/AnimationCanvas/index.d.ts +2 -2
  56. package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +1 -1
  57. package/dist/esm/types/components/AnimationKnob/index.d.ts +10 -3
  58. package/dist/esm/types/components/AnimationKnob/index.d.ts.map +1 -1
  59. package/dist/esm/types/components/Knob/index.d.ts +13 -3
  60. package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
  61. package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts +2 -0
  62. package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts.map +1 -1
  63. package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts +2 -0
  64. package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts.map +1 -1
  65. package/dist/esm/types/components/NumberInput/InternalInput.d.ts +18 -0
  66. package/dist/esm/types/components/NumberInput/InternalInput.d.ts.map +1 -0
  67. package/dist/esm/types/components/NumberInput/Stepper.d.ts +2 -0
  68. package/dist/esm/types/components/NumberInput/Stepper.d.ts.map +1 -1
  69. package/dist/esm/types/components/NumberInput/context.d.ts +3 -2
  70. package/dist/esm/types/components/NumberInput/context.d.ts.map +1 -1
  71. package/dist/esm/types/components/NumberInput/index.d.ts +12 -3
  72. package/dist/esm/types/components/NumberInput/index.d.ts.map +1 -1
  73. package/dist/esm/types/components/Piano/BlackKey.d.ts.map +1 -1
  74. package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +1 -1
  75. package/dist/esm/types/components/Piano/index.d.ts +7 -4
  76. package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
  77. package/dist/esm/types/components/Piano/key.d.ts +4 -0
  78. package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
  79. package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +2 -2
  80. package/dist/esm/types/components/Slider/Scale.d.ts +1 -3
  81. package/dist/esm/types/components/Slider/Scale.d.ts.map +1 -1
  82. package/dist/esm/types/components/Slider/Thumb.d.ts +1 -0
  83. package/dist/esm/types/components/Slider/Thumb.d.ts.map +1 -1
  84. package/dist/esm/types/components/Slider/Track.d.ts +2 -4
  85. package/dist/esm/types/components/Slider/Track.d.ts.map +1 -1
  86. package/dist/esm/types/components/Slider/context.d.ts +2 -10
  87. package/dist/esm/types/components/Slider/context.d.ts.map +1 -1
  88. package/dist/esm/types/components/Slider/index.d.ts +5 -1
  89. package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
  90. package/dist/esm/types/components/WheelObserver/index.d.ts +3 -3
  91. package/dist/esm/types/components/WheelObserver/index.d.ts.map +1 -1
  92. package/dist/esm/types/components/XYPad/Area.d.ts +3 -3
  93. package/dist/esm/types/components/XYPad/Area.d.ts.map +1 -1
  94. package/dist/esm/types/components/XYPad/Thumb.d.ts +1 -0
  95. package/dist/esm/types/components/XYPad/Thumb.d.ts.map +1 -1
  96. package/dist/esm/types/components/XYPad/index.d.ts +6 -1
  97. package/dist/esm/types/components/XYPad/index.d.ts.map +1 -1
  98. package/dist/esm/types/hooks/useAnimationFrame.d.ts.map +1 -1
  99. package/dist/esm/types/hooks/useInterval.d.ts +2 -0
  100. package/dist/esm/types/hooks/useInterval.d.ts.map +1 -0
  101. package/dist/esm/types/hooks/useLongPress.d.ts +2 -0
  102. package/dist/esm/types/hooks/useLongPress.d.ts.map +1 -0
  103. package/dist/esm/types/index.d.ts +5 -0
  104. package/dist/esm/types/index.d.ts.map +1 -1
  105. package/dist/styles/index.css +115 -33
  106. package/package.json +41 -40
  107. package/src/components/AnimationCanvas/index.tsx +15 -7
  108. package/src/components/AnimationKnob/index.tsx +216 -187
  109. package/src/components/Knob/index.tsx +230 -171
  110. package/src/components/NumberInput/DecrementStepper.tsx +9 -2
  111. package/src/components/NumberInput/IncrementStepper.tsx +9 -2
  112. package/src/components/NumberInput/InternalInput.tsx +219 -0
  113. package/src/components/NumberInput/Stepper.tsx +2 -0
  114. package/src/components/NumberInput/context.tsx +21 -9
  115. package/src/components/NumberInput/index.css +76 -22
  116. package/src/components/NumberInput/index.tsx +94 -162
  117. package/src/components/Piano/BlackKey.tsx +14 -0
  118. package/src/components/Piano/WhiteKey.tsx +14 -0
  119. package/src/components/Piano/index.css +22 -6
  120. package/src/components/Piano/index.tsx +20 -22
  121. package/src/components/Piano/key.ts +5 -0
  122. package/src/components/Piano/keyboardShortcuts.ts +2 -2
  123. package/src/components/Slider/Scale.tsx +1 -4
  124. package/src/components/Slider/Thumb.tsx +6 -0
  125. package/src/components/Slider/Track.tsx +5 -4
  126. package/src/components/Slider/context.tsx +5 -20
  127. package/src/components/Slider/index.css +5 -2
  128. package/src/components/Slider/index.tsx +52 -26
  129. package/src/components/WheelObserver/index.tsx +4 -2
  130. package/src/components/XYPad/Area.tsx +7 -6
  131. package/src/components/XYPad/Thumb.tsx +6 -0
  132. package/src/components/XYPad/index.css +12 -2
  133. package/src/components/XYPad/index.tsx +57 -41
  134. package/src/hooks/useInterval.ts +27 -0
  135. package/src/hooks/useLongPress.ts +31 -0
  136. package/src/index.ts +6 -0
  137. package/src/styles/index.css +0 -1
@@ -0,0 +1,219 @@
1
+ import clsx from 'clsx'
2
+ import {
3
+ ComponentPropsWithoutRef,
4
+ forwardRef,
5
+ useCallback,
6
+ useImperativeHandle,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ } from 'react'
11
+
12
+ import {
13
+ clamp,
14
+ InputEventOption,
15
+ normalizeValue,
16
+ rawValue,
17
+ stepValue,
18
+ } from '@tremolo-ui/functions'
19
+ import { parseValue } from '@tremolo-ui/functions/NumberInput'
20
+
21
+ import { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'
22
+
23
+ import { safeClamp, useNumberInputContext } from './context'
24
+
25
+ import { NumberInputMethods } from '.'
26
+
27
+ interface InternalProps {
28
+ disabled: boolean
29
+ readonly: boolean
30
+ wheel: InputEventOption | null
31
+ keyboard: InputEventOption | null
32
+
33
+ selectWithFocus?: 'all' | 'number' | 'none'
34
+ blurOnEnter?: boolean
35
+ keepWithinRange?: boolean
36
+ clampValueOnBlur?: boolean
37
+
38
+ onChange?: (value: number, text: string) => void
39
+ onFocus?: (
40
+ value: number,
41
+ text: string,
42
+ event: React.FocusEvent<HTMLInputElement, Element>,
43
+ ) => void
44
+ onBlur?: (
45
+ value: number,
46
+ text: string,
47
+ event: React.FocusEvent<HTMLInputElement, Element>,
48
+ ) => void
49
+ }
50
+
51
+ type InternalPropsWithAttributes = InternalProps &
52
+ Omit<ComponentPropsWithoutRef<'input'>, keyof InternalProps>
53
+
54
+ export const InternalInput = forwardRef<
55
+ NumberInputMethods,
56
+ InternalPropsWithAttributes
57
+ >(
58
+ (
59
+ {
60
+ disabled,
61
+ readonly,
62
+ selectWithFocus,
63
+ blurOnEnter,
64
+ clampValueOnBlur,
65
+ wheel,
66
+ keyboard,
67
+ className,
68
+ onChange,
69
+ onFocus,
70
+ onBlur,
71
+ onKeyDown,
72
+ children: _children,
73
+ ...props
74
+ }: InternalPropsWithAttributes,
75
+ ref,
76
+ ) => {
77
+ const elmRef = useRef<HTMLInputElement>(null)
78
+ const [editing, setEditing] = useState(false)
79
+ const value = useNumberInputContext((s) => s.value)
80
+ const valueAsNumber = useNumberInputContext((s) => s.valueAsNumber)
81
+ const min = useNumberInputContext((s) => s.min)
82
+ const max = useNumberInputContext((s) => s.max)
83
+ const step = useNumberInputContext((s) => s.step)
84
+ const units = useNumberInputContext((s) => s.units)
85
+ const digit = useNumberInputContext((s) => s.digit)
86
+ const change = useNumberInputContext((s) => s.change)
87
+
88
+ const error = useMemo(() => {
89
+ if (editing) return false
90
+ const v = valueAsNumber
91
+ return (min ?? -Infinity) > v || v > (max ?? Infinity)
92
+ }, [editing, max, min, valueAsNumber])
93
+
94
+ const updateValueByEvent = useCallback(
95
+ (eventType: InputEventOption[0], x: number) => {
96
+ let newValue
97
+ if (eventType == 'normalized') {
98
+ if (!min || !max) {
99
+ throw new Error('required parameter: min, max') // TODO
100
+ }
101
+ const n = normalizeValue(valueAsNumber, min, max)
102
+ newValue = rawValue(n + x, min, max)
103
+ return clamp(stepValue(newValue, step), min, max)
104
+ } else {
105
+ newValue = valueAsNumber + x
106
+ return stepValue(newValue, step)
107
+ }
108
+ },
109
+ [max, min, step, valueAsNumber],
110
+ )
111
+
112
+ const handleKeyDown = useCallback(
113
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
114
+ if (!keyboard || !onChange || readonly) return
115
+ const key = event.key
116
+ if (!['ArrowUp', 'ArrowDown'].includes(key)) return
117
+ event.preventDefault()
118
+ const x = key == 'ArrowUp' ? keyboard[1] : -keyboard[1]
119
+ const parsed = parseValue(String(updateValueByEvent(keyboard[0], x)))
120
+ console.log('key control')
121
+ onChange?.(parsed.rawValue, parsed.formatValue)
122
+ },
123
+ [keyboard, readonly, onChange, updateValueByEvent],
124
+ )
125
+
126
+ const wheelRefCallback = useRefCallbackEvent(
127
+ 'wheel',
128
+ (event) => {
129
+ if (!wheel || readonly) return
130
+ event.preventDefault()
131
+ if (!onChange || event.deltaY == 0) return
132
+ const x = Math.sign(event.deltaY) * -wheel[1]
133
+ const parsed = parseValue(String(updateValueByEvent(wheel[0], x)))
134
+ console.log('wheel control')
135
+ onChange?.(parsed.rawValue, parsed.formatValue)
136
+ },
137
+ { passive: false },
138
+ [wheel, readonly, onChange, updateValueByEvent],
139
+ )
140
+
141
+ useImperativeHandle(ref, () => {
142
+ return {
143
+ focus() {
144
+ elmRef.current?.focus()
145
+ },
146
+ blur() {
147
+ elmRef.current?.blur()
148
+ },
149
+ }
150
+ }, [])
151
+
152
+ return (
153
+ <input
154
+ ref={(input) => {
155
+ elmRef.current = input
156
+ wheelRefCallback(input)
157
+ }}
158
+ className={clsx('tremolo-number-input', className)}
159
+ value={value}
160
+ min={min}
161
+ max={max}
162
+ step={step}
163
+ type="text"
164
+ aria-disabled={disabled}
165
+ aria-readonly={readonly}
166
+ tabIndex={-1}
167
+ data-error={error}
168
+ onChange={(event) => {
169
+ if (readonly) return
170
+ const v = event.currentTarget.value
171
+ const cursorPos = event.target.selectionStart
172
+ change(v)
173
+ const valueAsNumber = parseValue(v, units, digit).rawValue
174
+ onChange?.(valueAsNumber, v)
175
+ if (cursorPos) {
176
+ event.target.selectionStart = cursorPos
177
+ event.target.selectionEnd = cursorPos
178
+ }
179
+ }}
180
+ onFocus={(event) => {
181
+ setEditing(true)
182
+ const v = event.currentTarget.value
183
+ const parsed = parseValue(v, units, digit)
184
+ if (selectWithFocus == 'all') {
185
+ event.currentTarget.setSelectionRange(0, v.length)
186
+ } else if (selectWithFocus == 'number') {
187
+ event.currentTarget.setSelectionRange(
188
+ 0,
189
+ parsed.formatValue.length - parsed.unit.length,
190
+ )
191
+ }
192
+ onFocus?.(parsed.rawValue, parsed.formatValue, event)
193
+ }}
194
+ onBlur={(event) => {
195
+ setEditing(false)
196
+ // update value
197
+ let v = parseValue(event.currentTarget.value, units, digit).rawValue
198
+ if (clampValueOnBlur) {
199
+ v = safeClamp(v, min, max)
200
+ }
201
+ const parsed = parseValue(String(v), units, digit)
202
+ change(parsed.formatValue)
203
+ if (clampValueOnBlur) {
204
+ onChange?.(parsed.rawValue, parsed.formatValue)
205
+ }
206
+ onBlur?.(parsed.rawValue, parsed.formatValue, event)
207
+ }}
208
+ onKeyDown={(event) => {
209
+ if (blurOnEnter && event.key == 'Enter') {
210
+ event.currentTarget.blur()
211
+ }
212
+ handleKeyDown(event)
213
+ onKeyDown?.(event)
214
+ }}
215
+ {...props}
216
+ />
217
+ )
218
+ },
219
+ )
@@ -1,12 +1,14 @@
1
1
  import clsx from 'clsx'
2
2
  import { ComponentPropsWithoutRef, ReactNode } from 'react'
3
3
 
4
+ /** @category NumberInput */
4
5
  export interface StepperProps {
5
6
  /** Display only when hovering. */
6
7
  dynamic?: boolean
7
8
  children?: ReactNode
8
9
  }
9
10
 
11
+ /** @category NumberInput */
10
12
  export function Stepper({
11
13
  dynamic = true,
12
14
  children,
@@ -7,12 +7,14 @@ import { parseValue, Units } from '@tremolo-ui/functions/NumberInput'
7
7
  type State = {
8
8
  value: string
9
9
  valueAsNumber: number
10
+ step: number
11
+
10
12
  min?: number
11
13
  max?: number
12
- step?: number
13
- keepWithinRange?: boolean
14
14
  units?: string | Units
15
15
  digit?: number
16
+ readonly?: boolean
17
+ keepWithinRange?: boolean
16
18
  onChange?: (value: number, text: string) => void
17
19
  }
18
20
 
@@ -41,6 +43,7 @@ const createNumberInputStore = (initProps?: ProviderProps) => {
41
43
  min: 0,
42
44
  max: 0,
43
45
  step: 1,
46
+ readonly: false,
44
47
  keepWithinRange: true,
45
48
  onChange: (_v: number, _t: string) => {},
46
49
  }
@@ -62,9 +65,13 @@ const createNumberInputStore = (initProps?: ProviderProps) => {
62
65
  },
63
66
  increment: () =>
64
67
  set((state) => {
65
- let next =
66
- parseValue(state.value, state.units, state.digit).rawValue +
67
- (state.step ?? 1)
68
+ if (state.readonly) return {}
69
+ const current = parseValue(
70
+ state.value,
71
+ state.units,
72
+ state.digit,
73
+ ).rawValue
74
+ let next = current + (state.step ?? 1)
68
75
  if (state.keepWithinRange) {
69
76
  next = safeClamp(next, state.min, state.max)
70
77
  }
@@ -77,9 +84,13 @@ const createNumberInputStore = (initProps?: ProviderProps) => {
77
84
  }),
78
85
  decrement: () =>
79
86
  set((state) => {
80
- let next =
81
- parseValue(state.value, state.units, state.digit).rawValue -
82
- (state.step ?? 1)
87
+ if (state.readonly) return {}
88
+ const current = parseValue(
89
+ state.value,
90
+ state.units,
91
+ state.digit,
92
+ ).rawValue
93
+ let next = current - (state.step ?? 1)
83
94
  if (state.keepWithinRange) {
84
95
  next = safeClamp(next, state.min, state.max)
85
96
  }
@@ -92,6 +103,7 @@ const createNumberInputStore = (initProps?: ProviderProps) => {
92
103
  }),
93
104
  change: (value) =>
94
105
  set((state) => {
106
+ if (state.readonly) return {}
95
107
  const v = value ?? ''
96
108
  return {
97
109
  value: v,
@@ -109,7 +121,7 @@ export function NumberInputProvider({
109
121
  children,
110
122
  ...props
111
123
  }: NumberInputProviderProps) {
112
- const storeRef = useRef<NumberInputStore>()
124
+ const storeRef = useRef<NumberInputStore>(null)
113
125
  if (!storeRef.current) {
114
126
  storeRef.current = createNumberInputStore(props)
115
127
  }
@@ -1,40 +1,78 @@
1
1
  .tremolo-number-input-wrapper {
2
- --tremolo-number-input-border-radius: 4px;
3
- --tremolo-number-input-stepper-width: 20px;
2
+ --border-radius: 4px;
3
+ --stepper-width: 20px;
4
+ --active-color: var(--tremolo-theme-color);
4
5
 
5
6
  display: inline-flex;
6
7
  flex-direction: row;
7
8
  position: relative;
8
-
9
- border-style: solid;
10
- border-width: 1px;
11
- border-color: #bbb;
12
- border-radius: var(--tremolo-number-input-border-radius);
13
-
14
9
  width: 140px;
15
10
  height: min-content;
16
-
17
- &:hover {
18
- border-color: var(--tremolo-theme-color);
19
- }
11
+ border-style: solid;
12
+ border-color: #c1c1c1;
13
+ border-width: 0px;
14
+ outline: none;
15
+ transition: all 0.1s;
20
16
 
21
17
  &:not(:focus-within):has(> .tremolo-number-input[data-error='true']) {
22
18
  border-color: #f34343;
23
19
  }
24
20
 
25
- &:focus-within {
26
- border-color: var(--tremolo-theme-color);
27
- box-shadow: 0px 0px 0px 2px rgba(var(--tremolo-theme-color-rgb), 0.1);
21
+ &[data-variant='outline'] {
22
+ border-width: 1px;
23
+ border-radius: var(--border-radius);
24
+
25
+ &:hover {
26
+ border-color: #909090;
27
+ }
28
+
29
+ &:focus-within {
30
+ border-color: var(--active-color);
31
+ box-shadow: 0px 0px 0px 2px
32
+ color-mix(in srgb, var(--active-color) 10%, transparent);
33
+ }
34
+ }
35
+
36
+ &[data-variant='filled'] {
37
+ border-width: 1px;
38
+ border-radius: var(--border-radius);
39
+ border-color: transparent;
40
+ background-color: #edf2f7;
41
+
42
+ &:hover {
43
+ background-color: #e4e9ee;
44
+ }
45
+
46
+ &:focus-within {
47
+ background-color: inherit;
48
+ border-color: var(--active-color);
49
+ box-shadow: 0px 0px 0px 2px
50
+ color-mix(in srgb, var(--active-color) 10%, transparent);
51
+ }
52
+ }
53
+
54
+ &[data-variant='flushed'] {
55
+ border-bottom-width: 1px;
56
+
57
+ &:hover {
58
+ border-color: #909090;
59
+ }
60
+
61
+ &:focus-within {
62
+ border-color: var(--active-color);
63
+ box-shadow: 0px 2px 0px 0px
64
+ color-mix(in srgb, var(--active-color) 10%, transparent);
65
+ }
28
66
  }
29
67
 
30
68
  &[data-stepper='false'] {
31
- --tremolo-number-input-stepper-width: 0px;
69
+ --stepper-width: 0px;
32
70
  }
33
71
  }
34
72
 
35
73
  .tremolo-number-input {
36
74
  display: block;
37
- width: calc(100% - 20px - var(--tremolo-number-input-stepper-width));
75
+ width: calc(100% - 20px - var(--stepper-width));
38
76
  background-color: inherit;
39
77
  font: inherit;
40
78
  padding: 6px 10px;
@@ -42,7 +80,11 @@
42
80
  margin: 0;
43
81
  border: none;
44
82
  outline: none;
45
- appearance: textfield;
83
+ appearance: none;
84
+
85
+ &[aria-readonly='true'] {
86
+ cursor: not-allowed;
87
+ }
46
88
  }
47
89
 
48
90
  .tremolo-number-input-stepper {
@@ -52,7 +94,7 @@
52
94
  position: absolute;
53
95
  top: 0;
54
96
  right: 0;
55
- width: var(--tremolo-number-input-stepper-width);
97
+ width: var(--stepper-width);
56
98
  transition: all 0.1s linear;
57
99
 
58
100
  &[data-dynamic='true'] {
@@ -61,7 +103,11 @@
61
103
  }
62
104
  }
63
105
 
64
- .tremolo-number-input-wrapper:hover .tremolo-number-input-stepper {
106
+ :is(
107
+ .tremolo-number-input-wrapper:hover,
108
+ .tremolo-number-input-wrapper:focus-within
109
+ )
110
+ .tremolo-number-input-stepper {
65
111
  opacity: 1;
66
112
  transform: translateX(0);
67
113
  }
@@ -78,7 +124,7 @@
78
124
  max-height: 50%;
79
125
  user-select: none;
80
126
  cursor: pointer;
81
- border-top-right-radius: var(--tremolo-number-input-border-radius);
127
+ border-top-right-radius: var(--border-radius);
82
128
 
83
129
  &[aria-disabled='false']:active {
84
130
  background-color: #3443560e;
@@ -87,6 +133,10 @@
87
133
  &[aria-disabled='true'] {
88
134
  cursor: not-allowed;
89
135
  }
136
+
137
+ &[aria-readonly='true'] {
138
+ cursor: not-allowed;
139
+ }
90
140
  }
91
141
 
92
142
  .tremolo-number-input-decrement-stepper {
@@ -102,7 +152,7 @@
102
152
  max-height: 50%;
103
153
  user-select: none;
104
154
  cursor: pointer;
105
- border-bottom-right-radius: var(--tremolo-number-input-border-radius);
155
+ border-bottom-right-radius: var(--border-radius);
106
156
 
107
157
  &[aria-disabled='false']:active {
108
158
  background-color: #3443560e;
@@ -111,4 +161,8 @@
111
161
  &[aria-disabled='true'] {
112
162
  cursor: not-allowed;
113
163
  }
164
+
165
+ &[aria-readonly='true'] {
166
+ cursor: not-allowed;
167
+ }
114
168
  }