zds-pickers 4.1.0 → 4.1.3

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 (68) hide show
  1. package/dist/index.cjs.js +9 -9
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.es.js +56 -57
  4. package/dist/index.es.js.map +1 -1
  5. package/dist/other/SoundFontProvider.js +5 -4
  6. package/dist/pickers/KeyPicker.js +1 -2
  7. package/dist/types/other/SoundFontProvider.d.ts +1 -1
  8. package/dist/types/pickers/KeyPicker.d.ts +1 -4
  9. package/lib/soundfonts/acoustic_grand_piano-mp3.js +107 -0
  10. package/package.json +5 -1
  11. package/.editorconfig +0 -19
  12. package/.github/workflows/codeql-analysis.yml +0 -67
  13. package/.nvmrc +0 -1
  14. package/.prettierignore +0 -0
  15. package/.prettierrc +0 -13
  16. package/.storybook/main.ts +0 -42
  17. package/.storybook/manager.ts +0 -12
  18. package/.storybook/preview.tsx +0 -26
  19. package/.vscode/extensions.json +0 -32
  20. package/.vscode/javascript.code-snippets +0 -229
  21. package/.vscode/settings.json +0 -358
  22. package/biome.jsonc +0 -158
  23. package/lib/@types/nebiru-react-rotary-knob.d.ts +0 -20
  24. package/lib/@types/react-svgmt.d.ts +0 -74
  25. package/lib/@types/zds-mappings.d.ts +0 -55
  26. package/lib/@types/zds-react-piano.d.ts +0 -17
  27. package/lib/hooks/useComponentSize.ts +0 -52
  28. package/lib/hooks/useStateWithDynamicDefault.ts +0 -13
  29. package/lib/index.ts +0 -52
  30. package/lib/midi/ccValues.ts +0 -139
  31. package/lib/midi/export.ts +0 -88
  32. package/lib/other/DefaultTooltip.ts +0 -14
  33. package/lib/other/OctavePlayer.tsx +0 -139
  34. package/lib/other/SoundFontProvider.tsx +0 -213
  35. package/lib/other/SvgText.tsx +0 -221
  36. package/lib/pickers/CCPicker.tsx +0 -28
  37. package/lib/pickers/ChannelMappingPicker.tsx +0 -150
  38. package/lib/pickers/ChannelPicker.tsx +0 -84
  39. package/lib/pickers/KeyPicker.tsx +0 -56
  40. package/lib/pickers/Knob.tsx +0 -93
  41. package/lib/pickers/KnobPicker.tsx +0 -93
  42. package/lib/pickers/LatchPicker.tsx +0 -33
  43. package/lib/pickers/MappingPicker.tsx +0 -68
  44. package/lib/pickers/NotePicker.tsx +0 -95
  45. package/lib/pickers/PianoPicker.tsx +0 -81
  46. package/lib/pickers/PolarityPicker.tsx +0 -39
  47. package/lib/pickers/ResponseCurve.tsx +0 -251
  48. package/lib/pickers/ResponseCurvePicker.tsx +0 -75
  49. package/lib/pickers/Select.tsx +0 -268
  50. package/lib/pickers/StatusPicker.tsx +0 -30
  51. package/lib/pickers/ValuePicker.tsx +0 -67
  52. package/lib/pickers/knobSkin10.tsx +0 -112
  53. package/lib/rotaryKnob/InternalInput.tsx +0 -43
  54. package/lib/rotaryKnob/Types.ts +0 -6
  55. package/lib/rotaryKnob/helpers/DrawCircle.tsx +0 -41
  56. package/lib/rotaryKnob/helpers/DrawLine.tsx +0 -32
  57. package/lib/rotaryKnob/helpers/HelpersOverlay.tsx +0 -43
  58. package/lib/rotaryKnob/helpers/KnobVisualHelpers.tsx +0 -138
  59. package/lib/rotaryKnob/index.tsx +0 -417
  60. package/lib/rotaryKnob/knobdefaultskin.ts +0 -69
  61. package/lib/rotaryKnob/utils.ts +0 -112
  62. package/lib/utils.ts +0 -41
  63. package/stories/assets/sampleStyles.css +0 -365
  64. package/stories/assets/utils.js +0 -7
  65. package/stories/picker.stories.tsx +0 -432
  66. package/tsconfig.json +0 -35
  67. package/vite.config.ts +0 -41
  68. /package/{lib/temp → dist/soundfonts}/acoustic_grand_piano-mp3.js +0 -0
@@ -1,251 +0,0 @@
1
- import { useRef } from 'react'
2
- import useComponentSize from '../hooks/useComponentSize'
3
- import {
4
- type Curve,
5
- responseCurves as origResponseCurves,
6
- } from '../midi/export'
7
- import { DefaultTooltip, type TooltipProps } from '../other/DefaultTooltip'
8
- import { SvgText } from '../other/SvgText'
9
-
10
- type ResponseCurveType = {
11
- value: Curve
12
- label: React.ReactNode
13
- c1: number
14
- c2: number
15
- x1: number
16
- y1: number
17
- x2: number
18
- y2: number
19
- labelX: number
20
- labelY: number
21
- }
22
-
23
- // const width = 218
24
- // const height = 150
25
- const axisOffset = 20
26
- const buttonSize = 15
27
-
28
- const axisX1 = axisOffset
29
- const axisY1 = axisOffset
30
-
31
- type ResponseCurveProps = {
32
- autosize: boolean
33
- disabled?: boolean
34
- inverted: boolean
35
- onChange: (event: { target: { value: Curve } }) => void
36
- Tooltip: React.FC<TooltipProps>
37
- value: Curve
38
- }
39
-
40
- const ResponseCurve = (props: ResponseCurveProps) => {
41
- const {
42
- Tooltip = DefaultTooltip,
43
- autosize,
44
- disabled,
45
- inverted,
46
- onChange,
47
- value: responseCurve,
48
- } = props
49
-
50
- const ref = useRef(null)
51
- const svgRef = useRef(null)
52
- const { height: ourHeight, width: ourWidth } = useComponentSize(ref)
53
-
54
- const width = autosize ? ourWidth || 218 : 218
55
- const height = autosize ? ourHeight || 150 : 150
56
-
57
- const axisX2 = width - axisOffset
58
- const axisY2 = height - axisOffset
59
-
60
- const xMid = width / 2
61
- const yMid = height / 2
62
-
63
- const svgProps = { ref: svgRef }
64
-
65
- const responseCurves = origResponseCurves.map(
66
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
67
- ({ value, label }): ResponseCurveType => {
68
- let c1 = 0
69
- let c2 = 0
70
- let x1 = axisX1
71
- let y1 = inverted ? axisY1 : axisY2
72
- let x2 = axisX2
73
- let y2 = inverted ? axisY2 : axisY1
74
- let labelX = xMid
75
- let labelY = yMid
76
- switch (value) {
77
- case 0:
78
- c1 = xMid
79
- c2 = yMid
80
- labelY += 3
81
-
82
- break
83
- case 1:
84
- c1 = inverted ? xMid + width * 0.13 : xMid - width * 0.13
85
- c2 = yMid - height * 0.13
86
- labelX = inverted ? xMid + width * 0.1 : xMid - width * 0.1
87
- labelY = yMid - height * 0.09
88
- break
89
-
90
- case 2:
91
- c1 = inverted ? xMid + width * 0.25 : xMid - width * 0.25
92
- c2 = yMid - height * 0.25
93
- labelX = inverted ? xMid + width * 0.2 : xMid - width * 0.2
94
- labelY = yMid - height * 0.17
95
- break
96
-
97
- case 3:
98
- c1 = inverted ? xMid + width * 0.35 : xMid - width * 0.35
99
- c2 = yMid - height * 0.35
100
- labelX = inverted ? xMid + width * 0.28 : xMid - width * 0.28
101
- labelY = yMid - height * 0.25
102
- break
103
-
104
- case 4:
105
- c1 = inverted ? xMid - width * 0.13 : xMid + width * 0.13
106
- c2 = yMid + height * 0.13
107
- labelX = inverted ? xMid - width * 0.1 : xMid + width * 0.1
108
- labelY = yMid + height * 0.1
109
- break
110
-
111
- case 5:
112
- c1 = inverted ? xMid - width * 0.25 : xMid + width * 0.25
113
- c2 = yMid + height * 0.25
114
- labelX = inverted ? xMid - width * 0.2 : xMid + width * 0.2
115
- labelY = yMid + height * 0.18
116
- break
117
-
118
- case 6:
119
- c1 = inverted ? xMid - width * 0.35 : xMid + width * 0.35
120
- c2 = yMid + height * 0.35
121
- labelX = inverted ? xMid - width * 0.28 : xMid + width * 0.28
122
- labelY = yMid + height * 0.25
123
- break
124
-
125
- case 7:
126
- x1 = inverted ? axisX1 : axisX2
127
- y1 = axisY1
128
- x2 = x1
129
- y2 = axisY2
130
- c1 = x1
131
- c2 = yMid
132
- labelX = x1 - 5
133
- labelY = height - 30
134
- break
135
-
136
- default:
137
- break
138
- }
139
- return {
140
- value,
141
- label,
142
- c1,
143
- c2,
144
- x1,
145
- y1,
146
- x2,
147
- y2,
148
- labelX,
149
- labelY,
150
- }
151
- },
152
- )
153
-
154
- return (
155
- <div
156
- className="response-curve-picker"
157
- ref={ref}>
158
- <svg {...svgProps}>
159
- <rect
160
- className="container"
161
- height={height}
162
- rx={3}
163
- ry={3}
164
- width={width}
165
- x={0}
166
- y={0}
167
- />
168
-
169
- <SvgText
170
- className="axis"
171
- textAnchor="middle"
172
- transform={`translate(${axisX1 - 14} ${height / 2}) rotate(90)`}
173
- x={0}
174
- y={0}
175
- text="Applied force"
176
- />
177
-
178
- <SvgText
179
- className="axis"
180
- textAnchor="middle"
181
- transform={`translate(${width / 2} ${axisY2 + 13})`}
182
- x={0}
183
- y={0}
184
- text="Output (velocity)"
185
- />
186
-
187
- <line
188
- className="axis"
189
- x1={axisX1}
190
- x2={axisX1}
191
- y1={axisY1}
192
- y2={axisY2}
193
- />
194
- <line
195
- className="axis"
196
- x1={axisX1}
197
- x2={axisX2}
198
- y1={axisY2}
199
- y2={axisY2}
200
- />
201
-
202
- {responseCurves.map(
203
- ({ value, label, x1, y1, x2, y2, c1, c2, labelX, labelY }) => (
204
- <g key={value}>
205
- <path
206
- className={value === responseCurve ? 'curve-selected' : 'curve'}
207
- d={`M${x1} ${y1} C ${c1} ${c2}, ${c1} ${c2}, ${x2} ${y2}`}
208
- />
209
-
210
- <Tooltip
211
- placement="left"
212
- title={label}>
213
- <rect
214
- className={
215
- value === responseCurve ? 'button-selected' : 'button'
216
- }
217
- height={buttonSize}
218
- onClick={
219
- disabled
220
- ? f => f
221
- : () =>
222
- onChange({
223
- target: {
224
- value: Number.parseInt(String(value)) as Curve,
225
- },
226
- })
227
- }
228
- transform={`translate(${labelX + 3} ${labelY - buttonSize / 1.05}) rotate(45)`}
229
- width={buttonSize}
230
- />
231
- </Tooltip>
232
-
233
- <text
234
- className={
235
- value === responseCurve ? 'button-selected' : 'button'
236
- }
237
- transform={`translate(${labelX} ${labelY})`}>
238
- {value}
239
- <title>{label}</title>
240
- </text>
241
- </g>
242
- ),
243
- )}
244
- </svg>
245
- </div>
246
- )
247
- }
248
-
249
- export { ResponseCurve }
250
-
251
- export type { ResponseCurveType, ResponseCurveProps }
@@ -1,75 +0,0 @@
1
- import { forwardRef, useCallback } from 'react'
2
- import type { GroupBase, SelectInstance } from 'react-select'
3
- import { type Curve, responseCurves } from '../midi/export'
4
- import { DefaultTooltip, type TooltipProps } from '../other/DefaultTooltip'
5
- import { findObj } from '../utils'
6
- import { ResponseCurve } from './ResponseCurve'
7
- import { Select } from './Select'
8
- import type { Option, SelectProps } from './Select'
9
-
10
- type ResponseCurvePickerProps = SelectProps<Curve> & {
11
- inverted?: boolean
12
- Tooltip?: React.FC<TooltipProps>
13
- }
14
-
15
- type ResponseCurvePickerRef = SelectInstance<
16
- Option<Curve>,
17
- false,
18
- GroupBase<Option<Curve>>
19
- >
20
-
21
- const ResponseCurvePicker = forwardRef<
22
- SelectInstance<Option<Curve>, false, GroupBase<Option<Curve>>>,
23
- ResponseCurvePickerProps
24
- >((props, ref) => {
25
- const {
26
- Tooltip = DefaultTooltip,
27
- inverted = false,
28
- onChange,
29
- value,
30
- ...rest
31
- } = props
32
-
33
- const Placeholder = useCallback(() => {
34
- const option = findObj('value', value)(responseCurves) as Option<Curve>
35
- return option ? (
36
- <div className="singleValue">{option.label}</div>
37
- ) : (
38
- <div className="zds-pickers__placeholder">Select...</div>
39
- )
40
- }, [value])
41
-
42
- const MenuList = useCallback(
43
- ({ setValue }: { setValue: (v: Curve) => void }) => (
44
- <ResponseCurve
45
- autosize
46
- inverted={inverted}
47
- onChange={({ target: { value: v } }) => {
48
- setValue(v)
49
- onChange(v)
50
- }}
51
- Tooltip={Tooltip}
52
- value={Number.parseInt(String(value)) as Curve}
53
- />
54
- ),
55
- [Tooltip, inverted, onChange, value],
56
- )
57
-
58
- return (
59
- <Select
60
- {...rest}
61
- components={{
62
- Placeholder,
63
- MenuList,
64
- }}
65
- isSearchable={false}
66
- onChange={f => f}
67
- ref={ref}
68
- value={value}
69
- />
70
- )
71
- })
72
-
73
- export { ResponseCurvePicker }
74
-
75
- export type { ResponseCurvePickerProps, ResponseCurvePickerRef }
@@ -1,268 +0,0 @@
1
- import {
2
- Children,
3
- type JSX,
4
- forwardRef,
5
- isValidElement,
6
- useCallback,
7
- useMemo,
8
- } from 'react'
9
- import ReactSelect, {
10
- type GroupBase,
11
- type IndicatorsContainerProps,
12
- components as originalComponents,
13
- type PlaceholderProps,
14
- type SelectComponentsConfig,
15
- type SelectInstance,
16
- type SingleValue,
17
- type StylesConfig,
18
- type ValueContainerProps,
19
- } from 'react-select'
20
- import { omit } from '../utils'
21
-
22
- const noSelection = 255
23
-
24
- const { IndicatorsContainer, Placeholder, ValueContainer } = originalComponents
25
-
26
- type PassedSelectProps = {
27
- actionButton?: React.ReactNode
28
- inputValue?: string
29
- placeholder?: React.ReactNode
30
- }
31
-
32
- type Option<T> = {
33
- label: React.ReactNode
34
- value: T
35
- }
36
-
37
- const noSelectionOption: Option<number> = {
38
- label: '--',
39
- value: noSelection,
40
- }
41
-
42
- interface CustomIndicatorsContainerProps<T>
43
- extends Omit<IndicatorsContainerProps<Option<T>, false>, 'selectProps'> {
44
- children: React.ReactNode
45
- selectProps: IndicatorsContainerProps<Option<T>, false>['selectProps'] &
46
- PassedSelectProps
47
- }
48
-
49
- const CustomIndicatorsContainer = <T,>(
50
- props: CustomIndicatorsContainerProps<T>,
51
- ) => {
52
- const { children, ...rest } = props
53
- const actionButton = rest.selectProps?.actionButton
54
-
55
- return (
56
- <IndicatorsContainer {...rest}>
57
- <div
58
- onMouseDown={e => {
59
- e.stopPropagation()
60
- e.preventDefault()
61
- }}
62
- style={{ display: 'flex' }}>
63
- {actionButton}
64
- {children}
65
- </div>
66
- </IndicatorsContainer>
67
- )
68
- }
69
-
70
- type CustomValueContainerProps<T> = (
71
- | ValueContainerProps<Option<T>, false>
72
- | PlaceholderProps<Option<T>, false>
73
- ) & {
74
- children: React.ReactNode
75
- hasValue?: boolean
76
- isFocused?: boolean
77
- }
78
-
79
- const CustomValueContainer = <T,>({
80
- children,
81
- ...props
82
- }: CustomValueContainerProps<T>) => (
83
- <ValueContainer {...props}>
84
- <Placeholder
85
- {...props}
86
- innerProps={props.innerProps || {}}
87
- className={props.hasValue || props.selectProps.inputValue ? 'shrunk' : ''}
88
- isFocused={props.isFocused ?? false}>
89
- {props.selectProps.placeholder}
90
- </Placeholder>
91
- {Children.map(children, child =>
92
- isValidElement(child) && child.type !== Placeholder ? child : null,
93
- )}
94
- </ValueContainer>
95
- )
96
-
97
- type SelectProps<T> = SelectComponentsConfig<
98
- Option<T>,
99
- false,
100
- GroupBase<Option<T>>
101
- > & {
102
- actionButton?: React.ReactNode
103
- className?: string
104
- components?: object
105
- disabled?: boolean
106
- filterOptions?: (candidate: Option<T>, inputValue: string) => boolean
107
- formatOptionLabel?: (
108
- option: Option<unknown>,
109
- { context }: { context: 'menu' | 'value' },
110
- ) => React.ReactNode
111
- isSearchable?: boolean
112
- label?: string
113
- menuPortalTarget?: HTMLElement | null
114
- menuPosition?: 'fixed' | 'absolute'
115
- menuShouldScrollIntoView?: boolean
116
- onChange: (value: Option<T>['value']) => void
117
- options: Option<T>[] | { options: Option<T>[] }[]
118
- preserveMenuWidth?: boolean
119
- selectProps?: PassedSelectProps
120
- shrinkLabel?: boolean
121
- value?: Option<T>['value']
122
- }
123
-
124
- const Select = forwardRef(
125
- <T,>(
126
- props: SelectProps<T>,
127
- ref: React.ForwardedRef<
128
- SelectInstance<Option<T>, false, GroupBase<Option<T>>>
129
- >,
130
- ) => {
131
- const {
132
- components,
133
- disabled,
134
- label,
135
- onChange,
136
- options = [],
137
- preserveMenuWidth,
138
- shrinkLabel,
139
- value,
140
- ...rest
141
- } = props
142
-
143
- const handleChange = useCallback(
144
- (option: SingleValue<Option<unknown>>) => {
145
- if (option) {
146
- onChange((option as Option<T>).value)
147
- }
148
- },
149
- [onChange],
150
- )
151
-
152
- const flatOptionsList = options.reduce<Option<T>[]>((acc, entry) => {
153
- if ('options' in entry) {
154
- return acc.concat(entry.options)
155
- }
156
- return acc.concat(entry)
157
- }, [])
158
-
159
- const selectedOption =
160
- flatOptionsList.find(option => value === option.value) || undefined
161
-
162
- const styles: unknown = useMemo(() => {
163
- const base = preserveMenuWidth
164
- ? {
165
- menu: (base: Record<string, unknown>) => omit('width')(base),
166
- menuList: (base: object) => ({
167
- ...base,
168
- overflowX: 'hidden',
169
- }),
170
- option: (base: object) => ({
171
- ...base,
172
- whiteSpace: 'nowrap',
173
- paddingRight: 10,
174
- }),
175
- }
176
- : {}
177
-
178
- return shrinkLabel
179
- ? {
180
- ...base,
181
- container: (provided: object /* , state */) => ({
182
- ...provided,
183
- marginTop: 10,
184
- }),
185
- placeholder: (
186
- _provided: object,
187
- state: PlaceholderProps<Option<T>, false>,
188
- ) => ({
189
- position: 'absolute',
190
- left: state.hasValue || state.selectProps.inputValue ? -2 : '4%',
191
- top: state.hasValue || state.selectProps.inputValue ? -12 : '50%',
192
- transition: 'top 0.1s, font-size 0.1s, color 0.1s',
193
- fontSize: (state.hasValue || state.selectProps.inputValue) && 13,
194
- }),
195
- valueContainer: (provided: object /* , state */) => ({
196
- ...provided,
197
- overflow: 'visible',
198
- }),
199
- }
200
- : {
201
- ...base,
202
- }
203
- }, [preserveMenuWidth, shrinkLabel])
204
-
205
- return shrinkLabel ? (
206
- <div className="zds-pickers__container">
207
- <ReactSelect
208
- {...rest}
209
- classNamePrefix="zds-pickers"
210
- components={{
211
- IndicatorsContainer: CustomIndicatorsContainer,
212
- ValueContainer: CustomValueContainer,
213
- ...components,
214
- }}
215
- isDisabled={disabled}
216
- onChange={handleChange}
217
- options={flatOptionsList}
218
- placeholder={label}
219
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
220
- ref={ref as React.Ref<any>}
221
- styles={
222
- styles as StylesConfig<
223
- Option<unknown>,
224
- false,
225
- GroupBase<Option<unknown>>
226
- >
227
- }
228
- value={selectedOption}
229
- />
230
- </div>
231
- ) : (
232
- <div className="zds-pickers__container">
233
- {Boolean(label) && <span className="zds-pickers__label">{label}</span>}
234
- <ReactSelect
235
- {...rest}
236
- classNamePrefix="zds-pickers"
237
- components={{
238
- IndicatorsContainer: CustomIndicatorsContainer,
239
- ...components,
240
- }}
241
- isDisabled={disabled}
242
- onChange={handleChange}
243
- options={flatOptionsList}
244
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
245
- ref={ref as React.Ref<any>}
246
- styles={
247
- styles as StylesConfig<
248
- Option<unknown>,
249
- false,
250
- GroupBase<Option<unknown>>
251
- >
252
- }
253
- value={selectedOption}
254
- />
255
- </div>
256
- )
257
- },
258
- ) as <T>(
259
- props: SelectProps<T> & {
260
- ref?: React.ForwardedRef<
261
- SelectInstance<Option<T>, false, GroupBase<Option<T>>>
262
- >
263
- },
264
- ) => JSX.Element
265
-
266
- export { noSelection, noSelectionOption, Select }
267
-
268
- export type { Option, SelectProps }
@@ -1,30 +0,0 @@
1
- import type { Status } from 'lib/midi/export'
2
- import { forwardRef } from 'react'
3
- import type { GroupBase, SelectInstance } from 'react-select'
4
- import { Select } from './Select'
5
- import type { Option, SelectProps } from './Select'
6
-
7
- type StatusPickerProps = Omit<SelectProps<Status>, 'options'> & {
8
- statuses: Option<Status>[]
9
- }
10
-
11
- type StatusPickerRef = SelectInstance<
12
- Option<Status>,
13
- false,
14
- GroupBase<Option<Status>>
15
- >
16
-
17
- const StatusPicker = forwardRef<
18
- SelectInstance<Option<Status>, false, GroupBase<Option<Status>>>,
19
- StatusPickerProps
20
- >(({ statuses, ...rest }, ref) => (
21
- <Select<Status>
22
- {...rest}
23
- options={statuses}
24
- ref={ref}
25
- />
26
- ))
27
-
28
- export { StatusPicker }
29
-
30
- export type { StatusPickerProps, StatusPickerRef }
@@ -1,67 +0,0 @@
1
- import { forwardRef, useCallback, useMemo } from 'react'
2
- import type { GroupBase, SelectInstance } from 'react-select'
3
- import useStateWithDynamicDefault from '../hooks/useStateWithDynamicDefault'
4
- import { arraySequence, assertRange } from '../utils'
5
- import { Select } from './Select'
6
- import type { Option, SelectProps } from './Select'
7
-
8
- type ValuePickerProps = Omit<SelectProps<number>, 'options'> & {
9
- highToLow?: boolean
10
- max?: number
11
- min?: number
12
- }
13
-
14
- type ValuePickerRef = SelectInstance<
15
- Option<number>,
16
- false,
17
- GroupBase<Option<number>>
18
- >
19
-
20
- const ValuePicker = forwardRef<
21
- SelectInstance<Option<number>, false, GroupBase<Option<number>>>,
22
- ValuePickerProps
23
- >((props, ref) => {
24
- const {
25
- disabled,
26
- highToLow,
27
- max = 127,
28
- min = 0,
29
- onChange,
30
- value: initialValue = 0,
31
- ...rest
32
- } = props
33
- const options = useMemo(() => {
34
- const result = arraySequence(max - min + 1)
35
- .map(i => min + i)
36
- .map(value => ({ value, label: value }))
37
- return (highToLow
38
- ? result.reverse()
39
- : result) as unknown as Option<number>[]
40
- }, [highToLow, max, min])
41
-
42
- const [value, setValue] = useStateWithDynamicDefault(initialValue)
43
-
44
- const handleChange = useCallback(
45
- (v: number | string) => {
46
- onChange(assertRange(v, max, min))
47
-
48
- setValue(Number.parseInt(String(v), 10))
49
- },
50
- [max, min, onChange, setValue],
51
- )
52
-
53
- return (
54
- <Select
55
- {...rest}
56
- disabled={disabled}
57
- onChange={handleChange}
58
- options={options}
59
- ref={ref}
60
- value={value}
61
- />
62
- )
63
- })
64
-
65
- export { ValuePicker }
66
-
67
- export type { ValuePickerProps, ValuePickerRef }