@snack-uikit/fields 0.19.0 → 0.19.1
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/CHANGELOG.md +12 -0
- package/README.md +204 -0
- package/dist/components/FieldDate/FieldDate.js +4 -2
- package/dist/components/FieldDecorator/FieldDecorator.d.ts +1 -1
- package/dist/components/FieldDecorator/FieldDecorator.js +4 -3
- package/dist/components/FieldSecure/FieldSecure.js +3 -1
- package/dist/components/FieldSelect/FieldSelectMultiple.js +4 -2
- package/dist/components/FieldSelect/FieldSelectSingle.js +4 -2
- package/dist/components/FieldSlider/FieldSlider.js +63 -19
- package/dist/components/FieldSlider/helpers/getClosestMark.d.ts +2 -2
- package/dist/components/FieldSlider/helpers/getClosestMark.js +3 -3
- package/dist/components/FieldSlider/helpers/index.d.ts +1 -0
- package/dist/components/FieldSlider/helpers/index.js +1 -0
- package/dist/components/FieldSlider/helpers/isMarkObject.d.ts +8 -0
- package/dist/components/FieldSlider/helpers/isMarkObject.js +3 -0
- package/dist/components/FieldStepper/FieldStepper.js +3 -1
- package/dist/components/FieldText/FieldText.js +3 -1
- package/dist/components/FieldTextArea/FieldTextArea.js +3 -1
- package/dist/utils/getValidationState.d.ts +5 -0
- package/dist/utils/getValidationState.js +4 -0
- package/package.json +3 -3
- package/src/components/FieldDate/FieldDate.tsx +4 -2
- package/src/components/FieldDecorator/FieldDecorator.tsx +4 -3
- package/src/components/FieldSecure/FieldSecure.tsx +5 -2
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +5 -2
- package/src/components/FieldSelect/FieldSelectSingle.tsx +5 -2
- package/src/components/FieldSlider/FieldSlider.tsx +93 -19
- package/src/components/FieldSlider/helpers/getClosestMark.ts +7 -3
- package/src/components/FieldSlider/helpers/index.ts +1 -0
- package/src/components/FieldSlider/helpers/isMarkObject.ts +13 -0
- package/src/components/FieldStepper/FieldStepper.tsx +5 -2
- package/src/components/FieldText/FieldText.tsx +4 -2
- package/src/components/FieldTextArea/FieldTextArea.tsx +5 -2
- package/src/utils/getValidationState.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 0.19.1 (2024-04-24)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **FF-0011:** validationState reacts on error prop ([d4a6cb5](https://github.com/cloud-ru-tech/snack-uikit/commit/d4a6cb517662520476f6b690c0a24b37311eb369))
|
|
12
|
+
* **FF-00:** fix input behavior for field-slider non-linear marks ([67fda28](https://github.com/cloud-ru-tech/snack-uikit/commit/67fda2853485bd69039351d71dbe9db5d14e163f))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
6
18
|
# 0.19.0 (2024-04-23)
|
|
7
19
|
|
|
8
20
|
|
package/README.md
CHANGED
|
@@ -167,22 +167,111 @@ const [isOpen, setIsOpen] = useState(false);
|
|
|
167
167
|
### Props
|
|
168
168
|
| name | type | default value | description |
|
|
169
169
|
|------|------|---------------|-------------|
|
|
170
|
+
| children* | `ReactNode` | - | Контент |
|
|
171
|
+
| className | `string` | - | CSS-класс |
|
|
172
|
+
| disabled | `boolean` | - | Деактивирован ли элемент Является ли поле деактивированным |
|
|
173
|
+
| readonly | `boolean` | - | Является ли поле доступным только на чтение Доступно ли поле только на чтение |
|
|
174
|
+
| error | `string` | - | |
|
|
175
|
+
| label | `string` | - | Лейбл |
|
|
176
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
177
|
+
| labelFor | `string` | - | Аттрибут for |
|
|
178
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
179
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
180
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
181
|
+
| length | `{ current: number; max?: number; }` | - | Допустимая длинна текста |
|
|
182
|
+
| hint | `string` | - | Подсказка внизу |
|
|
183
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
|
|
184
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
170
185
|
## FieldText
|
|
171
186
|
### Props
|
|
172
187
|
| name | type | default value | description |
|
|
173
188
|
|------|------|---------------|-------------|
|
|
189
|
+
| showCopyButton | `boolean` | - | Отображение кнопки Копировать для поля (актуально только для `readonly = true`) |
|
|
190
|
+
| showClearButton | `boolean` | true | Отображение кнопки очистки поля |
|
|
191
|
+
| allowMoreThanMaxLength | `boolean` | - | Можно ли вводить больше разрешённого кол-ва символов |
|
|
192
|
+
| prefixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-префикс для поля |
|
|
193
|
+
| value | `string` | - | Значение input |
|
|
194
|
+
| onChange | `(value: string, e?: ChangeEvent<HTMLInputElement>) => void` | - | Колбек смены значения |
|
|
195
|
+
| disabled | `boolean` | - | Является ли поле деактивированным |
|
|
196
|
+
| readonly | `boolean` | - | Является ли поле доступным только для чтения |
|
|
197
|
+
| id | `string` | - | Значение html-атрибута id |
|
|
198
|
+
| name | `string` | - | Значение html-атрибута name |
|
|
199
|
+
| placeholder | `string` | - | Значение плейсхолдера |
|
|
200
|
+
| maxLength | `number` | - | Максимальная длина вводимого значения |
|
|
201
|
+
| onFocus | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки получения фокуса |
|
|
202
|
+
| onBlur | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки потери фокуса |
|
|
203
|
+
| error | `string` | - | |
|
|
204
|
+
| className | `string` | - | CSS-класс |
|
|
205
|
+
| label | `string` | - | Лейбл |
|
|
206
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
207
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
208
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
209
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
210
|
+
| hint | `string` | - | Подсказка внизу |
|
|
211
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
|
|
212
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
174
213
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
175
214
|
| key | `Key` | - | |
|
|
176
215
|
## FieldTextArea
|
|
177
216
|
### Props
|
|
178
217
|
| name | type | default value | description |
|
|
179
218
|
|------|------|---------------|-------------|
|
|
219
|
+
| maxRows | `number` | - | Максимальное кол-во строк, до которого размер поля может быть увеличен |
|
|
220
|
+
| resizable | `boolean` | - | Может ли ли пользователь изменять размеры поля (если св-во не включено, поле автоматически меняет свой размер) |
|
|
221
|
+
| onChange | `(value: string, e?: ChangeEvent<HTMLTextAreaElement>) => void` | - | Колбек смены значения |
|
|
222
|
+
| showCopyButton | `boolean` | - | Отображение кнопки Копировать для поля (актуально только для `readonly = true`) |
|
|
223
|
+
| showClearButton | `boolean` | true | Отображение кнопки очистки поля |
|
|
224
|
+
| allowMoreThanMaxLength | `boolean` | true | Можно ли вводить больше разрешённого кол-ва символов |
|
|
225
|
+
| value | `string` | - | HTML-аттрибут value |
|
|
226
|
+
| disabled | `boolean` | - | Является ли поле деактивированным |
|
|
227
|
+
| readonly | `boolean` | - | Является ли поле доступным только на чтение |
|
|
228
|
+
| id | `string` | - | HTML-аттрибут id |
|
|
229
|
+
| name | `string` | - | HTML-аттрибут name |
|
|
230
|
+
| placeholder | `string` | - | Плейсхолдер |
|
|
231
|
+
| maxLength | `number` | - | Максимальное кол-во символов |
|
|
232
|
+
| onFocus | `FocusEventHandler<HTMLTextAreaElement>` | - | Колбек получения фокуса |
|
|
233
|
+
| onBlur | `FocusEventHandler<HTMLTextAreaElement>` | - | Колбек потери фокуса |
|
|
234
|
+
| error | `string` | - | |
|
|
235
|
+
| className | `string` | - | CSS-класс |
|
|
236
|
+
| label | `string` | - | Лейбл |
|
|
237
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
238
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
239
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
240
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
241
|
+
| hint | `string` | - | Подсказка внизу |
|
|
242
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
|
|
243
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
180
244
|
| ref | `Ref<HTMLTextAreaElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
181
245
|
| key | `Key` | - | |
|
|
182
246
|
## FieldSecure
|
|
183
247
|
### Props
|
|
184
248
|
| name | type | default value | description |
|
|
185
249
|
|------|------|---------------|-------------|
|
|
250
|
+
| hidden | `boolean` | - | Замаскированно ли значение поля |
|
|
251
|
+
| onHiddenChange | `(value: boolean) => void` | - | Колбек смены маскирования |
|
|
252
|
+
| showCopyButton | `boolean` | - | Отображение кнопки копирования |
|
|
253
|
+
| allowMoreThanMaxLength | `boolean` | - | Можно ли вводить больше разрешённого кол-ва символов |
|
|
254
|
+
| prefixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-префикс для поля |
|
|
255
|
+
| value | `string` | - | Значение input |
|
|
256
|
+
| onChange | `(value: string, e?: ChangeEvent<HTMLInputElement>) => void` | - | Колбек смены значения |
|
|
257
|
+
| disabled | `boolean` | - | Является ли поле деактивированным |
|
|
258
|
+
| readonly | `boolean` | - | Является ли поле доступным только для чтения |
|
|
259
|
+
| id | `string` | - | Значение html-атрибута id |
|
|
260
|
+
| name | `string` | - | Значение html-атрибута name |
|
|
261
|
+
| placeholder | `string` | - | Значение плейсхолдера |
|
|
262
|
+
| maxLength | `number` | - | Максимальная длина вводимого значения |
|
|
263
|
+
| onFocus | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки получения фокуса |
|
|
264
|
+
| onBlur | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки потери фокуса |
|
|
265
|
+
| error | `string` | - | |
|
|
266
|
+
| className | `string` | - | CSS-класс |
|
|
267
|
+
| label | `string` | - | Лейбл |
|
|
268
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
269
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
270
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
271
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
272
|
+
| hint | `string` | - | Подсказка внизу |
|
|
273
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
|
|
274
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
186
275
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
187
276
|
| key | `Key` | - | |
|
|
188
277
|
## parseDate
|
|
@@ -193,24 +282,139 @@ const [isOpen, setIsOpen] = useState(false);
|
|
|
193
282
|
### Props
|
|
194
283
|
| name | type | default value | description |
|
|
195
284
|
|------|------|---------------|-------------|
|
|
285
|
+
| value* | `string` | - | Значение input |
|
|
286
|
+
| open | `boolean` | - | Открыт date-picker |
|
|
287
|
+
| onOpenChange | `(value: boolean) => void` | - | Колбек открытия пикера |
|
|
288
|
+
| onChange | `(value: string) => void` | - | Колбек смены значения |
|
|
289
|
+
| showCopyButton | `boolean` | - | Отображение кнопки копирования |
|
|
290
|
+
| showClearButton | `boolean` | true | Отображение кнопки Очистки поля |
|
|
291
|
+
| locale | `Locale` | new Intl.Locale('ru-RU') | Текущая локаль календаря |
|
|
292
|
+
| buildCellProps | `(date: Date, viewMode: ViewMode) => { isDisabled?: boolean; isHoliday?: boolean };` | - | Колбек установки свойств ячеек календаря. Вызывается на построение каждой ячейки. Принимает два параметра: <br> `Date` - дата ячейки <br> `ViewMode`: <br> - `month` отображение месяца, каждая ячейка - 1 день <br> - `year` отображение года, каждая ячейка - 1 месяц <br> - `decade` отображение декады, каждая ячейка - 1 год <br><br> Колбек должен возвращать объект с полями, отвечающими за отключение и подкраску ячейки. |
|
|
293
|
+
| disabled | `boolean` | - | Является ли поле деактивированным |
|
|
294
|
+
| readonly | `boolean` | - | Является ли поле доступным только для чтения |
|
|
295
|
+
| id | `string` | - | Значение html-атрибута id |
|
|
296
|
+
| name | `string` | - | Значение html-атрибута name |
|
|
297
|
+
| onFocus | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки получения фокуса |
|
|
298
|
+
| onBlur | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки потери фокуса |
|
|
299
|
+
| error | `string` | - | |
|
|
300
|
+
| className | `string` | - | CSS-класс |
|
|
301
|
+
| label | `string` | - | Лейбл |
|
|
302
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
303
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
304
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
305
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
306
|
+
| hint | `string` | - | Подсказка внизу |
|
|
307
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
|
|
308
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
196
309
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
197
310
|
| key | `Key` | - | |
|
|
198
311
|
## FieldSelect
|
|
199
312
|
### Props
|
|
200
313
|
| name | type | default value | description |
|
|
201
314
|
|------|------|---------------|-------------|
|
|
315
|
+
| pinBottom* | `OptionProps[]` | - | |
|
|
316
|
+
| pinTop* | `OptionProps[]` | - | |
|
|
317
|
+
| options* | `OptionProps[]` | - | |
|
|
318
|
+
| disabled | `boolean` | false | Является ли поле деактивированным |
|
|
319
|
+
| readonly | `boolean` | false false | Является ли поле доступным только для чтения |
|
|
320
|
+
| id | `string` | - | Значение html-атрибута id |
|
|
321
|
+
| name | `string` | - | Значение html-атрибута name |
|
|
322
|
+
| placeholder | `string` | - | Значение плейсхолдера |
|
|
323
|
+
| onFocus | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки получения фокуса |
|
|
324
|
+
| onBlur | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки потери фокуса |
|
|
325
|
+
| onKeyDown | `KeyboardEventHandler<HTMLInputElement>` | - | Колбек обработки нажатия клавиши клавиатуры |
|
|
326
|
+
| error | `string` | - | |
|
|
327
|
+
| className | `string` | - | CSS-класс |
|
|
328
|
+
| label | `string` | - | Лейбл |
|
|
329
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
330
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
331
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | - | Размер |
|
|
332
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
333
|
+
| hint | `string` | - | Подсказка внизу |
|
|
334
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | - | Состояние валидации |
|
|
335
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
336
|
+
| loading | `boolean` | - | |
|
|
337
|
+
| value | `ItemId \| ItemId[]` | - | Controlled состояние |
|
|
338
|
+
| onChange | `OnChangeHandler<any>` | - | Controlled обработчик измения состояния |
|
|
339
|
+
| defaultValue | `ItemId \| ItemId[]` | - | Начальное состояние |
|
|
340
|
+
| searchable | `boolean` | - | |
|
|
341
|
+
| showCopyButton | `boolean` | - | Отображение кнопки Копировать для поля (актуально только для `readonly = true`) |
|
|
342
|
+
| showClearButton | `boolean` | true | Отображение кнопки очистки поля |
|
|
343
|
+
| prefixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-префикс для поля |
|
|
344
|
+
| footer | `ReactNode` | - | |
|
|
345
|
+
| widthStrategy | enum PopoverWidthStrategy: `"auto"`, `"gte"`, `"eq"` | - | |
|
|
346
|
+
| search | `SearchState` | - | |
|
|
347
|
+
| autocomplete | `boolean` | - | |
|
|
348
|
+
| addOptionByEnter | `boolean` | - | |
|
|
349
|
+
| open | `boolean` | - | |
|
|
350
|
+
| onOpenChange | `(open: boolean) => void` | - | |
|
|
351
|
+
| selectedOptionFormatter | `SelectedOptionFormatter` | - | |
|
|
352
|
+
| dataFiltered | `boolean` | - | |
|
|
353
|
+
| dataError | `boolean` | - | |
|
|
354
|
+
| noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
|
|
355
|
+
| noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
|
|
356
|
+
| errorDataState | `EmptyStateProps` | - | Экран при ошибке запроса |
|
|
357
|
+
| selection | "single" \| "multiple" | - | |
|
|
202
358
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
203
359
|
| key | `Key` | - | |
|
|
360
|
+
| removeByBackspace | `boolean` | - | |
|
|
204
361
|
## FieldStepper
|
|
205
362
|
### Props
|
|
206
363
|
| name | type | default value | description |
|
|
207
364
|
|------|------|---------------|-------------|
|
|
365
|
+
| value | `number` | - | Значение поля |
|
|
366
|
+
| onChange | `(value: number, e?: ChangeEvent<HTMLInputElement>) => void` | - | Колбек смены значения |
|
|
367
|
+
| step | `number` | 1 | Шаг поля |
|
|
368
|
+
| allowMoreThanLimits | `boolean` | true | Можно ли вводить c клавиатуры числа, выходящие за пределы min/max |
|
|
369
|
+
| disabled | `boolean` | - | Является ли поле деактивированным |
|
|
370
|
+
| readonly | `boolean` | - | Является ли поле доступным только для чтения |
|
|
371
|
+
| id | `string` | - | Значение html-атрибута id |
|
|
372
|
+
| name | `string` | - | Значение html-атрибута name |
|
|
373
|
+
| onFocus | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки получения фокуса |
|
|
374
|
+
| onBlur | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки потери фокуса |
|
|
375
|
+
| min | `number` | Number.NEGATIVE_INFINITY | Минимальное значение поля |
|
|
376
|
+
| max | `number` | Number.POSITIVE_INFINITY | Максимальное значение поля |
|
|
377
|
+
| error | `string` | - | |
|
|
378
|
+
| className | `string` | - | CSS-класс |
|
|
379
|
+
| label | `string` | - | Лейбл |
|
|
380
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
381
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
382
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
383
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
384
|
+
| hint | `string` | - | Подсказка внизу |
|
|
385
|
+
| validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
|
|
386
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
208
387
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
209
388
|
| key | `Key` | - | |
|
|
210
389
|
## FieldSlider
|
|
211
390
|
### Props
|
|
212
391
|
| name | type | default value | description |
|
|
213
392
|
|------|------|---------------|-------------|
|
|
393
|
+
| postfixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-постфикс для поля |
|
|
394
|
+
| showScaleBar | `boolean` | true | Отображение линейки |
|
|
395
|
+
| textInputFormatter | `TextInputFormatter` | - | Функция для форматирования значений в текстовом поле |
|
|
396
|
+
| disabled | `boolean` | - | Является ли поле деактивированным |
|
|
397
|
+
| readonly | `boolean` | - | Является ли поле доступным только для чтения |
|
|
398
|
+
| id | `string` | - | Значение html-атрибута id |
|
|
399
|
+
| name | `string` | - | Значение html-атрибута name |
|
|
400
|
+
| onFocus | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки получения фокуса |
|
|
401
|
+
| onBlur | `FocusEventHandler<HTMLInputElement>` | - | Колбек обработки потери фокуса |
|
|
402
|
+
| value | `number \| number[]` | - | |
|
|
403
|
+
| onChange | `(value: number \| number[]) => void` | - | |
|
|
404
|
+
| range | `boolean` | - | |
|
|
405
|
+
| tipFormatter | `(value: string \| number) => ReactNode` | - | |
|
|
406
|
+
| step | `number` | - | |
|
|
407
|
+
| min | `number` | - | |
|
|
408
|
+
| max | `number` | - | |
|
|
409
|
+
| marks | `Record<string \| number, ReactNode \| MarkObj>` | - | |
|
|
410
|
+
| className | `string` | - | CSS-класс |
|
|
411
|
+
| label | `string` | - | Лейбл |
|
|
412
|
+
| labelTooltip | `string` | - | Всплывающая подсказка лейбла |
|
|
413
|
+
| required | `boolean` | - | Является ли поле обязательным |
|
|
414
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | SIZE.S | Размер |
|
|
415
|
+
| labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
|
|
416
|
+
| hint | `string` | - | Подсказка внизу |
|
|
417
|
+
| showHintIcon | `boolean` | - | Отображать иконку подсказки |
|
|
214
418
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
215
419
|
| key | `Key` | - | |
|
|
216
420
|
|
|
@@ -21,6 +21,7 @@ import { extractSupportProps } from '@snack-uikit/utils';
|
|
|
21
21
|
import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
|
|
22
22
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
23
23
|
import { useCopyButton } from '../../hooks';
|
|
24
|
+
import { getValidationState } from '../../utils/getValidationState';
|
|
24
25
|
import { FieldDecorator } from '../FieldDecorator';
|
|
25
26
|
import { DEFAULT_LOCALE, SlotKey } from './constants';
|
|
26
27
|
import { useDateField } from './hooks';
|
|
@@ -45,6 +46,7 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
45
46
|
const showAdditionalButton = Boolean(valueProp && !disabled);
|
|
46
47
|
const showClearButton = showClearButtonProp && showAdditionalButton && !readonly;
|
|
47
48
|
const showCopyButton = showCopyButtonProp && showAdditionalButton && readonly;
|
|
49
|
+
const fieldValidationState = getValidationState({ validationState, error });
|
|
48
50
|
const checkForLeavingFocus = useCallback((event) => {
|
|
49
51
|
if (event.key === 'ArrowDown') {
|
|
50
52
|
setPickerAutofocus(true);
|
|
@@ -133,7 +135,7 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
133
135
|
e.stopPropagation();
|
|
134
136
|
}
|
|
135
137
|
}, [dateInputClickHandler, isOpen]);
|
|
136
|
-
return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState:
|
|
138
|
+
return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState: fieldValidationState }, extractSupportProps(rest), { children: _jsx(Dropdown, Object.assign({ trigger: 'click', triggerClassName: styles.triggerClassName, widthStrategy: 'gte' }, (readonly || disabled
|
|
137
139
|
? { open: false }
|
|
138
140
|
: {
|
|
139
141
|
open: showDropList,
|
|
@@ -143,5 +145,5 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
143
145
|
element === null || element === void 0 ? void 0 : element.focus();
|
|
144
146
|
setPickerAutofocus(false);
|
|
145
147
|
}
|
|
146
|
-
}, onFocusLeave: handleCalendarFocusLeave, locale: locale, "data-test-id": 'field-date__calendar' }) }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState:
|
|
148
|
+
}, onFocusLeave: handleCalendarFocusLeave, locale: locale, "data-test-id": 'field-date__calendar' }) }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, focused: showDropList, inputRef: localRef, postfix: _jsxs(_Fragment, { children: [buttons, _jsx(CalendarSVG, { size: calendarIconSize, className: styles.calendarIcon, "data-size": size })] }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value || '', placeholder: mask, onChange: handleChange, onFocus: inputHandlers.onFocus, onMouseDown: inputHandlers.onMouseDown, onBlur: onBlur, onKeyDown: handleInputKeyDown, onClick: onClick, disabled: disabled, readonly: readonly, tabIndex: inputTabIndex, type: 'text', id: id, name: name, "data-test-id": 'field-date__input' }) }) })) })));
|
|
147
149
|
});
|
|
@@ -12,4 +12,4 @@ export type FieldDecoratorProps = WithSupportProps<{
|
|
|
12
12
|
readonly?: boolean;
|
|
13
13
|
error?: string;
|
|
14
14
|
} & HeaderProps & FooterProps>;
|
|
15
|
-
export declare function FieldDecorator({ children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size, error, validationState
|
|
15
|
+
export declare function FieldDecorator({ children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size, error, validationState, ...rest }: FieldDecoratorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -14,12 +14,13 @@ import cn from 'classnames';
|
|
|
14
14
|
import { SIZE } from '@snack-uikit/input-private';
|
|
15
15
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
16
16
|
import { VALIDATION_STATE } from '../../constants';
|
|
17
|
+
import { getValidationState } from '../../utils/getValidationState';
|
|
17
18
|
import { Footer } from './Footer';
|
|
18
19
|
import { Header } from './Header';
|
|
19
20
|
import styles from './styles.module.css';
|
|
20
21
|
export function FieldDecorator(_a) {
|
|
21
|
-
var { children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size = SIZE.S, error, validationState
|
|
22
|
+
var { children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size = SIZE.S, error, validationState = VALIDATION_STATE.Default } = _a, rest = __rest(_a, ["children", "className", "label", "labelTooltip", "required", "labelFor", "length", "hint", "disabled", "readonly", "showHintIcon", "labelTooltipPlacement", "size", "error", "validationState"]);
|
|
22
23
|
const isFieldActive = !disabled && !readonly;
|
|
23
|
-
const
|
|
24
|
-
return (_jsxs("div", Object.assign({ className: cn(styles.decorator, className) }, extractSupportProps(rest), { "data-size": size, children: [label && (_jsx(Header, { labelTooltipPlacement: labelTooltipPlacement, required: required, label: label, labelTooltip: labelTooltip, labelFor: labelFor, size: size })), children, _jsx(Footer, { length: isFieldActive ? length : undefined, hint: error || hint, showHintIcon: showHintIcon, size: size, validationState: isFieldActive ?
|
|
24
|
+
const fieldValidationState = getValidationState({ validationState, error });
|
|
25
|
+
return (_jsxs("div", Object.assign({ className: cn(styles.decorator, className) }, extractSupportProps(rest), { "data-size": size, children: [label && (_jsx(Header, { labelTooltipPlacement: labelTooltipPlacement, required: required, label: label, labelTooltip: labelTooltip, labelFor: labelFor, size: size })), children, _jsx(Footer, { length: isFieldActive ? length : undefined, hint: error || hint, showHintIcon: showHintIcon, size: size, validationState: isFieldActive ? fieldValidationState : VALIDATION_STATE.Default })] })));
|
|
25
26
|
}
|
|
@@ -17,6 +17,7 @@ import { extractSupportProps } from '@snack-uikit/utils';
|
|
|
17
17
|
import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
|
|
18
18
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
19
19
|
import { useCopyButton, useHideButton, useValueControl } from '../../hooks';
|
|
20
|
+
import { getValidationState } from '../../utils/getValidationState';
|
|
20
21
|
import { FieldDecorator } from '../FieldDecorator';
|
|
21
22
|
export const FieldSecure = forwardRef((_a, ref) => {
|
|
22
23
|
var { id, name, value: valueProp, placeholder, maxLength, disabled = false, readonly = false, showCopyButton: showCopyButtonProp = true, allowMoreThanMaxLength = false, hidden: hiddenProp, onHiddenChange, showHintIcon, onChange: onChangeProp, onFocus, onBlur, className, label, labelTooltip, labelTooltipPlacement, required = false, hint, size = SIZE.S, validationState = VALIDATION_STATE.Default, prefixIcon, error } = _a, rest = __rest(_a, ["id", "name", "value", "placeholder", "maxLength", "disabled", "readonly", "showCopyButton", "allowMoreThanMaxLength", "hidden", "onHiddenChange", "showHintIcon", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "hint", "size", "validationState", "prefixIcon", "error"]);
|
|
@@ -35,6 +36,7 @@ export const FieldSecure = forwardRef((_a, ref) => {
|
|
|
35
36
|
});
|
|
36
37
|
const showCopyButton = showCopyButtonProp && Boolean(value) && readonly && !disabled;
|
|
37
38
|
const showHideButton = !(readonly && !value);
|
|
39
|
+
const fieldValidationState = getValidationState({ validationState, error });
|
|
38
40
|
const toggleHidden = () => {
|
|
39
41
|
setHidden(!hidden);
|
|
40
42
|
if (!readonly) {
|
|
@@ -53,5 +55,5 @@ export const FieldSecure = forwardRef((_a, ref) => {
|
|
|
53
55
|
readonly,
|
|
54
56
|
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
55
57
|
});
|
|
56
|
-
return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, length: maxLength ? { max: maxLength, current: value.length } : undefined, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState:
|
|
58
|
+
return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, length: maxLength ? { max: maxLength, current: value.length } : undefined, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState: fieldValidationState }, extractSupportProps(rest), { children: _jsx(FieldContainerPrivate, { size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: localRef, prefix: prefixIcon, postfix: buttons, children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value, onChange: onChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: onInputKeyDown, tabIndex: inputTabIndex, placeholder: placeholder, disabled: disabled, readonly: readonly, type: hidden ? 'password' : 'text', maxLength: allowMoreThanMaxLength ? undefined : maxLength || undefined, id: id, name: name, "data-test-id": 'field-secure__input' }) }) })));
|
|
57
59
|
});
|
|
@@ -19,6 +19,7 @@ import { Tag } from '@snack-uikit/tag';
|
|
|
19
19
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
20
20
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
21
21
|
import { useValueControl } from '../../hooks';
|
|
22
|
+
import { getValidationState } from '../../utils/getValidationState';
|
|
22
23
|
import { FieldDecorator } from '../FieldDecorator';
|
|
23
24
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
24
25
|
import { useButtons, useHandleDeleteItem, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
@@ -115,7 +116,8 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
115
116
|
};
|
|
116
117
|
const fuzzySearch = useFuzzySearch(items);
|
|
117
118
|
const result = autocomplete || !searchable || prevInputValue.current === inputValue ? items : fuzzySearch(inputValue);
|
|
118
|
-
|
|
119
|
+
const fieldValidationState = getValidationState({ validationState, error: rest.error });
|
|
120
|
+
return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { labelFor: id, size: size, validationState: fieldValidationState, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, triggerElemRef: localRef, selection: {
|
|
119
121
|
mode: 'multiple',
|
|
120
122
|
value: value,
|
|
121
123
|
onChange: value => {
|
|
@@ -124,7 +126,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
124
126
|
},
|
|
125
127
|
}, dataFiltered: (_b = rest.dataFiltered) !== null && _b !== void 0 ? _b : Boolean(inputValue.length), size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, children: ({ onKeyDown }) => {
|
|
126
128
|
var _a, _b, _c, _d;
|
|
127
|
-
return (_jsx(FieldContainerPrivate, { className: cn(styles.container, styles.tagContainer), validationState:
|
|
129
|
+
return (_jsx(FieldContainerPrivate, { className: cn(styles.container, styles.tagContainer), validationState: fieldValidationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: _jsxs(_Fragment, { children: [_jsxs("div", { className: styles.contentWrapper, ref: contentRef, children: [selectedItems &&
|
|
128
130
|
selectedItems.map(option => {
|
|
129
131
|
var _a;
|
|
130
132
|
return (_jsx(Tag, { size: size === 'l' ? 's' : 'xs', tabIndex: -1, label: selectedOptionFormatter(option), appearance: (_a = option.appearance) !== null && _a !== void 0 ? _a : 'neutral', onDelete: !option.disabled && !disabled && !readonly ? handleItemDelete(option) : undefined }, option.id));
|
|
@@ -18,6 +18,7 @@ import { Droplist } from '@snack-uikit/list';
|
|
|
18
18
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
19
19
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
20
20
|
import { useValueControl } from '../../hooks';
|
|
21
|
+
import { getValidationState } from '../../utils/getValidationState';
|
|
21
22
|
import { FieldDecorator } from '../FieldDecorator';
|
|
22
23
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
23
24
|
import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
@@ -122,11 +123,12 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
122
123
|
const result = autocomplete || !searchable || selectedOptionFormatter(selectedItem) === inputValue
|
|
123
124
|
? items
|
|
124
125
|
: fuzzySearch(inputValue);
|
|
125
|
-
|
|
126
|
+
const fieldValidationState = getValidationState({ validationState, error: rest.error });
|
|
127
|
+
return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { validationState: fieldValidationState, required: required, readonly: readonly, labelFor: id, disabled: disabled, size: size, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, selection: {
|
|
126
128
|
mode: 'single',
|
|
127
129
|
value: value,
|
|
128
130
|
onChange: handleSelectionChange,
|
|
129
|
-
}, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) => (_jsxs(FieldContainerPrivate, { className: styles.container, validationState:
|
|
131
|
+
}, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) => (_jsxs(FieldContainerPrivate, { className: styles.container, validationState: fieldValidationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: [_jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: placeholder, ref: mergeRefs(ref, localRef), onChange: searchable ? setInputValue : undefined, value: searchable ? inputValue : selectedOptionFormatter(selectedItem), readonly: readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur, className: cn({
|
|
130
132
|
[styles.readonlyCursor]: !searchable,
|
|
131
133
|
}) }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) })) })));
|
|
132
134
|
});
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import mergeRefs from 'merge-refs';
|
|
14
|
-
import { forwardRef, useEffect, useRef, useState } from 'react';
|
|
14
|
+
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
15
15
|
import { InputPrivate, SIZE } from '@snack-uikit/input-private';
|
|
16
16
|
import { Slider } from '@snack-uikit/slider';
|
|
17
17
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
@@ -19,7 +19,7 @@ import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
|
|
|
19
19
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
20
20
|
import { useValueControl } from '../../hooks';
|
|
21
21
|
import { FieldDecorator } from '../FieldDecorator';
|
|
22
|
-
import { generateAllowedValues, getClosestMark, getTextFieldValue } from './helpers';
|
|
22
|
+
import { generateAllowedValues, getClosestMark, getTextFieldValue, isMarkObject } from './helpers';
|
|
23
23
|
import styles from './styles.module.css';
|
|
24
24
|
const getDefaultValue = (range, min, max, value) => {
|
|
25
25
|
if (range) {
|
|
@@ -32,6 +32,14 @@ const getDefaultValue = (range, min, max, value) => {
|
|
|
32
32
|
};
|
|
33
33
|
export const FieldSlider = forwardRef((_a, ref) => {
|
|
34
34
|
var { id, name, min, max, step, marks, showScaleBar = true, value: valueProp, range = false, disabled = false, readonly = false, onChange: onChangeProp, onFocus, onBlur, className, label, labelTooltip, labelTooltipPlacement, required, hint, showHintIcon, size = SIZE.S, postfixIcon, textInputFormatter } = _a, rest = __rest(_a, ["id", "name", "min", "max", "step", "marks", "showScaleBar", "value", "range", "disabled", "readonly", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "hint", "showHintIcon", "size", "postfixIcon", "textInputFormatter"]);
|
|
35
|
+
const getMarkValue = useCallback((key) => {
|
|
36
|
+
const mark = marks[key];
|
|
37
|
+
if (isMarkObject(mark)) {
|
|
38
|
+
return mark.label;
|
|
39
|
+
}
|
|
40
|
+
return mark;
|
|
41
|
+
}, [marks]);
|
|
42
|
+
const hasMarksEqualToValues = useMemo(() => Object.keys(marks).every(key => key === getMarkValue(key)), [getMarkValue, marks]);
|
|
35
43
|
const [value = getDefaultValue(range, min, max, valueProp), onChange] = useValueControl({
|
|
36
44
|
value: valueProp,
|
|
37
45
|
defaultValue: getDefaultValue(range, min, max, valueProp),
|
|
@@ -40,46 +48,82 @@ export const FieldSlider = forwardRef((_a, ref) => {
|
|
|
40
48
|
const [textFieldInputValue, setTextFieldInputValue] = useState(getTextFieldValue(value, textInputFormatter));
|
|
41
49
|
const localRef = useRef(null);
|
|
42
50
|
const onTextFieldChange = (textFieldValue) => {
|
|
43
|
-
const numValue =
|
|
44
|
-
if (Number.isNaN(numValue)) {
|
|
51
|
+
const numValue = parseInt(textFieldValue);
|
|
52
|
+
if (textFieldValue && Number.isNaN(numValue)) {
|
|
45
53
|
return;
|
|
46
54
|
}
|
|
47
55
|
setTextFieldInputValue(textFieldValue);
|
|
48
56
|
};
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
57
|
+
const handleNonEqualMarksSliderChange = (textFieldNumValue) => {
|
|
58
|
+
const handleChange = (key) => {
|
|
59
|
+
setTextFieldInputValue(String(getMarkValue(key)));
|
|
60
|
+
onChange(Number(key));
|
|
61
|
+
};
|
|
62
|
+
const allowedValues = Object.keys(marks).map(key => ({
|
|
63
|
+
key,
|
|
64
|
+
value: parseInt(String(getMarkValue(key))),
|
|
65
|
+
}));
|
|
66
|
+
const suitableEntry = allowedValues.find(entry => entry.value === textFieldNumValue);
|
|
67
|
+
if (suitableEntry) {
|
|
68
|
+
handleChange(suitableEntry.key);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const actualMin = parseInt(String(getMarkValue(min)));
|
|
72
|
+
const actualMax = parseInt(String(getMarkValue(max)));
|
|
73
|
+
if (textFieldNumValue < actualMin) {
|
|
74
|
+
handleChange(min);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (textFieldNumValue > actualMax) {
|
|
78
|
+
handleChange(max);
|
|
52
79
|
return;
|
|
53
80
|
}
|
|
81
|
+
const { mark } = getClosestMark(textFieldNumValue, allowedValues, mark => mark.value);
|
|
82
|
+
handleChange(mark.key);
|
|
83
|
+
};
|
|
84
|
+
const handleEqualMarksSliderChange = (textFieldNumValue) => {
|
|
85
|
+
const handleChange = (value) => {
|
|
86
|
+
setTextFieldInputValue(String(value));
|
|
87
|
+
onChange(value);
|
|
88
|
+
};
|
|
54
89
|
if (textFieldNumValue < min) {
|
|
55
|
-
|
|
56
|
-
onChange(min);
|
|
90
|
+
handleChange(min);
|
|
57
91
|
return;
|
|
58
92
|
}
|
|
59
93
|
if (textFieldNumValue > max) {
|
|
60
|
-
|
|
61
|
-
onChange(max);
|
|
94
|
+
handleChange(max);
|
|
62
95
|
return;
|
|
63
96
|
}
|
|
64
97
|
if (step === null) {
|
|
65
98
|
const allowedValues = Object.keys(marks).map(Number);
|
|
66
99
|
if (allowedValues.includes(textFieldNumValue)) {
|
|
67
|
-
|
|
100
|
+
setTextFieldInputValue(String(textFieldNumValue));
|
|
101
|
+
handleChange(textFieldNumValue);
|
|
68
102
|
return;
|
|
69
103
|
}
|
|
70
|
-
const { mark } = getClosestMark(textFieldNumValue, allowedValues);
|
|
71
|
-
|
|
72
|
-
onChange(mark);
|
|
104
|
+
const { mark } = getClosestMark(textFieldNumValue, allowedValues, mark => mark);
|
|
105
|
+
handleChange(mark);
|
|
73
106
|
return;
|
|
74
107
|
}
|
|
75
108
|
const allowedValues = generateAllowedValues(min, max, step);
|
|
76
109
|
if (allowedValues.includes(textFieldNumValue)) {
|
|
77
|
-
|
|
110
|
+
handleChange(textFieldNumValue);
|
|
78
111
|
return;
|
|
79
112
|
}
|
|
80
|
-
const { mark } = getClosestMark(textFieldNumValue, allowedValues);
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
const { mark } = getClosestMark(textFieldNumValue, allowedValues, mark => mark);
|
|
114
|
+
handleChange(mark);
|
|
115
|
+
};
|
|
116
|
+
const handleTextValueChange = () => {
|
|
117
|
+
const textFieldNumValue = parseInt(textFieldInputValue);
|
|
118
|
+
if (Number.isNaN(textFieldNumValue)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (hasMarksEqualToValues) {
|
|
122
|
+
handleEqualMarksSliderChange(textFieldNumValue);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
handleNonEqualMarksSliderChange(textFieldNumValue);
|
|
126
|
+
}
|
|
83
127
|
};
|
|
84
128
|
const onTextFieldBlur = (e) => {
|
|
85
129
|
onBlur === null || onBlur === void 0 ? void 0 : onBlur(e);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const getDiff = (value, mark) => Math.abs(mark - value);
|
|
2
|
-
export const getClosestMark = (value, marks) => marks.reduce((accResult, mark) => {
|
|
3
|
-
const diff = getDiff(value, mark);
|
|
2
|
+
export const getClosestMark = (value, marks, getMarkValue) => marks.reduce((accResult, mark) => {
|
|
3
|
+
const diff = getDiff(value, getMarkValue(mark));
|
|
4
4
|
if (diff < accResult.lowestDiff) {
|
|
5
5
|
return {
|
|
6
6
|
lowestDiff: diff,
|
|
@@ -9,6 +9,6 @@ export const getClosestMark = (value, marks) => marks.reduce((accResult, mark) =
|
|
|
9
9
|
}
|
|
10
10
|
return accResult;
|
|
11
11
|
}, {
|
|
12
|
-
lowestDiff: getDiff(value, marks[0]),
|
|
12
|
+
lowestDiff: getDiff(value, getMarkValue(marks[0])),
|
|
13
13
|
mark: marks[0],
|
|
14
14
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { SliderProps as SliderComponentProps } from '@snack-uikit/slider';
|
|
3
|
+
type Marks = NonNullable<SliderComponentProps['marks']>;
|
|
4
|
+
type MarkObject = {
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export declare function isMarkObject(mark: Marks[keyof Marks]): mark is MarkObject;
|
|
8
|
+
export {};
|