@true-engineering/true-react-common-ui-kit 4.0.0-alpha54 → 4.0.0-alpha61

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 (151) hide show
  1. package/README.md +1 -0
  2. package/dist/components/AddButton/AddButton.d.ts +1 -0
  3. package/dist/components/AddButton/AddButton.styles.d.ts +1 -1
  4. package/dist/components/Button/Button.styles.d.ts +1 -1
  5. package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
  6. package/dist/components/ControlWrapper/ControlWrapper.d.ts +1 -1
  7. package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +1 -1
  8. package/dist/components/CssBaseline/CssBaseline.styles.d.ts +1 -1
  9. package/dist/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.d.ts +1 -1
  10. package/dist/components/Description/Description.styles.d.ts +1 -1
  11. package/dist/components/FileInput/FileInput.styles.d.ts +1 -1
  12. package/dist/components/FileItem/FileItem.styles.d.ts +1 -1
  13. package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
  14. package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +2 -2
  15. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
  16. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +1 -1
  17. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.d.ts +1 -1
  18. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.d.ts +1 -1
  19. package/dist/components/FiltersPane/types.d.ts +2 -1
  20. package/dist/components/FlexibleTable/FlexibleTable.styles.d.ts +1 -1
  21. package/dist/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.d.ts +1 -1
  22. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +1 -3
  23. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.d.ts +1 -1
  24. package/dist/components/FloatDocActions/components/DocActions/DocActions.styles.d.ts +1 -1
  25. package/dist/components/IconButton/IconButton.styles.d.ts +1 -1
  26. package/dist/components/List/components/ListItem/ListItem.styles.d.ts +1 -1
  27. package/dist/components/Modal/Modal.styles.d.ts +1 -1
  28. package/dist/components/MoreMenu/MoreMenu.styles.d.ts +1 -1
  29. package/dist/components/MultiSelect/MultiSelect.styles.d.ts +1 -1
  30. package/dist/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.styles.d.ts +1 -1
  31. package/dist/components/MultiSelectList/MultiSelectList.styles.d.ts +1 -1
  32. package/dist/components/NewMoreMenu/NewMoreMenu.styles.d.ts +1 -1
  33. package/dist/components/Notification/Notification.styles.d.ts +1 -1
  34. package/dist/components/PhoneInput/PhoneInput.styles.d.ts +1 -1
  35. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.styles.d.ts +1 -1
  36. package/dist/components/RadioButton/RadioButton.styles.d.ts +1 -1
  37. package/dist/components/SearchInput/SearchInput.d.ts +1 -1
  38. package/dist/components/Select/Select.styles.d.ts +3 -3
  39. package/dist/components/Select/components/SelectList/SelectList.styles.d.ts +1 -1
  40. package/dist/components/Selector/Selector.styles.d.ts +1 -1
  41. package/dist/components/Status/Status.styles.d.ts +1 -1
  42. package/dist/components/Switch/Switch.d.ts +3 -2
  43. package/dist/components/Switch/Switch.styles.d.ts +3 -2
  44. package/dist/components/Switch/types.d.ts +3 -0
  45. package/dist/components/TextArea/TextArea.styles.d.ts +1 -1
  46. package/dist/components/TextButton/TextButton.styles.d.ts +1 -1
  47. package/dist/components/TextWithInfo/TextWithInfo.styles.d.ts +1 -1
  48. package/dist/components/TextWithTooltip/TextWithTooltip.d.ts +2 -0
  49. package/dist/components/TextWithTooltip/TextWithTooltip.styles.d.ts +1 -1
  50. package/dist/components/ThemedPreloader/ThemedPreloader.styles.d.ts +1 -1
  51. package/dist/components/ThemedPreloader/components/DotsPreloader/DotsPreloader.styles.d.ts +1 -1
  52. package/dist/components/Toaster/Toaster.styles.d.ts +1 -1
  53. package/dist/components/Tooltip/Tooltip.d.ts +3 -0
  54. package/dist/components/Tooltip/Tooltip.styles.d.ts +2 -1
  55. package/dist/components/Tooltip/types.d.ts +3 -0
  56. package/dist/components/WithMessages/WithMessages.styles.d.ts +1 -1
  57. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  58. package/dist/components/WithTooltip/WithTooltip.d.ts +2 -0
  59. package/dist/helpers/misc.d.ts +2 -0
  60. package/dist/hooks/index.d.ts +1 -0
  61. package/dist/hooks/use-intersection-ref.d.ts +2 -1
  62. package/dist/hooks/use-resize-ref.d.ts +7 -0
  63. package/dist/hooks/use-tweak-styles.d.ts +3 -2
  64. package/dist/theme/Provider.d.ts +2 -12
  65. package/dist/theme/common.d.ts +34 -4
  66. package/dist/theme/helpers.d.ts +3 -16
  67. package/dist/theme/index.d.ts +0 -2
  68. package/dist/theme/types.d.ts +9 -8
  69. package/dist/true-react-common-ui-kit.js +12132 -10
  70. package/dist/true-react-common-ui-kit.js.map +1 -1
  71. package/dist/true-react-common-ui-kit.umd.cjs +2 -10
  72. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  73. package/dist/types.d.ts +3 -3
  74. package/package.json +1 -3
  75. package/src/components/AccountInfo/AccountInfo.tsx +2 -3
  76. package/src/components/AddButton/AddButton.tsx +3 -5
  77. package/src/components/Button/Button.tsx +76 -77
  78. package/src/components/CloseButton/CloseButton.tsx +2 -4
  79. package/src/components/Colors/Colors.stories.tsx +3 -2
  80. package/src/components/ControlWrapper/ControlWrapper.tsx +2 -2
  81. package/src/components/CssBaseline/CssBaseline.styles.ts +2 -0
  82. package/src/components/CssBaseline/CssBaseline.tsx +2 -3
  83. package/src/components/DateInput/DateInput.tsx +59 -61
  84. package/src/components/DatePicker/DatePicker.tsx +259 -262
  85. package/src/components/Description/Description.tsx +2 -3
  86. package/src/components/FileInput/FileInput.tsx +87 -95
  87. package/src/components/FileItem/FileItem.tsx +2 -4
  88. package/src/components/FiltersPane/FiltersPane.stories.tsx +3 -0
  89. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.tsx +2 -3
  90. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +6 -3
  91. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +3 -2
  92. package/src/components/FiltersPane/types.ts +2 -0
  93. package/src/components/FlexibleTable/FlexibleTable.styles.ts +1 -0
  94. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.ts +1 -0
  95. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.tsx +5 -2
  96. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +9 -7
  97. package/src/components/IconButton/IconButton.tsx +44 -48
  98. package/src/components/Input/Input.tsx +26 -24
  99. package/src/components/Input/InputBase.tsx +183 -187
  100. package/src/components/List/List.tsx +2 -3
  101. package/src/components/List/components/ListItem/ListItem.tsx +2 -4
  102. package/src/components/Modal/Modal.tsx +2 -4
  103. package/src/components/MoreMenu/MoreMenu.tsx +2 -4
  104. package/src/components/MultiSelect/MultiSelect.tsx +2 -4
  105. package/src/components/NewMoreMenu/NewMoreMenu.tsx +2 -4
  106. package/src/components/Notification/Notification.tsx +2 -3
  107. package/src/components/NumberInput/NumberInput.tsx +91 -93
  108. package/src/components/PhoneInput/PhoneInput.tsx +2 -3
  109. package/src/components/SearchInput/SearchInput.tsx +20 -19
  110. package/src/components/Select/Select.tsx +1 -1
  111. package/src/components/Selector/Selector.tsx +4 -6
  112. package/src/components/SmartInput/SmartInput.tsx +85 -87
  113. package/src/components/Status/Status.tsx +5 -4
  114. package/src/components/Switch/Switch.styles.ts +21 -13
  115. package/src/components/Switch/Switch.tsx +11 -6
  116. package/src/components/Switch/types.ts +5 -0
  117. package/src/components/TextArea/TextArea.tsx +128 -130
  118. package/src/components/TextButton/TextButton.tsx +68 -69
  119. package/src/components/TextWithInfo/TextWithInfo.tsx +2 -4
  120. package/src/components/TextWithTooltip/TextWithTooltip.tsx +6 -4
  121. package/src/components/ThemedPreloader/ThemedPreloader.tsx +2 -4
  122. package/src/components/Toaster/Toaster.tsx +2 -4
  123. package/src/components/Tooltip/Tooltip.stories.tsx +10 -0
  124. package/src/components/Tooltip/Tooltip.styles.ts +2 -1
  125. package/src/components/Tooltip/Tooltip.tsx +12 -5
  126. package/src/components/Tooltip/types.ts +5 -0
  127. package/src/components/WithMessages/WithMessages.tsx +41 -40
  128. package/src/components/WithTooltip/WithTooltip.tsx +4 -0
  129. package/src/helpers/misc.ts +6 -0
  130. package/src/hooks/index.ts +1 -0
  131. package/src/hooks/use-intersection-ref.ts +24 -6
  132. package/src/hooks/use-latest-ref.ts +6 -2
  133. package/src/hooks/use-resize-ref.ts +35 -0
  134. package/src/hooks/use-tweak-styles.ts +14 -51
  135. package/src/theme/Provider.tsx +4 -21
  136. package/src/theme/common.ts +33 -36
  137. package/src/theme/helpers.ts +50 -42
  138. package/src/theme/index.ts +0 -2
  139. package/src/theme/types.ts +13 -10
  140. package/src/types.ts +3 -3
  141. package/dist/theme/create-themed-styles.d.ts +0 -2
  142. package/dist/theme/true-jss/ThemedStylesManager.d.ts +0 -18
  143. package/dist/theme/true-jss/TweakStylesManager.d.ts +0 -34
  144. package/dist/theme/true-jss/index.d.ts +0 -2
  145. package/dist/theme/true-jss/jss-context.d.ts +0 -9
  146. package/dist/true-react-common-ui-kit.css +0 -756
  147. package/src/theme/create-themed-styles.ts +0 -78
  148. package/src/theme/true-jss/ThemedStylesManager.ts +0 -93
  149. package/src/theme/true-jss/TweakStylesManager.ts +0 -156
  150. package/src/theme/true-jss/index.ts +0 -2
  151. package/src/theme/true-jss/jss-context.tsx +0 -34
@@ -28,107 +28,105 @@ export interface INumberInputProps extends Omit<IInputProps, 'value' | 'onChange
28
28
  onChange: (value: number | undefined, event?: IChangeInputEvent) => void;
29
29
  }
30
30
 
31
- export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
32
- (
33
- {
34
- value,
35
- canBeFloat = false,
36
- canBeNegative = false,
37
- defaultValue,
38
- precision = 3,
39
- intPartPrecision = 7,
40
- onChange,
41
- onBlur,
42
- min,
43
- max,
44
- ...props
45
- },
46
- ref,
47
- ) => {
48
- const [showedValue, setShowedValue] = useState(() =>
49
- formatNumberWithDefault(value, defaultValue),
50
- );
31
+ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(function NumberInput(
32
+ {
33
+ value,
34
+ canBeFloat = false,
35
+ canBeNegative = false,
36
+ defaultValue,
37
+ precision = 3,
38
+ intPartPrecision = 7,
39
+ onChange,
40
+ onBlur,
41
+ min,
42
+ max,
43
+ ...props
44
+ },
45
+ ref,
46
+ ) {
47
+ const [showedValue, setShowedValue] = useState(() =>
48
+ formatNumberWithDefault(value, defaultValue),
49
+ );
51
50
 
52
- // специальный костыль для обработки Delete - т.к. без него каретка будет работать неправильно при удалении пробелов
53
- const [isDeleteForwardAction, setIsDeleteForwardAction] = useState(false);
51
+ // специальный костыль для обработки Delete - т.к. без него каретка будет работать неправильно при удалении пробелов
52
+ const [isDeleteForwardAction, setIsDeleteForwardAction] = useState(false);
54
53
 
55
- const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
56
- setIsDeleteForwardAction(event.key === 'Delete');
57
- };
54
+ const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
55
+ setIsDeleteForwardAction(event.key === 'Delete');
56
+ };
58
57
 
59
- const setShowedValueWithDefault = (v: string) => {
60
- setShowedValue(isStringNotEmpty(v) ? v : formatNumber(defaultValue));
61
- };
58
+ const setShowedValueWithDefault = (v: string) => {
59
+ setShowedValue(isStringNotEmpty(v) ? v : formatNumber(defaultValue));
60
+ };
62
61
 
63
- const handleChange = async (inputValue: string, event: IChangeInputEvent): Promise<void> => {
64
- const oldValue = showedValue;
65
- const target = event.target as HTMLInputElement;
66
- const defaultCaretPos = target.selectionStart ?? 0;
67
- const numString = removeStringFormat(inputValue);
62
+ const handleChange = async (inputValue: string, event: IChangeInputEvent): Promise<void> => {
63
+ const oldValue = showedValue;
64
+ const target = event.target as HTMLInputElement;
65
+ const defaultCaretPos = target.selectionStart ?? 0;
66
+ const numString = removeStringFormat(inputValue);
68
67
 
69
- if (numString === '') {
70
- onChange(undefined);
71
- // не убирать - ломается каретка
72
- setShowedValue('');
73
- return;
74
- }
68
+ if (numString === '') {
69
+ onChange(undefined);
70
+ // не убирать - ломается каретка
71
+ setShowedValue('');
72
+ return;
73
+ }
75
74
 
76
- const numberRegexp = new RegExp(
77
- constructRegExp({
78
- precision,
79
- intPartPrecision,
80
- canBeNegative,
81
- canBeFloat,
82
- }),
83
- );
75
+ const numberRegexp = new RegExp(
76
+ constructRegExp({
77
+ precision,
78
+ intPartPrecision,
79
+ canBeNegative,
80
+ canBeFloat,
81
+ }),
82
+ );
84
83
 
85
- if (!numberRegexp.test(numString)) {
86
- await setShowedValue(oldValue);
87
- setCaretPosition(target, defaultCaretPos - 1);
88
- return;
89
- }
84
+ if (!numberRegexp.test(numString)) {
85
+ await setShowedValue(oldValue);
86
+ setCaretPosition(target, defaultCaretPos - 1);
87
+ return;
88
+ }
90
89
 
91
- const hasDot = canBeFloat && /^[-]*[\d\s]*[.,]$/.test(inputValue);
92
- const formattedValue = formatStringNumber(numString);
93
- const newValue = hasDot ? `${formattedValue}.` : formattedValue;
94
- await setShowedValue(newValue);
95
- setCaretPosition(
96
- target,
97
- getNewCaretPosition(defaultCaretPos, oldValue, newValue, isDeleteForwardAction),
98
- );
99
- };
90
+ const hasDot = canBeFloat && /^[-]*[\d\s]*[.,]$/.test(inputValue);
91
+ const formattedValue = formatStringNumber(numString);
92
+ const newValue = hasDot ? `${formattedValue}.` : formattedValue;
93
+ await setShowedValue(newValue);
94
+ setCaretPosition(
95
+ target,
96
+ getNewCaretPosition(defaultCaretPos, oldValue, newValue, isDeleteForwardAction),
97
+ );
98
+ };
100
99
 
101
- const handleBlur = (event: FocusEvent<HTMLInputElement>): void => {
102
- const val = event.currentTarget.value;
103
- const num = stringToNumber(val);
104
- const newValue = num !== undefined ? getNumberInRange(num, min, max) : undefined;
105
- if (newValue !== value) {
106
- onChange(newValue);
107
- } else {
108
- setShowedValueWithDefault(formatNumber(value));
109
- }
110
- if (onBlur !== undefined) {
111
- onBlur(event);
112
- }
113
- };
100
+ const handleBlur = (event: FocusEvent<HTMLInputElement>): void => {
101
+ const val = event.currentTarget.value;
102
+ const num = stringToNumber(val);
103
+ const newValue = num !== undefined ? getNumberInRange(num, min, max) : undefined;
104
+ if (newValue !== value) {
105
+ onChange(newValue);
106
+ } else {
107
+ setShowedValueWithDefault(formatNumber(value));
108
+ }
109
+ if (onBlur !== undefined) {
110
+ onBlur(event);
111
+ }
112
+ };
114
113
 
115
- useDidMountEffect(() => {
116
- if (value !== undefined) {
117
- setShowedValueWithDefault(formatNumber(value));
118
- } else {
119
- setShowedValue(formatNumber(value));
120
- }
121
- }, [value]);
114
+ useDidMountEffect(() => {
115
+ if (value !== undefined) {
116
+ setShowedValueWithDefault(formatNumber(value));
117
+ } else {
118
+ setShowedValue(formatNumber(value));
119
+ }
120
+ }, [value]);
122
121
 
123
- return (
124
- <Input
125
- value={showedValue}
126
- onChange={handleChange}
127
- onBlur={handleBlur}
128
- onKeyDown={handleKeyDown}
129
- ref={ref}
130
- {...props}
131
- />
132
- );
133
- },
134
- );
122
+ return (
123
+ <Input
124
+ value={showedValue}
125
+ onChange={handleChange}
126
+ onBlur={handleBlur}
127
+ onKeyDown={handleKeyDown}
128
+ ref={ref}
129
+ {...props}
130
+ />
131
+ );
132
+ });
@@ -1,8 +1,7 @@
1
1
  import { FC, FocusEvent, useMemo, useRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataTestId, getTestId } from '@true-engineering/true-react-platform-helpers';
3
+ import { addDataAttributes, getTestId } from '@true-engineering/true-react-platform-helpers';
4
4
  import {
5
- addDataAttributes,
6
5
  findCountryByCode,
7
6
  getCountryCodeFromPhone,
8
7
  getFullPhone,
@@ -157,7 +156,7 @@ export const PhoneInput: FC<IPhoneInputProps> = ({
157
156
  useOnClickOutsideWithRef(list, handleClose, inputWrapper);
158
157
 
159
158
  return (
160
- <div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
159
+ <div className={classes.root} {...addDataAttributes(data, testId)}>
161
160
  <div
162
161
  className={clsx(classes.countrySelectContainer, {
163
162
  [classes.disabledCountrySelect]: isDisabled,
@@ -10,23 +10,24 @@ export type ISearchInputProps = Omit<
10
10
  > &
11
11
  ICommonProps<ISearchInputStyles>;
12
12
 
13
- export const SearchInput = forwardRef<HTMLInputElement, ISearchInputProps>(
14
- ({ isClearable = true, tweakStyles, ...props }, ref) => {
15
- const tweakInputStyles = useTweakStyles({
16
- innerStyles: inputStyles,
17
- tweakStyles,
18
- className: 'tweakInput',
19
- currentComponentName: 'SearchInput',
20
- });
13
+ export const SearchInput = forwardRef<HTMLInputElement, ISearchInputProps>(function SearchInput(
14
+ { isClearable = true, tweakStyles, ...props },
15
+ ref,
16
+ ) {
17
+ const tweakInputStyles = useTweakStyles({
18
+ innerStyles: inputStyles,
19
+ tweakStyles,
20
+ className: 'tweakInput',
21
+ currentComponentName: 'SearchInput',
22
+ });
21
23
 
22
- return (
23
- <Input
24
- ref={ref}
25
- startIcon="search"
26
- isClearable={isClearable}
27
- tweakStyles={tweakInputStyles}
28
- {...props}
29
- />
30
- );
31
- },
32
- );
24
+ return (
25
+ <Input
26
+ ref={ref}
27
+ startIcon="search"
28
+ isClearable={isClearable}
29
+ tweakStyles={tweakInputStyles}
30
+ {...props}
31
+ />
32
+ );
33
+ });
@@ -496,7 +496,7 @@ export function Select<Value>(
496
496
  const popperData = useDropdown({
497
497
  isOpen,
498
498
  onDropdownClose: handleListClose,
499
- referenceElement: input.current?.parentElement ?? inputWrapper.current,
499
+ referenceElement: inputWrapper.current,
500
500
  dropdownElement: list.current,
501
501
  options: dropdownOptions,
502
502
  dependenciesForPositionUpdating: [inputProps.isLoading, filteredOptions.length],
@@ -2,12 +2,11 @@ import { useEffect, useRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {
4
4
  addDataTestId,
5
- getTestId,
5
+ addDataAttributes,
6
6
  hasDuplicates,
7
7
  isNotEmpty,
8
8
  isReactNodeNotEmpty,
9
9
  } from '@true-engineering/true-react-platform-helpers';
10
- import { addDataAttributes } from '../../helpers';
11
10
  import { ICommonProps } from '../../types';
12
11
  import { renderIcon } from '../Icon';
13
12
  import { ISelectorOption, ISelectorValue } from './types';
@@ -77,8 +76,7 @@ export function Selector<V extends ISelectorValue>({
77
76
  [classes.autoWidth]: hasSameOptionsWidth,
78
77
  })}
79
78
  ref={listRef}
80
- {...addDataTestId(testId)}
81
- {...addDataAttributes(data)}
79
+ {...addDataAttributes(data, testId)}
82
80
  >
83
81
  {isNotEmpty(activeElementData) && (
84
82
  <div className={classes.line} style={getSelectorLineStyle(activeElementData)} />
@@ -90,7 +88,7 @@ export function Selector<V extends ISelectorValue>({
90
88
  const isActiveOption = option.value === value;
91
89
 
92
90
  return (
93
- <div key={optionId} className={classes.optionWrapper} {...addDataTestId(testId)}>
91
+ <div key={optionId} className={classes.optionWrapper}>
94
92
  <button
95
93
  type="button"
96
94
  className={clsx(classes.option, classes[size], {
@@ -99,7 +97,7 @@ export function Selector<V extends ISelectorValue>({
99
97
  })}
100
98
  disabled={isDisabledOption}
101
99
  onClick={!isDisabledOption ? () => onChange(option.value) : undefined}
102
- {...addDataTestId(getTestId(testId, optionId))}
100
+ {...addDataTestId(testId, optionId)}
103
101
  >
104
102
  {isReactNodeNotEmpty(option.icon) && (
105
103
  <div className={classes.optionIcon}>{renderIcon(option.icon)}</div>
@@ -26,91 +26,89 @@ export interface ISmartInputProps extends Omit<IInputProps, 'onChange'> {
26
26
  ) => void;
27
27
  }
28
28
 
29
- export const SmartInput = forwardRef<HTMLInputElement, ISmartInputProps>(
30
- (
31
- {
32
- value = '',
33
- smartType = 'default',
34
- regExp,
35
- maxLength,
36
- isUpperCase = false,
37
- isTransliterationEnabled = true,
38
- onChange,
39
- ...rest
40
- },
41
- ref,
42
- ) => {
43
- const inputRef = useRef<HTMLInputElement>(null);
44
- const mergedRef = useMergedRefs([ref, inputRef]);
45
-
46
- const regex = regExp || SMART_INPUT_REGEX_MAP[smartType];
47
-
48
- const getUpperCaseIfNeeded = (str: string) => (isUpperCase ? str.toUpperCase() : str);
49
-
50
- const updateCaretPosition = (position: number | null, newValue: string) => {
51
- const input = inputRef.current;
52
- if (isNotEmpty(input) && input.type !== 'email') {
53
- // Нужно для того, чтобы после ререндера позиция каретки не сбросилась
54
- input.value = newValue;
55
- input.setSelectionRange(position, position);
56
- }
57
- };
58
-
59
- const handleChange = async (str: string, event: IChangeInputEvent) => {
60
- const isValid = regex.test(str);
61
-
62
- const charactersMap = smartType === 'email' ? EmailCharactersMap : CharactersMap;
63
- const newValue = getUpperCaseIfNeeded(
64
- isValid ? str : mapSymbols(str, regex, charactersMap, isTransliterationEnabled),
65
- );
66
-
67
- onChange(newValue, { rawValue: str, isValid }, event);
68
-
69
- const input = inputRef.current;
70
- if (isNotEmpty(input)) {
71
- const start = input.selectionStart;
72
- updateCaretPosition(isEmpty(start) || newValue !== value ? start : start - 1, newValue);
73
- }
74
- };
75
-
76
- const handlePaste = async (event: ClipboardEvent<HTMLInputElement>) => {
77
- event.preventDefault();
78
-
79
- const str = event.clipboardData.getData('text/plain').split('').join('');
80
-
81
- const input = event.currentTarget;
82
- const selectionStart = input.selectionStart ?? 0;
83
- const selectionEnd = input.selectionEnd ?? 0;
84
-
85
- const isValid = regex.test(str);
86
-
87
- let mappedValue = isValid
88
- ? str
89
- : mapSymbols(str, regex, TransliterationMap, isTransliterationEnabled);
90
-
91
- const newValueLength = mappedValue.length + value.length - (selectionEnd - selectionStart);
92
-
93
- if (isNotEmpty(maxLength) && maxLength >= 0 && newValueLength > maxLength) {
94
- mappedValue = mappedValue.substring(0, mappedValue.length - (newValueLength - maxLength));
95
- }
96
-
97
- const newValue = getUpperCaseIfNeeded(
98
- `${value.substring(0, selectionStart)}${mappedValue}${value.substring(selectionEnd)}`,
99
- );
100
-
101
- onChange(newValue, { rawValue: str, isValid }, event);
102
- updateCaretPosition(selectionStart + mappedValue.length, newValue);
103
- };
104
-
105
- return (
106
- <Input
107
- {...rest}
108
- ref={mergedRef}
109
- value={value}
110
- maxLength={maxLength}
111
- onPaste={handlePaste}
112
- onChange={handleChange}
113
- />
114
- );
29
+ export const SmartInput = forwardRef<HTMLInputElement, ISmartInputProps>(function SmartInput(
30
+ {
31
+ value = '',
32
+ smartType = 'default',
33
+ regExp,
34
+ maxLength,
35
+ isUpperCase = false,
36
+ isTransliterationEnabled = true,
37
+ onChange,
38
+ ...rest
115
39
  },
116
- );
40
+ ref,
41
+ ) {
42
+ const inputRef = useRef<HTMLInputElement>(null);
43
+ const mergedRef = useMergedRefs([ref, inputRef]);
44
+
45
+ const regex = regExp || SMART_INPUT_REGEX_MAP[smartType];
46
+
47
+ const getUpperCaseIfNeeded = (str: string) => (isUpperCase ? str.toUpperCase() : str);
48
+
49
+ const updateCaretPosition = (position: number | null, newValue: string) => {
50
+ const input = inputRef.current;
51
+ if (isNotEmpty(input) && input.type !== 'email') {
52
+ // Нужно для того, чтобы после ререндера позиция каретки не сбросилась
53
+ input.value = newValue;
54
+ input.setSelectionRange(position, position);
55
+ }
56
+ };
57
+
58
+ const handleChange = async (str: string, event: IChangeInputEvent) => {
59
+ const isValid = regex.test(str);
60
+
61
+ const charactersMap = smartType === 'email' ? EmailCharactersMap : CharactersMap;
62
+ const newValue = getUpperCaseIfNeeded(
63
+ isValid ? str : mapSymbols(str, regex, charactersMap, isTransliterationEnabled),
64
+ );
65
+
66
+ onChange(newValue, { rawValue: str, isValid }, event);
67
+
68
+ const input = inputRef.current;
69
+ if (isNotEmpty(input)) {
70
+ const start = input.selectionStart;
71
+ updateCaretPosition(isEmpty(start) || newValue !== value ? start : start - 1, newValue);
72
+ }
73
+ };
74
+
75
+ const handlePaste = async (event: ClipboardEvent<HTMLInputElement>) => {
76
+ event.preventDefault();
77
+
78
+ const str = event.clipboardData.getData('text/plain').split('').join('');
79
+
80
+ const input = event.currentTarget;
81
+ const selectionStart = input.selectionStart ?? 0;
82
+ const selectionEnd = input.selectionEnd ?? 0;
83
+
84
+ const isValid = regex.test(str);
85
+
86
+ let mappedValue = isValid
87
+ ? str
88
+ : mapSymbols(str, regex, TransliterationMap, isTransliterationEnabled);
89
+
90
+ const newValueLength = mappedValue.length + value.length - (selectionEnd - selectionStart);
91
+
92
+ if (isNotEmpty(maxLength) && maxLength >= 0 && newValueLength > maxLength) {
93
+ mappedValue = mappedValue.substring(0, mappedValue.length - (newValueLength - maxLength));
94
+ }
95
+
96
+ const newValue = getUpperCaseIfNeeded(
97
+ `${value.substring(0, selectionStart)}${mappedValue}${value.substring(selectionEnd)}`,
98
+ );
99
+
100
+ onChange(newValue, { rawValue: str, isValid }, event);
101
+ updateCaretPosition(selectionStart + mappedValue.length, newValue);
102
+ };
103
+
104
+ return (
105
+ <Input
106
+ {...rest}
107
+ ref={mergedRef}
108
+ value={value}
109
+ maxLength={maxLength}
110
+ onPaste={handlePaste}
111
+ onChange={handleChange}
112
+ />
113
+ );
114
+ });
@@ -1,7 +1,9 @@
1
1
  import { FC, ReactNode } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataTestId, isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes } from '../../helpers';
3
+ import {
4
+ addDataAttributes,
5
+ isReactNodeNotEmpty,
6
+ } from '@true-engineering/true-react-platform-helpers';
5
7
  import { ICommonProps } from '../../types';
6
8
  import { IIcon, renderIcon } from '../Icon';
7
9
  import { IStatusColor, IStatusSize } from './types';
@@ -34,8 +36,7 @@ export const Status: FC<IStatusProps> = ({
34
36
  return (
35
37
  <span
36
38
  className={clsx(classes.root, classes[size], classes[color])}
37
- {...addDataTestId(testId)}
38
- {...addDataAttributes(data)}
39
+ {...addDataAttributes(data, testId)}
39
40
  >
40
41
  {isReactNodeNotEmpty(children) && <span className={classes.text}>{children}</span>}
41
42
  {isReactNodeNotEmpty(icon) && (
@@ -1,10 +1,18 @@
1
1
  import { ITweakStyles, animations, createThemedStyles } from '../../theme';
2
+ import { ISwitchSizes } from './types';
2
3
 
3
4
  export const useStyles = createThemedStyles('Switch', {
4
5
  root: {
5
6
  display: 'flex',
6
7
  alignItems: 'center',
7
8
  cursor: 'pointer',
9
+
10
+ '--switch-width': '36px',
11
+ '--switch-height': '20px',
12
+ '--switch-toggle-width': '16px',
13
+ '--switch-toggle-height': '16px',
14
+ '--switch-toggle-padding': 'calc((var(--switch-height) - var(--switch-toggle-height)) / 2)',
15
+ '--switch-label-gap': '12px',
8
16
  },
9
17
 
10
18
  primary: {},
@@ -20,7 +28,7 @@ export const useStyles = createThemedStyles('Switch', {
20
28
 
21
29
  checked: {
22
30
  '& $switch::before': {
23
- left: 18,
31
+ left: 'calc(var(--switch-width) - var(--switch-toggle-width) - var(--switch-toggle-padding))',
24
32
  },
25
33
  },
26
34
 
@@ -28,25 +36,25 @@ export const useStyles = createThemedStyles('Switch', {
28
36
  position: 'relative',
29
37
  flexShrink: 0,
30
38
  display: 'block',
31
- width: 36,
32
- height: 20,
33
- backgroundColor: '#333',
34
- borderRadius: 10,
39
+ width: 'var(--switch-width)',
40
+ height: 'var(--switch-height)',
41
+ borderRadius: 'calc(infinity * 1px)',
35
42
  boxSizing: 'border-box',
36
43
  transition: animations.defaultTransition,
37
44
  transitionProperty: 'opacity, background-color',
45
+ backgroundColor: '#333',
38
46
 
39
47
  '&::before': {
40
48
  content: '""',
41
49
  position: 'absolute',
42
- top: 2,
43
- left: 2,
50
+ top: 'var(--switch-toggle-padding)',
51
+ left: 'var(--switch-toggle-padding)',
52
+ width: 'var(--switch-toggle-width)',
53
+ height: 'var(--switch-toggle-height)',
44
54
  right: 'auto',
45
55
  display: 'block',
46
- width: 16,
47
- height: 16,
48
56
  backgroundColor: '#fff',
49
- borderRadius: '50%',
57
+ borderRadius: 'calc(infinity * 1px)',
50
58
  zIndex: 1,
51
59
  transition: animations.defaultTransition,
52
60
  transitionProperty: 'left, background-color',
@@ -64,12 +72,12 @@ export const useStyles = createThemedStyles('Switch', {
64
72
 
65
73
  labelLeft: {
66
74
  order: -1,
67
- marginRight: 12,
75
+ marginRight: 'var(--switch-label-gap)',
68
76
  },
69
77
 
70
78
  labelRight: {
71
- marginLeft: 12,
79
+ marginLeft: 'var(--switch-label-gap)',
72
80
  },
73
81
  });
74
82
 
75
- export type ISwitchStyles = ITweakStyles<typeof useStyles>;
83
+ export type ISwitchStyles = ITweakStyles<typeof useStyles, ISwitchSizes>;
@@ -1,9 +1,13 @@
1
1
  import { ReactNode } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataTestId, isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes } from '../../helpers';
3
+ import {
4
+ addDataAttributes,
5
+ addDataTestId,
6
+ isNotEmpty,
7
+ isReactNodeNotEmpty,
8
+ } from '@true-engineering/true-react-platform-helpers';
5
9
  import { ICommonProps } from '../../types';
6
- import { ISwitchState } from './types';
10
+ import { ISwitchSize, ISwitchState } from './types';
7
11
  import { useStyles, ISwitchStyles } from './Switch.styles';
8
12
 
9
13
  export interface ISwitchProps<V extends string> extends ICommonProps<ISwitchStyles> {
@@ -19,6 +23,7 @@ export interface ISwitchProps<V extends string> extends ICommonProps<ISwitchStyl
19
23
  labelPosition?: 'left' | 'right';
20
24
  /** @default 'primary' */
21
25
  color?: 'primary' | 'secondary';
26
+ size?: ISwitchSize;
22
27
  onChange: (state: ISwitchState<V>) => void;
23
28
  }
24
29
 
@@ -30,6 +35,7 @@ export const Switch = <V extends string>({
30
35
  children,
31
36
  labelPosition = 'right',
32
37
  color = 'primary',
38
+ size,
33
39
  data,
34
40
  tweakStyles,
35
41
  testId,
@@ -41,13 +47,12 @@ export const Switch = <V extends string>({
41
47
 
42
48
  return (
43
49
  <label
44
- className={clsx(classes.root, classes[color], {
50
+ className={clsx(classes.root, classes[color], isNotEmpty(size) && classes[size], {
45
51
  [classes.disabled]: isDisabled,
46
52
  [classes.checked]: isChecked,
47
53
  [classes.invalid]: isInvalid,
48
54
  })}
49
- {...addDataTestId(testId)}
50
- {...addDataAttributes(data)}
55
+ {...addDataAttributes(data, testId)}
51
56
  >
52
57
  <span className={classes.switch}>
53
58
  <input
@@ -2,3 +2,8 @@ export interface ISwitchState<V = string> {
2
2
  name: V;
3
3
  isEnabled: boolean;
4
4
  }
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
7
+ export interface ISwitchSizes {}
8
+
9
+ export type ISwitchSize = keyof ISwitchSizes;