@true-engineering/true-react-common-ui-kit 3.45.1 → 4.0.0-alpha0

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 (122) hide show
  1. package/README.md +0 -40
  2. package/dist/components/CloseButton/CloseButton.d.ts +1 -1
  3. package/dist/components/ControlGroup/ControlGroup.d.ts +10 -0
  4. package/dist/components/ControlGroup/ControlGroup.stories.d.ts +7 -0
  5. package/dist/components/ControlGroup/ControlGroup.styles.d.ts +3 -0
  6. package/dist/components/ControlGroup/index.d.ts +2 -0
  7. package/dist/components/ControlWrapper/ControlWrapper.d.ts +27 -0
  8. package/dist/components/ControlWrapper/ControlWrapper.stories.d.ts +6 -0
  9. package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +6 -0
  10. package/dist/components/ControlWrapper/index.d.ts +2 -0
  11. package/dist/components/DateInput/DateInput.d.ts +3 -3
  12. package/dist/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.d.ts +1 -1
  13. package/dist/components/DatePicker/types.d.ts +1 -1
  14. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +1 -2
  15. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.d.ts +1 -1
  16. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.d.ts +1 -2
  17. package/dist/components/Input/Input.d.ts +5 -52
  18. package/dist/components/Input/Input.stories.d.ts +4 -13
  19. package/dist/components/Input/Input.styles.d.ts +5 -4
  20. package/dist/components/Input/InputBase.d.ts +24 -0
  21. package/dist/components/Input/index.d.ts +1 -0
  22. package/dist/components/Input/types.d.ts +3 -4
  23. package/dist/components/NumberInput/NumberInput.d.ts +3 -3
  24. package/dist/components/PhoneInput/PhoneInput.d.ts +3 -3
  25. package/dist/components/PhoneInput/PhoneInput.stories.d.ts +2 -2
  26. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.d.ts +3 -2
  27. package/dist/components/PhoneInput/types.d.ts +2 -0
  28. package/dist/components/SearchInput/SearchInput.d.ts +1 -3
  29. package/dist/components/SearchInput/SearchInput.stories.d.ts +11 -1
  30. package/dist/components/SearchInput/SearchInput.styles.d.ts +1 -1
  31. package/dist/components/Select/Select.d.ts +5 -5
  32. package/dist/components/Select/Select.styles.d.ts +17 -16
  33. package/dist/components/Select/types.d.ts +3 -0
  34. package/dist/components/SmartInput/SmartInput.d.ts +3 -3
  35. package/dist/components/TextArea/TextArea.d.ts +5 -14
  36. package/dist/components/TextArea/TextArea.styles.d.ts +8 -2
  37. package/dist/components/WithPopup/WithPopup.d.ts +3 -10
  38. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  39. package/dist/components/WithPopup/types.d.ts +0 -3
  40. package/dist/components/WithTooltip/WithTooltip.styles.d.ts +0 -1
  41. package/dist/components/index.d.ts +2 -0
  42. package/dist/theme/common.d.ts +13 -5
  43. package/dist/theme/types.d.ts +4 -2
  44. package/dist/true-react-common-ui-kit.js +1184 -1029
  45. package/dist/true-react-common-ui-kit.js.map +1 -1
  46. package/dist/true-react-common-ui-kit.umd.cjs +1164 -1009
  47. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  48. package/dist/types.d.ts +2 -1
  49. package/package.json +1 -1
  50. package/src/components/Button/Button.stories.tsx +4 -8
  51. package/src/components/CloseButton/CloseButton.tsx +4 -4
  52. package/src/components/ControlGroup/ControlGroup.stories.tsx +40 -0
  53. package/src/components/ControlGroup/ControlGroup.styles.ts +46 -0
  54. package/src/components/ControlGroup/ControlGroup.tsx +55 -0
  55. package/src/components/ControlGroup/index.ts +2 -0
  56. package/src/components/ControlWrapper/ControlWrapper.stories.tsx +45 -0
  57. package/src/components/ControlWrapper/ControlWrapper.styles.ts +185 -0
  58. package/src/components/ControlWrapper/ControlWrapper.tsx +151 -0
  59. package/src/components/ControlWrapper/index.ts +2 -0
  60. package/src/components/DateInput/DateInput.styles.ts +2 -7
  61. package/src/components/DateInput/DateInput.tsx +4 -4
  62. package/src/components/DatePicker/DatePicker.tsx +3 -3
  63. package/src/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.ts +7 -41
  64. package/src/components/DatePicker/components/DatePickerHeader/DatePickerHeader.tsx +18 -26
  65. package/src/components/DatePicker/types.ts +1 -1
  66. package/src/components/FileItem/FileItem.stories.tsx +4 -8
  67. package/src/components/FiltersPane/FiltersPane.stories.tsx +0 -4
  68. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.styles.ts +9 -7
  69. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.tsx +1 -8
  70. package/src/components/FiltersPane/components/FilterSelect/FilterSelect.styles.ts +7 -5
  71. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +7 -9
  72. package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.ts +12 -17
  73. package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.tsx +2 -5
  74. package/src/components/IconButton/IconButton.stories.tsx +5 -5
  75. package/src/components/IncrementInput/IncrementInput.stories.tsx +0 -2
  76. package/src/components/IncrementInput/IncrementInput.styles.ts +9 -9
  77. package/src/components/Input/Input.stories.tsx +17 -25
  78. package/src/components/Input/Input.styles.ts +50 -260
  79. package/src/components/Input/Input.tsx +22 -285
  80. package/src/components/Input/InputBase.tsx +250 -0
  81. package/src/components/Input/index.ts +1 -0
  82. package/src/components/Input/types.ts +3 -32
  83. package/src/components/MultiSelectList/MultiSelectList.styles.ts +7 -5
  84. package/src/components/Notification/Notification.stories.tsx +2 -6
  85. package/src/components/NumberInput/NumberInput.stories.tsx +0 -2
  86. package/src/components/NumberInput/NumberInput.tsx +4 -7
  87. package/src/components/PhoneInput/PhoneInput.stories.tsx +6 -10
  88. package/src/components/PhoneInput/PhoneInput.styles.ts +13 -10
  89. package/src/components/PhoneInput/PhoneInput.tsx +9 -12
  90. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.styles.ts +6 -4
  91. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +6 -6
  92. package/src/components/PhoneInput/types.ts +4 -0
  93. package/src/components/SearchInput/SearchInput.stories.tsx +1 -0
  94. package/src/components/SearchInput/SearchInput.styles.ts +17 -27
  95. package/src/components/SearchInput/SearchInput.tsx +13 -34
  96. package/src/components/Select/CustomSelect.stories.tsx +6 -9
  97. package/src/components/Select/MultiSelect.stories.tsx +4 -12
  98. package/src/components/Select/Select.stories.tsx +3 -11
  99. package/src/components/Select/Select.styles.ts +28 -42
  100. package/src/components/Select/Select.tsx +73 -81
  101. package/src/components/Select/types.ts +5 -0
  102. package/src/components/SmartInput/SmartInput.stories.tsx +0 -1
  103. package/src/components/SmartInput/SmartInput.tsx +4 -4
  104. package/src/components/Status/Status.stories.tsx +3 -7
  105. package/src/components/TextArea/TextArea.stories.tsx +1 -3
  106. package/src/components/TextArea/TextArea.styles.ts +27 -126
  107. package/src/components/TextArea/TextArea.tsx +86 -112
  108. package/src/components/TextButton/TextButton.stories.tsx +4 -8
  109. package/src/components/WithPopup/WithPopup.stories.tsx +0 -1
  110. package/src/components/WithPopup/WithPopup.styles.ts +0 -2
  111. package/src/components/WithPopup/WithPopup.tsx +10 -36
  112. package/src/components/WithPopup/types.ts +0 -7
  113. package/src/components/WithTooltip/WithTooltip.styles.ts +0 -6
  114. package/src/components/WithTooltip/WithTooltip.tsx +2 -7
  115. package/src/components/index.ts +2 -0
  116. package/src/theme/common.ts +15 -6
  117. package/src/theme/types.ts +8 -4
  118. package/src/types.ts +3 -0
  119. package/dist/components/Input/constants.d.ts +0 -1
  120. package/dist/components/WithPopup/helpers.d.ts +0 -2
  121. package/src/components/Input/constants.ts +0 -1
  122. package/src/components/WithPopup/helpers.ts +0 -9
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { FocusEventHandler, KeyboardEventHandler, MouseEventHandler, PointerEventHandler, ReactNode } from 'react';
1
+ import { FocusEventHandler, type KeyboardEvent, KeyboardEventHandler, MouseEvent, MouseEventHandler, PointerEventHandler, ReactNode } from 'react';
2
2
  import { Modifier, Placement } from 'react-overlays/usePopper';
3
3
  export interface ITestIdProps {
4
4
  testId?: string;
@@ -23,6 +23,7 @@ export interface IDropdownWithPopperOptions {
23
23
  placement?: Placement;
24
24
  flipOptions?: Record<string, any>;
25
25
  }
26
+ export type IClickHandlerEvent = MouseEvent | KeyboardEvent;
26
27
  export interface IDomElementInteractions<T> {
27
28
  onBlur?: FocusEventHandler<T>;
28
29
  onFocus?: FocusEventHandler<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-engineering/true-react-common-ui-kit",
3
- "version": "3.45.1",
3
+ "version": "4.0.0-alpha0",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -1,14 +1,10 @@
1
- import { ComponentStory, ComponentMeta } from '@storybook/react';
2
- import { IIconType, iconsList } from '../Icon';
1
+ import { ComponentMeta, ComponentStory } from '@storybook/react';
2
+ import { iconsList, IIconType } from '../Icon';
3
3
  import { complexIcons } from '../Icon/complexIcons';
4
4
  import { Button, IButtonProps } from './Button';
5
5
  import { BUTTON_SIZES, BUTTON_VIEWS } from './constants';
6
6
 
7
- const iconTypes = [
8
- undefined,
9
- ...Object.keys(iconsList),
10
- ...Object.keys(complexIcons),
11
- ] as IIconType[];
7
+ const icons = [undefined, ...Object.keys(iconsList), ...Object.keys(complexIcons)] as IIconType[];
12
8
 
13
9
  const preloaderTypes: Array<IButtonProps['preloaderType']> = ['dots', 'default', 'logo'];
14
10
 
@@ -29,7 +25,7 @@ export default {
29
25
  isFullWidth: false,
30
26
  },
31
27
  argTypes: {
32
- icon: { options: iconTypes, control: 'select' },
28
+ icon: { options: icons, control: 'select' },
33
29
  size: { options: BUTTON_SIZES, control: 'inline-radio' },
34
30
  view: { options: BUTTON_VIEWS, control: 'inline-radio' },
35
31
  iconPosition: { options: ['left', 'right'], control: 'inline-radio' },
@@ -3,11 +3,11 @@ import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
3
3
  import { addDataAttributes } from '../../helpers';
4
4
  import { ICommonProps } from '../../types';
5
5
  import { Icon } from '../Icon';
6
- import { useStyles, ICloseButtonStyles } from './CloseButton.styles';
6
+ import { ICloseButtonStyles, useStyles } from './CloseButton.styles';
7
7
 
8
8
  export interface ICloseButtonProps extends ICommonProps<ICloseButtonStyles> {
9
9
  /** @default 'close' */
10
- iconType?: 'close' | 'close-large' | 'close-window';
10
+ icon?: 'close' | 'close-large' | 'close-window';
11
11
  onClose?: () => void;
12
12
  }
13
13
 
@@ -16,7 +16,7 @@ export const CloseButton: FC<ICloseButtonProps> = ({
16
16
  tweakStyles,
17
17
  testId,
18
18
  data,
19
- iconType = 'close',
19
+ icon = 'close',
20
20
  onClose,
21
21
  }) => {
22
22
  const classes = useStyles({ theme: tweakStyles });
@@ -29,7 +29,7 @@ export const CloseButton: FC<ICloseButtonProps> = ({
29
29
  {...addDataTestId(testId)}
30
30
  {...addDataAttributes(data)}
31
31
  >
32
- <Icon type={iconType} />
32
+ <Icon type={icon} />
33
33
  </button>
34
34
  );
35
35
  };
@@ -0,0 +1,40 @@
1
+ import { doNothing } from '@true-engineering/true-react-platform-helpers';
2
+ import { ComponentStory } from '@storybook/react';
3
+ import { IInputProps, Input } from '../Input';
4
+ import { ControlGroup } from './ControlGroup';
5
+
6
+ export default {
7
+ title: 'ControlGroup',
8
+ component: ControlGroup,
9
+ };
10
+
11
+ const Template: ComponentStory<typeof ControlGroup> = ({ direction, ...args }) => {
12
+ let groupPlacement: Array<IInputProps['groupPlacement']> = [];
13
+ if (direction === 'horizontal') {
14
+ groupPlacement = ['left', 'right'];
15
+ }
16
+ if (direction === 'vertical') {
17
+ groupPlacement = ['top', 'bottom'];
18
+ }
19
+ return (
20
+ <ControlGroup {...args} direction={direction}>
21
+ <Input value="value" groupPlacement={groupPlacement[0]} onChange={doNothing} />
22
+ <Input value="value" groupPlacement={groupPlacement[1]} onChange={doNothing} />
23
+ </ControlGroup>
24
+ );
25
+ };
26
+
27
+ export const Default = Template.bind({});
28
+
29
+ Default.args = {
30
+ infoMessage: 'Message Info',
31
+ errorMessage: 'Error Text',
32
+ direction: undefined,
33
+ };
34
+
35
+ Default.argTypes = {
36
+ direction: {
37
+ options: [undefined, 'horizontal', 'vertical'],
38
+ control: 'radio',
39
+ },
40
+ };
@@ -0,0 +1,46 @@
1
+ import { createThemedStyles, ITweakStyles } from '../../theme';
2
+
3
+ export const useStyles = createThemedStyles('ControlGroup', {
4
+ root: {
5
+ display: 'flex',
6
+ flexDirection: 'column',
7
+ width: '100%',
8
+ },
9
+
10
+ error: {
11
+ color: 'red',
12
+ },
13
+
14
+ info: {
15
+ color: 'gray',
16
+ },
17
+
18
+ horizontal: {
19
+ display: 'flex',
20
+
21
+ '& > *': {
22
+ flexGrow: 1,
23
+
24
+ '&:not(:first-child)': {
25
+ marginLeft: -1,
26
+ },
27
+ },
28
+ },
29
+
30
+ vertical: {
31
+ display: 'flex',
32
+ flexDirection: 'column',
33
+
34
+ '& > *:not(:first-child)': {
35
+ marginTop: -1,
36
+ },
37
+ },
38
+
39
+ message: {
40
+ fontSize: 12,
41
+ },
42
+
43
+ children: {},
44
+ });
45
+
46
+ export type IControlGroupStyles = ITweakStyles<typeof useStyles>;
@@ -0,0 +1,55 @@
1
+ import { forwardRef, ReactNode } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataAttributes, addDataTestId, isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
4
+ import { ICommonProps } from '../../types';
5
+ import { IControlGroupStyles, useStyles } from './ControlGroup.styles';
6
+
7
+ export interface IControlGroupProps extends ICommonProps<IControlGroupStyles> {
8
+ children: ReactNode;
9
+ infoMessage?: ReactNode;
10
+ errorMessage?: ReactNode;
11
+ direction?: 'horizontal' | 'vertical';
12
+ }
13
+
14
+ export const ControlGroup = forwardRef<HTMLDivElement, IControlGroupProps>(
15
+ ({ children, infoMessage, errorMessage, direction, tweakStyles, testId, data }, ref) => {
16
+ const classes = useStyles({ theme: tweakStyles });
17
+
18
+ const shouldShowError = isReactNodeNotEmpty(errorMessage);
19
+ const shouldShowInfo = isReactNodeNotEmpty(infoMessage) && !shouldShowError;
20
+
21
+ return (
22
+ <div
23
+ ref={ref}
24
+ className={classes.root}
25
+ data-invalid={shouldShowError ? true : undefined}
26
+ {...addDataAttributes(data, testId)}
27
+ >
28
+ {isReactNodeNotEmpty(children) && (
29
+ <div
30
+ className={clsx(classes.children, {
31
+ [classes.horizontal]: direction === 'horizontal',
32
+ [classes.vertical]: direction === 'vertical',
33
+ })}
34
+ >
35
+ {children}
36
+ </div>
37
+ )}
38
+ {(shouldShowError || shouldShowInfo) && (
39
+ <div className={classes.message}>
40
+ {shouldShowError && (
41
+ <div className={classes.error} {...addDataTestId(testId, 'error')}>
42
+ {errorMessage}
43
+ </div>
44
+ )}
45
+ {shouldShowInfo && (
46
+ <div className={classes.info} {...addDataTestId(testId, 'info')}>
47
+ {infoMessage}
48
+ </div>
49
+ )}
50
+ </div>
51
+ )}
52
+ </div>
53
+ );
54
+ },
55
+ );
@@ -0,0 +1,2 @@
1
+ export * from './ControlGroup';
2
+ export type { IControlGroupStyles } from './ControlGroup.styles';
@@ -0,0 +1,45 @@
1
+ import { doNothing } from '@true-engineering/true-react-platform-helpers';
2
+ import { ComponentStory } from '@storybook/react';
3
+ import { iconsList } from '../Icon';
4
+ import { ControlWrapper } from './ControlWrapper';
5
+
6
+ export default {
7
+ title: 'ControlWrapper',
8
+ component: ControlWrapper,
9
+ };
10
+
11
+ const Template: ComponentStory<typeof ControlWrapper> = (args) => (
12
+ <ControlWrapper {...args} onClear={doNothing} onIconClick={doNothing}>
13
+ <div style={{ minWidth: 200, height: 48 }} />
14
+ </ControlWrapper>
15
+ );
16
+
17
+ export const Default = Template.bind({});
18
+
19
+ Default.args = {
20
+ isInvalid: false,
21
+ label: 'Label',
22
+ isFocused: false,
23
+ isRequired: false,
24
+ isLoading: false,
25
+ isDisabled: false,
26
+ hasValue: false,
27
+ };
28
+
29
+ Default.argTypes = {
30
+ icon: { control: 'select', options: [undefined, ...Object.keys(iconsList)] },
31
+ groupPlacement: {
32
+ control: 'select',
33
+ options: [
34
+ 'top',
35
+ 'bottom',
36
+ 'top-left',
37
+ 'top-right',
38
+ 'bottom-left',
39
+ 'bottom-right',
40
+ 'left',
41
+ 'right',
42
+ 'middle',
43
+ ],
44
+ },
45
+ };
@@ -0,0 +1,185 @@
1
+ import { animations, createThemedStyles, dimensions, ITweakStyles } from '../../theme';
2
+ import { IThemedPreloaderStyles } from '../ThemedPreloader';
3
+
4
+ const { CONTROL, Z_INDEX } = dimensions;
5
+
6
+ export const useStyles = createThemedStyles('ControlWrapper', {
7
+ root: {
8
+ '--control-height': `${CONTROL.HEIGHT - 2}px`, // borders
9
+ '--control-padding': `${CONTROL.PADDING}px`,
10
+ '--icon-size': `${CONTROL.ICON_SIZE}px`,
11
+ '--icon-inner-size': `${CONTROL.ICON_INNER_SIZE}px`,
12
+ '--icon-gap': `${CONTROL.ICON_GAP}px`,
13
+ display: 'flex',
14
+ width: '100%',
15
+ backgroundColor: 'white',
16
+ position: 'relative',
17
+ border: ['solid', 1, 'gray'],
18
+ borderRadius: 8,
19
+ boxSizing: 'border-box',
20
+ zIndex: 0,
21
+ },
22
+
23
+ invalid: {
24
+ zIndex: Z_INDEX.CONTROL_INVALID,
25
+ },
26
+
27
+ disabled: {},
28
+
29
+ focused: {
30
+ position: 'relative',
31
+ zIndex: Z_INDEX.CONTROL_FOCUS,
32
+ },
33
+
34
+ withValue: {},
35
+
36
+ loading: {},
37
+
38
+ minContent: {
39
+ width: 'min-content',
40
+ },
41
+
42
+ label: {
43
+ position: 'absolute',
44
+ pointerEvents: 'none',
45
+ left: 'var(--control-padding)',
46
+ top: '50%',
47
+ transformOrigin: 'top left',
48
+ transform: 'translateY(-50%)',
49
+ transition: animations.defaultTransition,
50
+ transitionProperty: 'transform, color',
51
+ fontSize: 16,
52
+ zIndex: 1,
53
+ },
54
+
55
+ activeLabel: {},
56
+
57
+ requiredLabel: {
58
+ '&:after': {
59
+ content: '""',
60
+ display: 'block',
61
+ position: 'absolute',
62
+ top: 0,
63
+ right: -8,
64
+ width: 6,
65
+ height: 6,
66
+ borderRadius: '50%',
67
+ backgroundColor: 'orange',
68
+ },
69
+ },
70
+
71
+ disabledLabel: {},
72
+
73
+ wrapper: {
74
+ display: 'flex',
75
+ flexGrow: 1,
76
+ minWidth: 0, // Нужно для селекта
77
+ textAlign: 'left',
78
+ },
79
+
80
+ controls: {
81
+ display: 'flex',
82
+ marginLeft: 'auto',
83
+ flexShrink: 0,
84
+ },
85
+
86
+ icon: {
87
+ display: 'flex',
88
+ alignItems: 'center',
89
+ justifyContent: 'center',
90
+ minWidth: 'var(--icon-size)',
91
+ width: 'var(--icon-size)',
92
+ height: '100%',
93
+ flexShrink: 0,
94
+ cursor: 'default',
95
+
96
+ '&:last-child': {
97
+ paddingRight: 6,
98
+ },
99
+ },
100
+
101
+ iconInner: {
102
+ width: 'var(--icon-inner-size)',
103
+ },
104
+
105
+ customIcon: {
106
+ width: 'unset',
107
+
108
+ '& $iconInner': {
109
+ width: 'unset',
110
+ },
111
+ },
112
+
113
+ endIcon: {},
114
+
115
+ activeIcon: {
116
+ cursor: 'pointer',
117
+ outline: 'none',
118
+ },
119
+
120
+ clearIcon: {
121
+ '& $iconInner': {
122
+ width: 'var(--icon-inner-size)',
123
+ },
124
+ },
125
+
126
+ loader: {
127
+ '& $iconInner': {
128
+ width: 'var(--icon-inner-size)',
129
+ },
130
+ },
131
+
132
+ /* groupPositions */
133
+ 'placement-top': {
134
+ borderBottomLeftRadius: 0,
135
+ borderBottomRightRadius: 0,
136
+ },
137
+
138
+ 'placement-bottom': {
139
+ borderTopLeftRadius: 0,
140
+ borderTopRightRadius: 0,
141
+ },
142
+
143
+ 'placement-top-left': {
144
+ borderTopRightRadius: 0,
145
+ borderBottomLeftRadius: 0,
146
+ borderBottomRightRadius: 0,
147
+ },
148
+
149
+ 'placement-top-right': {
150
+ borderTopLeftRadius: 0,
151
+ borderBottomLeftRadius: 0,
152
+ borderBottomRightRadius: 0,
153
+ },
154
+
155
+ 'placement-bottom-left': {
156
+ borderTopLeftRadius: 0,
157
+ borderTopRightRadius: 0,
158
+ borderBottomRightRadius: 0,
159
+ },
160
+
161
+ 'placement-bottom-right': {
162
+ borderTopLeftRadius: 0,
163
+ borderTopRightRadius: 0,
164
+ borderBottomLeftRadius: 0,
165
+ },
166
+
167
+ 'placement-left': {
168
+ borderTopRightRadius: 0,
169
+ borderBottomRightRadius: 0,
170
+ },
171
+
172
+ 'placement-right': {
173
+ borderTopLeftRadius: 0,
174
+ borderBottomLeftRadius: 0,
175
+ },
176
+
177
+ 'placement-middle': {
178
+ borderRadius: 0,
179
+ },
180
+ });
181
+
182
+ export type IControlWrapperStyles = ITweakStyles<
183
+ typeof useStyles,
184
+ { tweakPreloader: IThemedPreloaderStyles }
185
+ >;
@@ -0,0 +1,151 @@
1
+ import { FC, ReactNode } from 'react';
2
+ import clsx from 'clsx';
3
+ import {
4
+ addClickHandler,
5
+ addDataAttributes,
6
+ addDataTestId,
7
+ isNotEmpty,
8
+ isReactNodeNotEmpty,
9
+ isString,
10
+ } from '@true-engineering/true-react-platform-helpers';
11
+ import { useTweakStyles } from '../../hooks';
12
+ import { IClickHandlerEvent, ICommonProps } from '../../types';
13
+ import { Icon, IIcon, renderIcon } from '../Icon';
14
+ import { ThemedPreloader } from '../ThemedPreloader';
15
+ import { IControlWrapperStyles, useStyles } from './ControlWrapper.styles';
16
+
17
+ export interface IControlWrapperProps extends ICommonProps<IControlWrapperStyles> {
18
+ children: ReactNode;
19
+ label?: ReactNode;
20
+ icon?: IIcon;
21
+ groupPlacement?:
22
+ | 'left'
23
+ | 'right'
24
+ | 'middle'
25
+ | 'top'
26
+ | 'bottom'
27
+ | 'top-left'
28
+ | 'top-right'
29
+ | 'bottom-left'
30
+ | 'bottom-right';
31
+ /** @default false */
32
+ isInvalid?: boolean;
33
+ /** @default false */
34
+ isFocused?: boolean;
35
+ /** @default false */
36
+ hasValue?: boolean;
37
+ /** @default false */
38
+ isRequired?: boolean;
39
+ /** @default false */
40
+ isFullWidth?: boolean;
41
+ /** @default false */
42
+ isLoading?: boolean;
43
+ /** @default false */
44
+ isDisabled?: boolean;
45
+ onIconClick?: (event: IClickHandlerEvent) => void;
46
+ onClear?: (event: IClickHandlerEvent) => void;
47
+ }
48
+
49
+ export const ControlWrapper: FC<IControlWrapperProps> = ({
50
+ label,
51
+ icon,
52
+ groupPlacement,
53
+ isInvalid,
54
+ isFocused,
55
+ isRequired,
56
+ isLoading,
57
+ isFullWidth,
58
+ isDisabled,
59
+ hasValue,
60
+ testId,
61
+ children,
62
+ tweakStyles,
63
+ data,
64
+ onIconClick,
65
+ onClear,
66
+ }) => {
67
+ const classes = useStyles({ theme: tweakStyles });
68
+
69
+ const hasEndIcon = !isLoading && isReactNodeNotEmpty(icon);
70
+ const hasClearButton = !isDisabled && !isLoading && hasValue && isNotEmpty(onClear);
71
+ const hasControls = hasEndIcon || hasClearButton || isLoading;
72
+
73
+ const tweakPreloaderStyles = useTweakStyles({
74
+ tweakStyles,
75
+ className: 'tweakPreloader',
76
+ currentComponentName: 'ControlWrapper',
77
+ });
78
+
79
+ return (
80
+ <div
81
+ className={clsx(
82
+ classes.root,
83
+ isNotEmpty(groupPlacement) && [classes[`placement-${groupPlacement}`]],
84
+ {
85
+ [classes.invalid]: isInvalid,
86
+ [classes.focused]: isFocused,
87
+ [classes.withValue]: hasValue,
88
+ [classes.disabled]: isDisabled,
89
+ [classes.loading]: isLoading,
90
+ [classes.minContent]: !isFullWidth,
91
+ },
92
+ )}
93
+ {...addDataAttributes(data, testId)}
94
+ >
95
+ {isReactNodeNotEmpty(label) && (
96
+ <div
97
+ className={clsx(classes.label, {
98
+ [classes.requiredLabel]: isRequired,
99
+ [classes.disabledLabel]: isDisabled,
100
+ [classes.activeLabel]: isFocused || hasValue,
101
+ })}
102
+ >
103
+ {label}
104
+ </div>
105
+ )}
106
+ <div className={classes.wrapper}>
107
+ {children}
108
+
109
+ {hasControls && (
110
+ <div className={classes.controls}>
111
+ {hasClearButton && (
112
+ <div
113
+ className={clsx(classes.icon, classes.clearIcon, classes.activeIcon)}
114
+ {...addClickHandler(onClear)}
115
+ {...addDataTestId(testId, 'clear')}
116
+ >
117
+ <div className={classes.iconInner}>
118
+ <Icon type="close" />
119
+ </div>
120
+ </div>
121
+ )}
122
+
123
+ {hasEndIcon && (
124
+ <div
125
+ className={clsx(classes.icon, classes.endIcon, {
126
+ [classes.activeIcon]: !isDisabled && isNotEmpty(onIconClick),
127
+ [classes.customIcon]: !isString(icon),
128
+ })}
129
+ {...addClickHandler(onIconClick, !isDisabled)}
130
+ {...addDataTestId(testId, 'icon')}
131
+ >
132
+ <div className={classes.iconInner}>{renderIcon(icon)}</div>
133
+ </div>
134
+ )}
135
+
136
+ {isLoading && (
137
+ <div
138
+ className={clsx(classes.icon, classes.loader)}
139
+ {...addDataTestId(testId, 'loading')}
140
+ >
141
+ <div className={classes.iconInner}>
142
+ <ThemedPreloader tweakStyles={tweakPreloaderStyles} />
143
+ </div>
144
+ </div>
145
+ )}
146
+ </div>
147
+ )}
148
+ </div>
149
+ </div>
150
+ );
151
+ };
@@ -0,0 +1,2 @@
1
+ export * from './ControlWrapper';
2
+ export type { IControlWrapperStyles } from './ControlWrapper.styles';
@@ -1,4 +1,4 @@
1
- import { ITweakStyles, createThemedStyles } from '../../theme';
1
+ import { createThemedStyles, ITweakStyles } from '../../theme';
2
2
  import { IInputStyles } from '../Input';
3
3
 
4
4
  export const useStyles = createThemedStyles('DateInput', {
@@ -10,9 +10,4 @@ export const useStyles = createThemedStyles('DateInput', {
10
10
  },
11
11
  });
12
12
 
13
- export type IDateInputStyles = ITweakStyles<
14
- typeof useStyles,
15
- {
16
- tweakInput: IInputStyles;
17
- }
18
- >;
13
+ export type IDateInputStyles = ITweakStyles<typeof useStyles, { tweakInput: IInputStyles }>;
@@ -1,11 +1,11 @@
1
- import { FormEvent, MouseEvent, forwardRef, ChangeEvent } from 'react';
1
+ import { ChangeEvent, forwardRef, MouseEvent } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import { addDataAttributes } from '../../helpers';
4
4
  import { useTweakStyles } from '../../hooks';
5
5
  import { ICommonProps } from '../../types';
6
- import { IInputProps, Input } from '../Input';
6
+ import { IChangeInputEvent, IInputProps, Input } from '../Input';
7
7
  import { EMPTY_DATE_INPUT_VALUE, EMPTY_DATE_RANGE_INPUT_VALUE } from './constants';
8
- import { useStyles, IDateInputStyles } from './DateInput.styles';
8
+ import { IDateInputStyles, useStyles } from './DateInput.styles';
9
9
 
10
10
  export interface IDateInputProps
11
11
  extends Omit<IInputProps, 'value' | 'beforeMaskedStateChange' | 'onChange' | 'tweakStyles'>,
@@ -20,7 +20,7 @@ export interface IDateInputProps
20
20
  isRange?: boolean;
21
21
  onClick?: (event: MouseEvent<HTMLDivElement>) => void;
22
22
  // react-datepicker ожидает event первым аргументом
23
- onChange?: (event: FormEvent<HTMLInputElement>, value: string) => void;
23
+ onChange?: (event: IChangeInputEvent, value: string) => void;
24
24
  }
25
25
 
26
26
  export const DateInput = forwardRef<HTMLInputElement, IDateInputProps>(
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, FC, FocusEvent, SyntheticEvent, forwardRef, useMemo } from 'react';
1
+ import { FC, FocusEvent, forwardRef, SyntheticEvent, useEffect, useMemo, useState } from 'react';
2
2
  import ReactDatePicker from 'react-datepicker';
3
3
  import 'react-datepicker/dist/react-datepicker.css';
4
4
  import clsx from 'clsx';
@@ -16,7 +16,7 @@ import { DatePickerHeader, PopperContainer } from './components';
16
16
  import { DatePickerComponent, DEFAULT_DATE_FORMAT } from './constants';
17
17
  import { areDatesEquals, getDateFormatter, getDateValueParser } from './helpers';
18
18
  import { IDatePickerBaseProps, IRange } from './types';
19
- import { useStyles, IDatePickerStyles } from './DatePicker.styles';
19
+ import { IDatePickerStyles, useStyles } from './DatePicker.styles';
20
20
 
21
21
  export interface IDatePickerProps extends IDatePickerBaseProps, ICommonProps<IDatePickerStyles> {
22
22
  selectedDate?: Date | null;
@@ -125,7 +125,7 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
125
125
  isDisabled,
126
126
  isClearable,
127
127
  isActive: isOpen,
128
- iconType: isClearable && hasDateInputValue ? undefined : 'calendar',
128
+ icon: isClearable && hasDateInputValue ? undefined : 'calendar',
129
129
  tweakStyles: tweakDateInputStyles,
130
130
  ...(isRange ? { startDate: startDateValue, endDate: endDateValue } : { date: dateValue }),
131
131
  };