@snack-uikit/fields 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +9 -0
  3. package/dist/components/FieldColor/FieldColor.d.ts +1 -1
  4. package/dist/components/FieldColor/FieldColor.js +3 -3
  5. package/dist/components/FieldDate/FieldDate.js +11 -5
  6. package/dist/components/FieldSecure/FieldSecure.d.ts +1 -1
  7. package/dist/components/FieldSecure/FieldSecure.js +3 -3
  8. package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +3 -1
  9. package/dist/components/FieldSelect/FieldSelectMultiple.js +7 -5
  10. package/dist/components/FieldSelect/FieldSelectSingle.d.ts +3 -1
  11. package/dist/components/FieldSelect/FieldSelectSingle.js +8 -6
  12. package/dist/components/FieldSelect/hooks.d.ts +1 -1
  13. package/dist/components/FieldSelect/hooks.js +3 -3
  14. package/dist/components/FieldSelect/types.d.ts +5 -1
  15. package/dist/components/FieldSlider/FieldSlider.d.ts +6 -2
  16. package/dist/components/FieldSlider/FieldSlider.js +13 -11
  17. package/dist/components/FieldStepper/FieldStepper.d.ts +5 -1
  18. package/dist/components/FieldStepper/FieldStepper.js +6 -4
  19. package/dist/components/FieldText/FieldText.d.ts +9 -2
  20. package/dist/components/FieldText/FieldText.js +46 -8
  21. package/dist/components/FieldText/helpers.d.ts +4 -0
  22. package/dist/components/FieldText/helpers.js +9 -0
  23. package/dist/components/FieldTextArea/FieldTextArea.d.ts +1 -1
  24. package/dist/components/FieldTextArea/FieldTextArea.js +3 -3
  25. package/dist/constants.d.ts +6 -0
  26. package/dist/constants.js +6 -0
  27. package/dist/helperComponents/ButtonField/ButtonField.d.ts +18 -0
  28. package/dist/helperComponents/ButtonField/ButtonField.js +10 -0
  29. package/dist/helperComponents/ButtonField/index.d.ts +1 -0
  30. package/dist/helperComponents/ButtonField/index.js +1 -0
  31. package/dist/helperComponents/ButtonField/styles.module.css +96 -0
  32. package/dist/helperComponents/ButtonFieldList/ButtonFieldList.d.ts +4 -0
  33. package/dist/helperComponents/ButtonFieldList/ButtonFieldList.js +27 -0
  34. package/dist/helperComponents/ButtonFieldList/helpers.d.ts +5 -0
  35. package/dist/helperComponents/ButtonFieldList/helpers.js +8 -0
  36. package/dist/helperComponents/ButtonFieldList/index.d.ts +1 -0
  37. package/dist/helperComponents/ButtonFieldList/index.js +1 -0
  38. package/dist/helperComponents/ButtonFieldList/styles.module.css +3 -0
  39. package/dist/helperComponents/FieldContainerPrivate/FieldContainerPrivate.d.ts +5 -4
  40. package/dist/helperComponents/FieldContainerPrivate/FieldContainerPrivate.js +2 -2
  41. package/dist/helperComponents/FieldContainerPrivate/styles.module.css +56 -5
  42. package/dist/helperComponents/index.d.ts +2 -0
  43. package/dist/helperComponents/index.js +2 -0
  44. package/dist/hooks/index.d.ts +4 -0
  45. package/dist/hooks/index.js +4 -0
  46. package/dist/hooks/styles.module.css +13 -0
  47. package/dist/hooks/useCopyButton.d.ts +3 -1
  48. package/dist/hooks/useCopyButton.js +4 -3
  49. package/dist/hooks/useHideButton.js +1 -0
  50. package/dist/hooks/usePostfix.d.ts +6 -0
  51. package/dist/hooks/usePostfix.js +11 -0
  52. package/dist/hooks/usePostfixButton.d.ts +11 -0
  53. package/dist/hooks/usePostfixButton.js +28 -0
  54. package/dist/hooks/usePrefix.d.ts +6 -0
  55. package/dist/hooks/usePrefix.js +11 -0
  56. package/dist/hooks/usePrefixButton.d.ts +11 -0
  57. package/dist/hooks/usePrefixButton.js +28 -0
  58. package/dist/types.d.ts +12 -1
  59. package/package.json +6 -5
  60. package/src/components/FieldColor/FieldColor.tsx +6 -3
  61. package/src/components/FieldDate/FieldDate.tsx +17 -10
  62. package/src/components/FieldSecure/FieldSecure.tsx +3 -3
  63. package/src/components/FieldSelect/FieldSelectMultiple.tsx +17 -4
  64. package/src/components/FieldSelect/FieldSelectSingle.tsx +17 -4
  65. package/src/components/FieldSelect/hooks.ts +3 -3
  66. package/src/components/FieldSelect/types.ts +10 -2
  67. package/src/components/FieldSlider/FieldSlider.tsx +30 -14
  68. package/src/components/FieldStepper/FieldStepper.tsx +40 -23
  69. package/src/components/FieldText/FieldText.tsx +78 -10
  70. package/src/components/FieldText/helpers.tsx +13 -0
  71. package/src/components/FieldTextArea/FieldTextArea.tsx +6 -3
  72. package/src/constants.ts +7 -0
  73. package/src/helperComponents/ButtonField/ButtonField.tsx +73 -0
  74. package/src/helperComponents/ButtonField/index.ts +1 -0
  75. package/src/helperComponents/ButtonField/styles.module.scss +57 -0
  76. package/src/helperComponents/ButtonFieldList/ButtonFieldList.tsx +36 -0
  77. package/src/helperComponents/ButtonFieldList/helpers.tsx +13 -0
  78. package/src/helperComponents/ButtonFieldList/index.ts +1 -0
  79. package/src/helperComponents/ButtonFieldList/styles.module.scss +5 -0
  80. package/src/helperComponents/FieldContainerPrivate/FieldContainerPrivate.tsx +6 -3
  81. package/src/helperComponents/FieldContainerPrivate/styles.module.scss +14 -8
  82. package/src/helperComponents/index.ts +2 -0
  83. package/src/hooks/index.ts +4 -0
  84. package/src/hooks/styles.module.scss +17 -0
  85. package/src/hooks/useCopyButton.tsx +7 -2
  86. package/src/hooks/useHideButton.tsx +1 -0
  87. package/src/hooks/usePostfix.tsx +21 -0
  88. package/src/hooks/usePostfixButton.tsx +74 -0
  89. package/src/hooks/usePrefix.tsx +21 -0
  90. package/src/hooks/usePrefixButton.tsx +74 -0
  91. package/src/types.ts +16 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
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.29.0 (2024-09-27)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **PDS-199:** ajust components according to new useButtonNavigation api ([4e9b58b](https://github.com/cloud-ru-tech/snack-uikit/commit/4e9b58b2345e4e630aee94679c9831c9861a4548))
12
+
13
+
14
+ ### Features
15
+
16
+ * **PDS-199:** add button prop - to field-text; add prefix and postfix props - to field-text, field-slider, field-stepper, field-select ([8bfb5eb](https://github.com/cloud-ru-tech/snack-uikit/commit/8bfb5ebc9320a451cb3765b8377e022115b4a371))
17
+
18
+
19
+
20
+
21
+
6
22
  # 0.28.0 (2024-09-26)
7
23
 
8
24
 
package/README.md CHANGED
@@ -214,6 +214,9 @@ FieldStepper в основном предназначен для работы с
214
214
  | showClearButton | `boolean` | true | Отображение кнопки очистки поля |
215
215
  | allowMoreThanMaxLength | `boolean` | - | Можно ли вводить больше разрешённого кол-ва символов |
216
216
  | prefixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-префикс для поля |
217
+ | prefix | `ReactNode` | - | Произвольный префикс для поля |
218
+ | postfix | `ReactNode` | - | Произвольный постфикс для поля |
219
+ | button | `Button` | - | Кнопка действия внутри поля |
217
220
  | value | `string` | - | Значение input |
218
221
  | onChange | `(value: string, e?: ChangeEvent<HTMLInputElement>) => void` | - | Колбек смены значения |
219
222
  | disabled | `boolean` | - | Является ли поле деактивированным |
@@ -365,6 +368,8 @@ FieldStepper в основном предназначен для работы с
365
368
  | validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | - | Состояние валидации |
366
369
  | showHintIcon | `boolean` | - | Отображать иконку подсказки |
367
370
  | loading | `boolean` | - | |
371
+ | prefix | `ReactNode` | - | Произвольный префикс для поля |
372
+ | postfix | `ReactNode` | - | Произвольный постфикс для поля |
368
373
  | value | `ItemId \| ItemId[]` | - | Controlled состояние |
369
374
  | onChange | `OnChangeHandler<any>` | - | Controlled обработчик измения состояния |
370
375
  | defaultValue | `ItemId \| ItemId[]` | - | Начальное состояние |
@@ -402,6 +407,8 @@ FieldStepper в основном предназначен для работы с
402
407
  | onChange | `(value: number, e?: ChangeEvent<HTMLInputElement>) => void` | - | Колбек смены значения |
403
408
  | step | `number` | 1 | Шаг поля |
404
409
  | allowMoreThanLimits | `boolean` | true | Можно ли вводить c клавиатуры числа, выходящие за пределы min/max |
410
+ | prefix | `ReactNode` | - | Произвольный префикс для поля |
411
+ | postfix | `ReactNode` | - | Произвольный постфикс для поля |
405
412
  | disabled | `boolean` | - | Является ли поле деактивированным |
406
413
  | readonly | `boolean` | - | Является ли поле доступным только для чтения |
407
414
  | id | `string` | - | Значение html-атрибута id |
@@ -431,6 +438,8 @@ FieldStepper в основном предназначен для работы с
431
438
  | showScaleBar | `boolean` | true | Отображение линейки |
432
439
  | textInputFormatter | `TextInputFormatter` | - | Функция для форматирования значений в текстовом поле |
433
440
  | unbindInputFromMarks | `boolean` | - | Отвязать текстовое поле от значений на линейке |
441
+ | prefix | `ReactNode` | - | Произвольный префикс для поля |
442
+ | postfix | `ReactNode` | - | Произвольный постфикс для поля |
434
443
  | disabled | `boolean` | - | Является ли поле деактивированным |
435
444
  | readonly | `boolean` | - | Является ли поле доступным только для чтения |
436
445
  | id | `string` | - | Значение html-атрибута id |
@@ -36,5 +36,5 @@ export declare const FieldColor: import("react").ForwardRefExoticComponent<{
36
36
  showClearButton?: boolean;
37
37
  value?: string;
38
38
  onChange?(value: string): void;
39
- } & Omit<ColorPickerProps, "onChange" | "value"> & InputProps & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
39
+ } & Omit<ColorPickerProps, "value" | "onChange"> & InputProps & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
40
40
  export {};
@@ -44,9 +44,9 @@ export const FieldColor = forwardRef((_a, ref) => {
44
44
  };
45
45
  const clearButtonSettings = useClearButton({ clearButtonRef, showClearButton, size, onClear });
46
46
  const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy: value });
47
- const { buttons, inputTabIndex, onInputKeyDown } = useButtonNavigation({
47
+ const { postfixButtons, inputTabIndex, onInputKeyDown } = useButtonNavigation({
48
48
  inputRef: localRef,
49
- buttons: useMemo(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
49
+ postfixButtons: useMemo(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
50
50
  readonly,
51
51
  submitKeys: ['Enter', 'Space', 'Tab'],
52
52
  });
@@ -65,7 +65,7 @@ export const FieldColor = forwardRef((_a, ref) => {
65
65
  setValue === null || setValue === void 0 ? void 0 : setValue(hex || '');
66
66
  }, colorMode: {
67
67
  hex: false,
68
- } }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, focused: showDropList, inputRef: localRef, postfix: buttons, prefix: _jsx("div", { className: styles.colorPreview, style: {
68
+ } }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, focused: showDropList, inputRef: localRef, postfix: postfixButtons, prefix: _jsx("div", { className: styles.colorPreview, style: {
69
69
  '--color': value,
70
70
  } }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value, onChange: onChange, onFocus: onFocus, onBlur: onBlur, tabIndex: inputTabIndex, onKeyDown: onInputKeyDown, disabled: disabled, readonly: readonly, placeholder: placeholder, type: 'text', id: id, name: name, "data-test-id": 'field-color__input' }) }) })) })));
71
71
  });
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import mergeRefs from 'merge-refs';
14
14
  import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
15
15
  import { useUncontrolledProp } from 'uncontrollable';
@@ -70,7 +70,13 @@ export const FieldDate = forwardRef((_a, ref) => {
70
70
  }, [onChange, required, setIsOpen]);
71
71
  const clearButtonSettings = useClearButton({ clearButtonRef, showClearButton, size, onClear: handleClear });
72
72
  const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy: valueProp || '' });
73
- const memorizedButtons = useMemo(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]);
73
+ const calendarIcon = useMemo(() => ({
74
+ active: false,
75
+ show: true,
76
+ id: 'calendarIcon',
77
+ render: props => (_jsx(CalendarSVG, Object.assign({}, props, { size: calendarIconSize, className: styles.calendarIcon, "data-size": size }))),
78
+ }), [calendarIconSize, size]);
79
+ const memorizedButtons = useMemo(() => [clearButtonSettings, copyButtonSettings, calendarIcon], [clearButtonSettings, copyButtonSettings, calendarIcon]);
74
80
  const { value, handleChange, handleClick: dateInputClickHandler, handleKeyDown: dateInputKeyDownHandler, handleBlur: dateInputBlurHandler, mask, setInputFocus, } = useDateField({
75
81
  inputRef: localRef,
76
82
  onChange,
@@ -79,10 +85,10 @@ export const FieldDate = forwardRef((_a, ref) => {
79
85
  setIsOpen,
80
86
  });
81
87
  const setInputFocusFromButtons = useCallback(() => setInputFocus(SlotKey.Year), [setInputFocus]);
82
- const { buttons, inputTabIndex, onInputKeyDown: navigationInputKeyDownHandler, setInitialTabIndices, } = useButtonNavigation({
88
+ const { postfixButtons, inputTabIndex, onInputKeyDown: navigationInputKeyDownHandler, setInitialTabIndices, } = useButtonNavigation({
83
89
  setInputFocus: setInputFocusFromButtons,
84
90
  inputRef: localRef,
85
- buttons: memorizedButtons,
91
+ postfixButtons: memorizedButtons,
86
92
  onButtonKeyDown: checkForLeavingFocus,
87
93
  readonly,
88
94
  submitKeys: ['Enter', 'Space', 'Tab'],
@@ -145,5 +151,5 @@ export const FieldDate = forwardRef((_a, ref) => {
145
151
  element === null || element === void 0 ? void 0 : element.focus();
146
152
  setPickerAutofocus(false);
147
153
  }
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' }) }) })) })));
154
+ }, 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: postfixButtons, 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' }) }) })) })));
149
155
  });
@@ -21,5 +21,5 @@ type FieldSecureOwnProps = {
21
21
  export type FieldSecureProps = WithSupportProps<FieldSecureOwnProps & InputProps & WrapperProps>;
22
22
  export declare const FieldSecure: import("react").ForwardRefExoticComponent<{
23
23
  'data-test-id'?: string;
24
- } & import("react").AriaAttributes & FieldSecureOwnProps & Pick<Partial<InputPrivateProps>, "onChange" | "value"> & Pick<InputPrivateProps, "disabled" | "readonly" | "id" | "name" | "onFocus" | "onBlur" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
24
+ } & import("react").AriaAttributes & FieldSecureOwnProps & Pick<Partial<InputPrivateProps>, "value" | "onChange"> & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
25
25
  export {};
@@ -104,11 +104,11 @@ export const FieldSecure = forwardRef((_a, ref) => {
104
104
  hidden,
105
105
  disabled: disabled || isLoading,
106
106
  });
107
- const { buttons, inputTabIndex, onInputKeyDown } = useButtonNavigation({
107
+ const { postfixButtons, inputTabIndex, onInputKeyDown } = useButtonNavigation({
108
108
  inputRef: localRef,
109
- buttons: useMemo(() => [copyButtonSettings, hideButtonSettings], [copyButtonSettings, hideButtonSettings]),
109
+ postfixButtons: useMemo(() => [copyButtonSettings, hideButtonSettings], [copyButtonSettings, hideButtonSettings]),
110
110
  readonly,
111
111
  submitKeys: ['Enter', 'Space', 'Tab'],
112
112
  });
113
- return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, caption: caption, 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(WithSkeleton, { skeleton: _jsx(Skeleton, { width: '100%', borderRadius: 2 }), loading: isLoading, 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', autoComplete: autoComplete }) }) }) })));
113
+ return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, caption: caption, 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: postfixButtons, children: _jsx(WithSkeleton, { skeleton: _jsx(Skeleton, { width: '100%', borderRadius: 2 }), loading: isLoading, 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', autoComplete: autoComplete }) }) }) })));
114
114
  });
@@ -2,6 +2,8 @@ import { SelectedOptionFormatter } from './types';
2
2
  export declare const FieldSelectMultiple: import("react").ForwardRefExoticComponent<import("./types").InputProps & import("./types").WrapperProps & {
3
3
  options: import("./types").OptionProps[];
4
4
  loading?: boolean;
5
+ prefix?: import("react").ReactNode;
6
+ postfix?: import("react").ReactNode;
5
7
  } & {
6
8
  removeByBackspace?: boolean;
7
9
  } & Omit<import("@snack-uikit/list").SelectionMultipleState, "mode"> & Omit<{
@@ -25,4 +27,4 @@ export declare const FieldSelectMultiple: import("react").ForwardRefExoticCompon
25
27
  resetSearchOnOptionSelection?: boolean;
26
28
  onOpenChange?(open: boolean): void;
27
29
  selectedOptionFormatter?: SelectedOptionFormatter;
28
- } & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
30
+ } & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataFiltered" | "dataError" | "noDataState" | "noResultsState" | "errorDataState">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -18,7 +18,7 @@ import { Droplist } from '@snack-uikit/list';
18
18
  import { Tag } from '@snack-uikit/tag';
19
19
  import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
20
20
  import { FieldContainerPrivate } from '../../helperComponents';
21
- import { useValueControl } from '../../hooks';
21
+ import { usePostfix, usePrefix, useValueControl } from '../../hooks';
22
22
  import { getValidationState } from '../../utils/getValidationState';
23
23
  import { FieldDecorator } from '../FieldDecorator';
24
24
  import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
@@ -32,7 +32,7 @@ const defaultSelectedOptionFormatter = item =>
32
32
  (item === null || item === void 0 ? void 0 : item.content.option) || '';
33
33
  export const FieldSelectMultiple = forwardRef((props, ref) => {
34
34
  var _a;
35
- const { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showClearButton = true, onKeyDown: onInputKeyDownProp, validationState = 'default', search, autocomplete = false, prefixIcon, removeByBackspace = false, addOptionByEnter = false, untouchableScrollbars = false, open: openProp, enableFuzzySearch = true, resetSearchOnOptionSelection = true, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "validationState", "search", "autocomplete", "prefixIcon", "removeByBackspace", "addOptionByEnter", "untouchableScrollbars", "open", "enableFuzzySearch", "resetSearchOnOptionSelection", "onOpenChange", "selectedOptionFormatter"]);
35
+ const { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showClearButton = true, onKeyDown: onInputKeyDownProp, validationState = 'default', search, autocomplete = false, prefixIcon, prefix, postfix, removeByBackspace = false, addOptionByEnter = false, untouchableScrollbars = false, open: openProp, enableFuzzySearch = true, resetSearchOnOptionSelection = true, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "validationState", "search", "autocomplete", "prefixIcon", "prefix", "postfix", "removeByBackspace", "addOptionByEnter", "untouchableScrollbars", "open", "enableFuzzySearch", "resetSearchOnOptionSelection", "onOpenChange", "selectedOptionFormatter"]);
36
36
  const localRef = useRef(null);
37
37
  const inputPlugRef = useRef(null);
38
38
  const contentRef = useRef(null);
@@ -45,6 +45,8 @@ export const FieldSelectMultiple = forwardRef((props, ref) => {
45
45
  const [{ selectedItems, items = [] }, setItems] = useState(() => updateMultipleItems({ options, value, currentItems: [], selectedItems: undefined }));
46
46
  const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '', selectedOptionFormatter,
47
47
  resetSearchOnOptionSelection }));
48
+ const prefixSettings = usePrefix({ prefix, disabled });
49
+ const postfixSettings = usePostfix({ postfix, disabled });
48
50
  useLayoutEffect(() => {
49
51
  setItems(({ selectedItems }) => updateMultipleItems({ options, value, selectedItems }));
50
52
  }, [options, value]);
@@ -57,7 +59,7 @@ export const FieldSelectMultiple = forwardRef((props, ref) => {
57
59
  }
58
60
  };
59
61
  const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
60
- const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
62
+ const { postfixButtons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
61
63
  readonly,
62
64
  size,
63
65
  showClearButton: showClearButton && !disabled && !readonly && Boolean(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.find(item => !item.disabled)),
@@ -135,7 +137,7 @@ export const FieldSelectMultiple = forwardRef((props, ref) => {
135
137
  },
136
138
  }, dataFiltered: (_a = rest.dataFiltered) !== null && _a !== void 0 ? _a : Boolean(inputValue.length), untouchableScrollbars: untouchableScrollbars, size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, children: ({ onKeyDown }) => {
137
139
  var _a, _b, _c, _d;
138
- 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 &&
140
+ 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 || prefixSettings.show) && (_jsxs(_Fragment, { children: [prefixIcon, prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })] })), children: _jsxs(_Fragment, { children: [_jsxs("div", { className: styles.contentWrapper, ref: contentRef, children: [selectedItems &&
139
141
  selectedItems.map(option => {
140
142
  var _a;
141
143
  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));
@@ -145,6 +147,6 @@ export const FieldSelectMultiple = forwardRef((props, ref) => {
145
147
  : '100%',
146
148
  }, children: _jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: !selectedItems || !selectedItems.length ? placeholder : undefined, ref: mergeRefs(ref, localRef), onChange: searchable ? setInputValue : undefined, value: searchable ? inputValue : '', readonly: !searchable || readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur, className: cn({
147
149
  [styles.readonlyCursor]: !searchable,
148
- }) }) })] }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] }), _jsx("span", { ref: inputPlugRef, className: styles.inputPlug, children: inputValue })] }) }));
150
+ }) }) })] }), _jsxs("div", { className: styles.postfix, children: [postfixButtons, postfixSettings.show && postfixSettings.render({ key: postfixSettings.id }), _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] }), _jsx("span", { ref: inputPlugRef, className: styles.inputPlug, children: inputValue })] }) }));
149
151
  } })) })));
150
152
  });
@@ -2,6 +2,8 @@ import { SelectedOptionFormatter } from './types';
2
2
  export declare const FieldSelectSingle: import("react").ForwardRefExoticComponent<import("./types").InputProps & import("./types").WrapperProps & {
3
3
  options: import("./types").OptionProps[];
4
4
  loading?: boolean;
5
+ prefix?: import("react").ReactNode;
6
+ postfix?: import("react").ReactNode;
5
7
  } & Omit<import("@snack-uikit/list").SelectionSingleState, "mode"> & Omit<{
6
8
  'data-test-id'?: string;
7
9
  } & import("react").AriaAttributes & {
@@ -23,4 +25,4 @@ export declare const FieldSelectSingle: import("react").ForwardRefExoticComponen
23
25
  resetSearchOnOptionSelection?: boolean;
24
26
  onOpenChange?(open: boolean): void;
25
27
  selectedOptionFormatter?: SelectedOptionFormatter;
26
- } & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState">, "resetSearchOnOptionSelection"> & import("react").RefAttributes<HTMLInputElement>>;
28
+ } & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataFiltered" | "dataError" | "noDataState" | "noResultsState" | "errorDataState">, "resetSearchOnOptionSelection"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
14
  import mergeRefs from 'merge-refs';
15
15
  import { forwardRef, useCallback, useEffect, useRef, useState, } from 'react';
@@ -17,7 +17,7 @@ import { InputPrivate } from '@snack-uikit/input-private';
17
17
  import { Droplist } from '@snack-uikit/list';
18
18
  import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
19
19
  import { FieldContainerPrivate } from '../../helperComponents';
20
- import { useValueControl } from '../../hooks';
20
+ import { usePostfix, usePrefix, useValueControl } from '../../hooks';
21
21
  import { getValidationState } from '../../utils/getValidationState';
22
22
  import { FieldDecorator } from '../FieldDecorator';
23
23
  import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
@@ -29,7 +29,7 @@ const defaultSelectedOptionFormatter = item =>
29
29
  // @ts-expect-error
30
30
  (item === null || item === void 0 ? void 0 : item.content.option) || '';
31
31
  export const FieldSelectSingle = forwardRef((props, ref) => {
32
- const { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showCopyButton = true, showClearButton = true, onKeyDown: onInputKeyDownProp, required = false, validationState = 'default', search, autocomplete = false, prefixIcon, addOptionByEnter = false, untouchableScrollbars = false, open: openProp, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter, enableFuzzySearch = true } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showCopyButton", "showClearButton", "onKeyDown", "required", "validationState", "search", "autocomplete", "prefixIcon", "addOptionByEnter", "untouchableScrollbars", "open", "onOpenChange", "selectedOptionFormatter", "enableFuzzySearch"]);
32
+ const { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showCopyButton = true, showClearButton = true, onKeyDown: onInputKeyDownProp, required = false, validationState = 'default', search, autocomplete = false, prefixIcon, prefix, postfix, addOptionByEnter = false, untouchableScrollbars = false, open: openProp, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter, enableFuzzySearch = true } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showCopyButton", "showClearButton", "onKeyDown", "required", "validationState", "search", "autocomplete", "prefixIcon", "prefix", "postfix", "addOptionByEnter", "untouchableScrollbars", "open", "onOpenChange", "selectedOptionFormatter", "enableFuzzySearch"]);
33
33
  const localRef = useRef(null);
34
34
  const [open = false, setOpen] = useValueControl({ value: openProp, onChange: onOpenChange });
35
35
  const [value, setValue] = useValueControl({
@@ -40,6 +40,8 @@ export const FieldSelectSingle = forwardRef((props, ref) => {
40
40
  const [{ selectedItem, items = [] }, setItems] = useState(() => updateItems({ options, value, currentItems: [], selectedItem: undefined }));
41
41
  const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: selectedOptionFormatter(selectedItem), selectedOptionFormatter }));
42
42
  const prevSelectedItem = useRef(selectedItem);
43
+ const prefixSettings = usePrefix({ prefix, disabled });
44
+ const postfixSettings = usePostfix({ postfix, disabled });
43
45
  useLayoutEffect(() => {
44
46
  setItems(({ selectedItem }) => updateItems({ options, value, selectedItem }));
45
47
  }, [options, value]);
@@ -64,7 +66,7 @@ export const FieldSelectSingle = forwardRef((props, ref) => {
64
66
  }
65
67
  }, [required, setOpen, setValue]);
66
68
  const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
67
- const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
69
+ const { postfixButtons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
68
70
  readonly,
69
71
  size,
70
72
  showClearButton: showClearButton && !disabled && !readonly && value !== undefined,
@@ -126,7 +128,7 @@ export const FieldSelectSingle = forwardRef((props, ref) => {
126
128
  mode: 'single',
127
129
  value: value,
128
130
  onChange: handleSelectionChange,
129
- }, size: size, open: open, onOpenChange: handleOpenChange, trigger: 'click', triggerElemRef: localRef, untouchableScrollbars: untouchableScrollbars, 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({
131
+ }, size: size, open: open, onOpenChange: handleOpenChange, trigger: 'click', triggerElemRef: localRef, untouchableScrollbars: untouchableScrollbars, 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 || prefixSettings.show) && (_jsxs(_Fragment, { children: [prefixIcon, prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })] })), 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
- }) }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) })) })));
133
+ }) }), _jsxs("div", { className: styles.postfix, children: [postfixButtons, postfixSettings.show && postfixSettings.render({ key: postfixSettings.id }), _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) })) })));
132
134
  });
@@ -18,7 +18,7 @@ type UseButtonsProps = {
18
18
  valueToCopy?: string;
19
19
  };
20
20
  export declare function useButtons({ readonly, showClearButton, showCopyButton, size, onClear, inputRef, valueToCopy, }: UseButtonsProps): {
21
- buttons: import("react/jsx-runtime").JSX.Element;
21
+ postfixButtons: import("react/jsx-runtime").JSX.Element | undefined;
22
22
  inputKeyDownNavigationHandler: KeyboardEventHandler<HTMLInputElement>;
23
23
  buttonsRefs: (Element | null)[];
24
24
  };
@@ -42,14 +42,14 @@ export function useButtons({ readonly, showClearButton, showCopyButton, size, on
42
42
  size,
43
43
  valueToCopy,
44
44
  });
45
- const { onInputKeyDown: inputKeyDownNavigationHandler, buttons } = useButtonNavigation({
45
+ const { onInputKeyDown: inputKeyDownNavigationHandler, postfixButtons } = useButtonNavigation({
46
46
  inputRef,
47
- buttons: useMemo(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
47
+ postfixButtons: useMemo(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
48
48
  onButtonKeyDown: undefined,
49
49
  readonly,
50
50
  submitKeys: ['Enter', 'Space', 'Tab'],
51
51
  });
52
- return { buttons, inputKeyDownNavigationHandler, buttonsRefs };
52
+ return { postfixButtons, inputKeyDownNavigationHandler, buttonsRefs };
53
53
  }
54
54
  export function useSearchInput({ value, onChange, defaultValue, selectedOptionFormatter, resetSearchOnOptionSelection = true, }) {
55
55
  const [inputValue = '', setInputValue] = useValueControl({ value, onChange, defaultValue });
@@ -1,4 +1,4 @@
1
- import { ReactElement } from 'react';
1
+ import { ReactElement, ReactNode } from 'react';
2
2
  import { InputPrivateProps } from '@snack-uikit/input-private';
3
3
  import { AccordionItemProps, BaseItemProps, DroplistProps, GroupItemProps, ItemContentProps, NextListItemProps, SelectionMultipleState, SelectionSingleState } from '@snack-uikit/list';
4
4
  import { TagProps } from '@snack-uikit/tag';
@@ -34,6 +34,10 @@ export type SearchState = {
34
34
  export type FieldSelectPrivateProps = InputProps & WrapperProps & {
35
35
  options: OptionProps[];
36
36
  loading?: boolean;
37
+ /** Произвольный префикс для поля */
38
+ prefix?: ReactNode;
39
+ /** Произвольный постфикс для поля */
40
+ postfix?: ReactNode;
37
41
  };
38
42
  type FiledSelectCommonProps = WithSupportProps<{
39
43
  options: OptionProps[];
@@ -1,4 +1,4 @@
1
- import { ReactElement } from 'react';
1
+ import { ReactElement, ReactNode } from 'react';
2
2
  import { InputPrivateProps } from '@snack-uikit/input-private';
3
3
  import { SliderProps as SliderComponentProps } from '@snack-uikit/slider';
4
4
  import { WithSupportProps } from '@snack-uikit/utils';
@@ -15,9 +15,13 @@ type FieldSliderOwnProps = {
15
15
  textInputFormatter?: TextInputFormatter;
16
16
  /** Отвязать текстовое поле от значений на линейке */
17
17
  unbindInputFromMarks?: boolean;
18
+ /** Произвольный префикс для поля */
19
+ prefix?: ReactNode;
20
+ /** Произвольный постфикс для поля */
21
+ postfix?: ReactNode;
18
22
  };
19
23
  export type FieldSliderProps = WithSupportProps<FieldSliderOwnProps & SliderProps & WrapperProps>;
20
24
  export declare const FieldSlider: import("react").ForwardRefExoticComponent<{
21
25
  'data-test-id'?: string;
22
- } & import("react").AriaAttributes & FieldSliderOwnProps & Pick<InputPrivateProps, "disabled" | "readonly" | "id" | "name" | "onFocus" | "onBlur"> & Pick<SliderComponentProps, "onChange" | "value" | "range" | "tipFormatter"> & Required<Pick<SliderComponentProps, "max" | "min" | "step" | "marks">> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
26
+ } & import("react").AriaAttributes & FieldSliderOwnProps & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name"> & Pick<SliderComponentProps, "value" | "onChange" | "range" | "tipFormatter"> & Required<Pick<SliderComponentProps, "max" | "min" | "step" | "marks">> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
23
27
  export {};
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import mergeRefs from 'merge-refs';
14
14
  import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
15
15
  import { InputPrivate, SIZE } from '@snack-uikit/input-private';
@@ -17,7 +17,7 @@ import { Slider } from '@snack-uikit/slider';
17
17
  import { extractSupportProps, useEventHandler } from '@snack-uikit/utils';
18
18
  import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
19
19
  import { FieldContainerPrivate } from '../../helperComponents';
20
- import { useValueControl } from '../../hooks';
20
+ import { usePostfix, usePrefix, useValueControl } from '../../hooks';
21
21
  import { FieldDecorator } from '../FieldDecorator';
22
22
  import { generateAllowedValues, getClosestMark, getTextFieldValue, isMarkObject } from './helpers';
23
23
  import styles from './styles.module.css';
@@ -31,7 +31,16 @@ const getDefaultValue = (range, min, max, value) => {
31
31
  return value !== null && value !== void 0 ? value : min;
32
32
  };
33
33
  export const FieldSlider = forwardRef((_a, ref) => {
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, caption, hint, showHintIcon, size = SIZE.S, postfixIcon, textInputFormatter, unbindInputFromMarks } = _a, rest = __rest(_a, ["id", "name", "min", "max", "step", "marks", "showScaleBar", "value", "range", "disabled", "readonly", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "postfixIcon", "textInputFormatter", "unbindInputFromMarks"]);
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, caption, hint, showHintIcon, size = SIZE.S, textInputFormatter, unbindInputFromMarks, postfixIcon, prefix, postfix } = _a, rest = __rest(_a, ["id", "name", "min", "max", "step", "marks", "showScaleBar", "value", "range", "disabled", "readonly", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "textInputFormatter", "unbindInputFromMarks", "postfixIcon", "prefix", "postfix"]);
35
+ const [value = getDefaultValue(range, min, max, valueProp), onChange] = useValueControl({
36
+ value: valueProp,
37
+ defaultValue: getDefaultValue(range, min, max, valueProp),
38
+ onChange: onChangeProp,
39
+ });
40
+ const [textFieldInputValue, setTextFieldInputValue] = useState(getTextFieldValue(value, textInputFormatter));
41
+ const localRef = useRef(null);
42
+ const prefixSettings = usePrefix({ prefix, disabled });
43
+ const postfixSettings = usePostfix({ postfix, disabled });
35
44
  const getMarkValue = useCallback((key) => {
36
45
  const mark = marks[key];
37
46
  if (isMarkObject(mark)) {
@@ -40,13 +49,6 @@ export const FieldSlider = forwardRef((_a, ref) => {
40
49
  return mark;
41
50
  }, [marks]);
42
51
  const hasMarksEqualToValues = useMemo(() => Object.keys(marks).every(key => key === getMarkValue(key)), [getMarkValue, marks]);
43
- const [value = getDefaultValue(range, min, max, valueProp), onChange] = useValueControl({
44
- value: valueProp,
45
- defaultValue: getDefaultValue(range, min, max, valueProp),
46
- onChange: onChangeProp,
47
- });
48
- const [textFieldInputValue, setTextFieldInputValue] = useState(getTextFieldValue(value, textInputFormatter));
49
- const localRef = useRef(null);
50
52
  const onTextFieldChange = (textFieldValue) => {
51
53
  const numValue = parseInt(textFieldValue);
52
54
  if (textFieldValue && Number.isNaN(numValue)) {
@@ -146,5 +148,5 @@ export const FieldSlider = forwardRef((_a, ref) => {
146
148
  useEffect(() => {
147
149
  handleTextValueChange();
148
150
  }, [marks, min, max, handleTextValueChange]);
149
- return (_jsxs(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, disabled: disabled, required: required, caption: caption, hint: hint, showHintIcon: showHintIcon, readonly: readonly, size: size }, extractSupportProps(rest), { children: [_jsx(FieldContainerPrivate, { className: styles.fieldContainer, size: size, validationState: VALIDATION_STATE.Default, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: localRef, postfix: postfixIcon, children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: textFieldInputValue, onChange: range ? undefined : onTextFieldChange, onFocus: onFocus, onBlur: range ? onBlur : onTextFieldBlur, onKeyDown: handleTextFieldKeyChange, disabled: disabled, readonly: range ? true : readonly, type: 'text', id: id, name: name, "data-test-id": 'field-slider__input' }) }), _jsx("div", { className: styles.sliderWrapper, children: _jsx("div", { className: styles.slider, "data-size": size, children: _jsx(Slider, { range: range, min: min, max: max, step: step, value: value, onChange: onChange, marks: showScaleBar ? marks : undefined, disabled: readonly || disabled, "data-test-id": 'field-slider__slider' }) }) })] })));
151
+ return (_jsxs(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, disabled: disabled, required: required, caption: caption, hint: hint, showHintIcon: showHintIcon, readonly: readonly, size: size }, extractSupportProps(rest), { children: [_jsx(FieldContainerPrivate, { className: styles.fieldContainer, size: size, validationState: VALIDATION_STATE.Default, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: localRef, prefix: prefixSettings.show && prefixSettings.render({ key: prefixSettings.id }), postfix: _jsxs(_Fragment, { children: [postfixSettings.show && postfixSettings.render({ key: postfixSettings.id }), postfixIcon] }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: textFieldInputValue, onChange: range ? undefined : onTextFieldChange, onFocus: onFocus, onBlur: range ? onBlur : onTextFieldBlur, onKeyDown: handleTextFieldKeyChange, disabled: disabled, readonly: range ? true : readonly, type: 'text', id: id, name: name, "data-test-id": 'field-slider__input' }) }), _jsx("div", { className: styles.sliderWrapper, children: _jsx("div", { className: styles.slider, "data-size": size, children: _jsx(Slider, { range: range, min: min, max: max, step: step, value: value, onChange: onChange, marks: showScaleBar ? marks : undefined, disabled: readonly || disabled, "data-test-id": 'field-slider__slider' }) }) })] })));
150
152
  });
@@ -1,4 +1,4 @@
1
- import { ChangeEvent } from 'react';
1
+ import { ChangeEvent, ReactNode } from 'react';
2
2
  import { InputPrivateProps } from '@snack-uikit/input-private';
3
3
  import { WithSupportProps } from '@snack-uikit/utils';
4
4
  import { FieldDecoratorProps } from '../FieldDecorator';
@@ -13,6 +13,10 @@ type FieldStepperOwnProps = {
13
13
  step?: number;
14
14
  /** Можно ли вводить c клавиатуры числа, выходящие за пределы min/max */
15
15
  allowMoreThanLimits?: boolean;
16
+ /** Произвольный префикс для поля */
17
+ prefix?: ReactNode;
18
+ /** Произвольный постфикс для поля */
19
+ postfix?: ReactNode;
16
20
  };
17
21
  export type FieldStepperProps = WithSupportProps<FieldStepperOwnProps & InputProps & WrapperProps>;
18
22
  export declare const FieldStepper: import("react").ForwardRefExoticComponent<{
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { jsx as _jsx } from "react/jsx-runtime";
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import mergeRefs from 'merge-refs';
14
14
  import { forwardRef, useEffect, useRef, useState, } from 'react';
15
15
  import { ButtonFunction } from '@snack-uikit/button';
@@ -20,7 +20,7 @@ import { Tooltip } from '@snack-uikit/tooltip';
20
20
  import { extractSupportProps } from '@snack-uikit/utils';
21
21
  import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
22
22
  import { FieldContainerPrivate } from '../../helperComponents';
23
- import { useValueControl } from '../../hooks';
23
+ import { usePostfix, usePrefix, useValueControl } from '../../hooks';
24
24
  import { getValidationState } from '../../utils/getValidationState';
25
25
  import { FieldDecorator } from '../FieldDecorator';
26
26
  import styles from './styles.module.css';
@@ -35,7 +35,7 @@ const getDefaultValue = (min, max) => {
35
35
  return 0;
36
36
  };
37
37
  export const FieldStepper = forwardRef((_a, ref) => {
38
- var { id, name, value: valueProp, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY, step = 1, disabled = false, readonly = false, allowMoreThanLimits = true, onChange: onChangeProp, onFocus, onBlur, className, label, labelTooltip, labelTooltipPlacement, required = false, caption, hint, showHintIcon, size = SIZE.S, validationState = VALIDATION_STATE.Default, error } = _a, rest = __rest(_a, ["id", "name", "value", "min", "max", "step", "disabled", "readonly", "allowMoreThanLimits", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "validationState", "error"]);
38
+ var { id, name, value: valueProp, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY, step = 1, disabled = false, readonly = false, allowMoreThanLimits = true, onChange: onChangeProp, onFocus, onBlur, className, label, labelTooltip, labelTooltipPlacement, required = false, caption, hint, showHintIcon, size = SIZE.S, validationState = VALIDATION_STATE.Default, error, prefix, postfix } = _a, rest = __rest(_a, ["id", "name", "value", "min", "max", "step", "disabled", "readonly", "allowMoreThanLimits", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "validationState", "error", "prefix", "postfix"]);
39
39
  const { t } = useLocale('Fields');
40
40
  const [value = 0, setValue] = useValueControl({
41
41
  value: valueProp,
@@ -50,6 +50,8 @@ export const FieldStepper = forwardRef((_a, ref) => {
50
50
  const plusButtonRef = useRef(null);
51
51
  const isMinusButtonDisabled = (typeof min === 'number' && value <= min) || readonly || disabled;
52
52
  const isPlusButtonDisabled = (typeof max === 'number' && value >= max) || readonly || disabled;
53
+ const prefixSettings = usePrefix({ prefix, disabled });
54
+ const postfixSettings = usePostfix({ postfix, disabled });
53
55
  const fieldValidationState = getValidationState({ validationState, error });
54
56
  const adjustValue = (value) => {
55
57
  setValue(value);
@@ -124,5 +126,5 @@ export const FieldStepper = forwardRef((_a, ref) => {
124
126
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
125
127
  }
126
128
  };
127
- return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, caption: caption, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, validationState: fieldValidationState, error: error }, extractSupportProps(rest), { children: _jsx(Tooltip, { tip: tooltip, open: allowMoreThanLimits ? false : tooltipOpen, "data-test-id": 'field-stepper__limit-tooltip', children: _jsx(FieldContainerPrivate, { size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: inputRef, prefix: _jsx(ButtonFunction, { tabIndex: -1, ref: minusButtonRef, size: 'xs', className: styles.button, icon: _jsx(MinusSVG, {}), onClick: handleMinusButtonClick, onKeyDown: handleMinusButtonKeyDown, disabled: isMinusButtonDisabled, "data-test-id": 'field-stepper__minus-button' }), postfix: _jsx(ButtonFunction, { ref: plusButtonRef, tabIndex: -1, size: 'xs', className: styles.button, icon: _jsx(PlusSVG, {}), onClick: handlePlusButtonClick, onKeyDown: handlePlusButtonKeyDown, disabled: isPlusButtonDisabled, "data-test-id": 'field-stepper__plus-button' }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, inputRef), className: styles.stepper, "data-size": size, value: String(value), tabIndex: 0, onKeyDown: handleInputKeyDown, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, disabled: disabled, readonly: readonly, type: 'number', id: id, name: name, min: min, max: max, "data-test-id": 'field-stepper__input' }) }) }) })));
129
+ return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, caption: caption, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, validationState: fieldValidationState, error: error }, extractSupportProps(rest), { children: _jsx(Tooltip, { tip: tooltip, open: allowMoreThanLimits ? false : tooltipOpen, "data-test-id": 'field-stepper__limit-tooltip', children: _jsx(FieldContainerPrivate, { size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: inputRef, prefix: _jsxs(_Fragment, { children: [_jsx(ButtonFunction, { tabIndex: -1, ref: minusButtonRef, size: 'xs', className: styles.button, icon: _jsx(MinusSVG, {}), onClick: handleMinusButtonClick, onKeyDown: handleMinusButtonKeyDown, disabled: isMinusButtonDisabled, "data-test-id": 'field-stepper__minus-button' }), prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })] }), postfix: _jsxs(_Fragment, { children: [postfixSettings.show && postfixSettings.render({ key: postfixSettings.id }), _jsx(ButtonFunction, { ref: plusButtonRef, tabIndex: -1, size: 'xs', className: styles.button, icon: _jsx(PlusSVG, {}), onClick: handlePlusButtonClick, onKeyDown: handlePlusButtonKeyDown, disabled: isPlusButtonDisabled, "data-test-id": 'field-stepper__plus-button' })] }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, inputRef), className: styles.stepper, "data-size": size, value: String(value), tabIndex: 0, onKeyDown: handleInputKeyDown, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, disabled: disabled, readonly: readonly, type: 'number', id: id, name: name, min: min, max: max, "data-test-id": 'field-stepper__input' }) }) }) })));
128
130
  });
@@ -1,6 +1,7 @@
1
- import { ReactElement } from 'react';
1
+ import { ReactElement, ReactNode } from 'react';
2
2
  import { InputPrivateProps } from '@snack-uikit/input-private';
3
3
  import { WithSupportProps } from '@snack-uikit/utils';
4
+ import { Button } from '../../types';
4
5
  import { FieldDecoratorProps } from '../FieldDecorator';
5
6
  type InputProps = Pick<Partial<InputPrivateProps>, 'value' | 'onChange'> & Pick<InputPrivateProps, 'id' | 'name' | 'placeholder' | 'maxLength' | 'disabled' | 'readonly' | 'onFocus' | 'onBlur' | 'autoComplete'>;
6
7
  type WrapperProps = Pick<FieldDecoratorProps, 'className' | 'label' | 'labelTooltip' | 'required' | 'caption' | 'hint' | 'showHintIcon' | 'size' | 'validationState' | 'labelTooltipPlacement' | 'error'>;
@@ -16,9 +17,15 @@ type FieldTextOwnProps = {
16
17
  allowMoreThanMaxLength?: boolean;
17
18
  /** Иконка-префикс для поля */
18
19
  prefixIcon?: ReactElement;
20
+ /** Произвольный префикс для поля */
21
+ prefix?: ReactNode;
22
+ /** Произвольный постфикс для поля */
23
+ postfix?: ReactNode;
24
+ /** Кнопка действия внутри поля */
25
+ button?: Button;
19
26
  };
20
27
  export type FieldTextProps = WithSupportProps<FieldTextOwnProps & InputProps & WrapperProps>;
21
28
  export declare const FieldText: import("react").ForwardRefExoticComponent<{
22
29
  'data-test-id'?: string;
23
- } & import("react").AriaAttributes & FieldTextOwnProps & Pick<Partial<InputPrivateProps>, "onChange" | "value"> & Pick<InputPrivateProps, "disabled" | "readonly" | "id" | "name" | "onFocus" | "onBlur" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
30
+ } & import("react").AriaAttributes & FieldTextOwnProps & Pick<Partial<InputPrivateProps>, "value" | "onChange"> & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
24
31
  export {};