@true-engineering/true-react-common-ui-kit 3.40.0 → 3.42.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 (95) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +16 -1
  3. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +2 -1
  4. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.d.ts +1 -1
  5. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.d.ts +1 -1
  6. package/dist/components/FiltersPane/types.d.ts +1 -0
  7. package/dist/components/Input/Input.styles.d.ts +1 -1
  8. package/dist/components/SearchInput/SearchInput.stories.d.ts +1 -1
  9. package/dist/components/Select/Select.styles.d.ts +3 -3
  10. package/dist/components/SmartInput/SmartInput.d.ts +8 -6
  11. package/dist/components/SmartInput/constants.d.ts +4 -6
  12. package/dist/components/SmartInput/helpers.d.ts +2 -4
  13. package/dist/components/SmartInput/types.d.ts +5 -0
  14. package/dist/true-react-common-ui-kit.js +1154 -998
  15. package/dist/true-react-common-ui-kit.js.map +1 -1
  16. package/dist/true-react-common-ui-kit.umd.cjs +1154 -998
  17. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  18. package/package.json +3 -2
  19. package/src/components/AccountInfo/AccountInfo.stories.tsx +32 -32
  20. package/src/components/AccountInfo/AccountInfo.tsx +80 -80
  21. package/src/components/AddButton/AddButton.stories.tsx +21 -21
  22. package/src/components/AddButton/AddButton.tsx +52 -52
  23. package/src/components/Colors/Colors.stories.tsx +7 -7
  24. package/src/components/DateInput/DateInput.tsx +90 -90
  25. package/src/components/DateInput/constants.ts +2 -2
  26. package/src/components/Description/Description.stories.tsx +27 -27
  27. package/src/components/Description/Description.tsx +61 -61
  28. package/src/components/FiltersPane/FiltersPane.stories.tsx +12 -0
  29. package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +166 -166
  30. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +210 -210
  31. package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +177 -177
  32. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.ts +4 -0
  33. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +20 -2
  34. package/src/components/FiltersPane/types.ts +1 -0
  35. package/src/components/Flag/Flag.stories.tsx +29 -29
  36. package/src/components/Flag/Flag.tsx +26 -26
  37. package/src/components/Flag/augment.d.ts +1 -1
  38. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.ts +25 -25
  39. package/src/components/Icon/Icon.stories.tsx +86 -86
  40. package/src/components/Icon/complexIcons/augment.d.ts +1 -1
  41. package/src/components/Icon/complexIcons/avatarGreen.svg +57 -57
  42. package/src/components/Icon/complexIcons/index.ts +1 -1
  43. package/src/components/IncrementInput/IncrementInput.tsx +105 -105
  44. package/src/components/Input/types.ts +32 -32
  45. package/src/components/Modal/Modal.stories.tsx +105 -105
  46. package/src/components/MultiSelect/MultiSelect.stories.tsx +46 -46
  47. package/src/components/MultiSelect/MultiSelect.tsx +106 -106
  48. package/src/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.tsx +53 -53
  49. package/src/components/Notification/Notification.stories.tsx +55 -55
  50. package/src/components/Notification/Notification.styles.ts +57 -57
  51. package/src/components/Notification/Notification.tsx +77 -77
  52. package/src/components/Notification/types.ts +1 -1
  53. package/src/components/NumberInput/NumberInput.tsx +137 -137
  54. package/src/components/NumberInput/index.ts +1 -1
  55. package/src/components/PhoneInput/PhoneInput.tsx +214 -214
  56. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +155 -155
  57. package/src/components/PhoneInput/types.ts +16 -16
  58. package/src/components/RadioButton/RadioButton.stories.tsx +46 -46
  59. package/src/components/RadioButton/RadioButton.tsx +57 -57
  60. package/src/components/ScrollIntoViewIfNeeded/index.ts +1 -1
  61. package/src/components/Select/constants.ts +2 -2
  62. package/src/components/Select/types.ts +1 -1
  63. package/src/components/Selector/Selector.stories.tsx +62 -62
  64. package/src/components/Selector/Selector.tsx +115 -115
  65. package/src/components/Selector/index.ts +2 -2
  66. package/src/components/Selector/types.ts +12 -12
  67. package/src/components/Skeleton/Skeleton.stories.tsx +19 -19
  68. package/src/components/SmartInput/SmartInput.stories.tsx +2 -1
  69. package/src/components/SmartInput/SmartInput.tsx +76 -94
  70. package/src/components/SmartInput/constants.ts +9 -2
  71. package/src/components/SmartInput/helpers.ts +26 -13
  72. package/src/components/SmartInput/types.ts +7 -0
  73. package/src/components/Status/Status.stories.tsx +73 -73
  74. package/src/components/Status/Status.styles.ts +143 -143
  75. package/src/components/Status/Status.tsx +49 -49
  76. package/src/components/Status/constants.ts +11 -11
  77. package/src/components/Status/index.ts +3 -3
  78. package/src/components/Status/types.ts +5 -5
  79. package/src/components/Switch/Switch.stories.tsx +40 -40
  80. package/src/components/Switch/Switch.tsx +75 -75
  81. package/src/components/TextWithInfo/TextWithInfo.stories.tsx +53 -53
  82. package/src/components/TextWithInfo/TextWithInfo.tsx +62 -62
  83. package/src/components/TextWithTooltip/TextWithTooltip.stories.tsx +58 -58
  84. package/src/components/ThemedPreloader/ThemedPreloader.stories.tsx +41 -41
  85. package/src/components/ThemedPreloader/ThemedPreloader.tsx +54 -54
  86. package/src/components/ThemedPreloader/components/DefaultPreloader/index.ts +1 -1
  87. package/src/components/Toaster/Toaster.stories.tsx +30 -30
  88. package/src/components/Tooltip/Tooltip.stories.tsx +19 -19
  89. package/src/components/Tooltip/Tooltip.tsx +35 -35
  90. package/src/components/Tooltip/types.ts +1 -1
  91. package/src/helpers/popper-helpers.ts +17 -17
  92. package/src/hooks/use-dropdown.ts +84 -84
  93. package/src/hooks/use-is-mounted.ts +15 -15
  94. package/src/theme/helpers.ts +76 -76
  95. package/src/vite-env.d.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-engineering/true-react-common-ui-kit",
3
- "version": "3.40.0",
3
+ "version": "3.42.0",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -94,5 +94,6 @@
94
94
  },
95
95
  "resolutions": {
96
96
  "strip-ansi": "6.0.1"
97
- }
97
+ },
98
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
98
99
  }
@@ -1,32 +1,32 @@
1
- import { ComponentStory } from '@storybook/react';
2
- import { AccountInfo } from './AccountInfo';
3
-
4
- export default {
5
- title: 'Data Display/AccountInfo',
6
- component: AccountInfo,
7
- };
8
-
9
- const Template: ComponentStory<typeof AccountInfo> = (args) => (
10
- <div
11
- style={{
12
- display: 'flex',
13
- alignItems: 'center',
14
- justifyContent: 'center',
15
- width: 400,
16
- height: 200,
17
- border: '1px dotted rgba(0, 0, 0, 0.2)',
18
- }}
19
- >
20
- <AccountInfo {...args} options={[{ item: 'Logout', onClick: () => console.log('logout') }]} />
21
- </div>
22
- );
23
-
24
- export const Default = Template.bind({});
25
- Default.args = {
26
- accountName: 'Ivan Ivanov',
27
- };
28
- Default.parameters = {
29
- controls: {
30
- exclude: ['data', 'options', 'avatar'],
31
- },
32
- };
1
+ import { ComponentStory } from '@storybook/react';
2
+ import { AccountInfo } from './AccountInfo';
3
+
4
+ export default {
5
+ title: 'Data Display/AccountInfo',
6
+ component: AccountInfo,
7
+ };
8
+
9
+ const Template: ComponentStory<typeof AccountInfo> = (args) => (
10
+ <div
11
+ style={{
12
+ display: 'flex',
13
+ alignItems: 'center',
14
+ justifyContent: 'center',
15
+ width: 400,
16
+ height: 200,
17
+ border: '1px dotted rgba(0, 0, 0, 0.2)',
18
+ }}
19
+ >
20
+ <AccountInfo {...args} options={[{ item: 'Logout', onClick: () => console.log('logout') }]} />
21
+ </div>
22
+ );
23
+
24
+ export const Default = Template.bind({});
25
+ Default.args = {
26
+ accountName: 'Ivan Ivanov',
27
+ };
28
+ Default.parameters = {
29
+ controls: {
30
+ exclude: ['data', 'options', 'avatar'],
31
+ },
32
+ };
@@ -1,80 +1,80 @@
1
- import { FC, ReactNode, useRef, useState, MouseEvent } from 'react';
2
- import { CSSTransition } from 'react-transition-group';
3
- import clsx from 'clsx';
4
- import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
5
- import { addDataAttributes } from '../../helpers';
6
- import { useOnClickOutsideWithRef, useTweakStyles } from '../../hooks';
7
- import { ICommonProps } from '../../types';
8
- import { Icon } from '../Icon';
9
- import { IListProps, List } from '../List';
10
- import { ANIMATION_TIMEOUT } from './constants';
11
- import { useStyles, IAccountInfoStyles } from './AccountInfo.styles';
12
-
13
- export interface IAccountInfoProps extends ICommonProps<IAccountInfoStyles> {
14
- /** @default `<Icon type='avatar' />` */
15
- avatar?: ReactNode;
16
- accountName: ReactNode;
17
- options: IListProps['items'];
18
- }
19
-
20
- export const AccountInfo: FC<IAccountInfoProps> = ({
21
- data,
22
- testId,
23
- avatar,
24
- tweakStyles,
25
- accountName,
26
- options,
27
- }) => {
28
- const classes = useStyles({ theme: tweakStyles });
29
-
30
- const tweakListStyles = useTweakStyles({
31
- tweakStyles,
32
- className: 'tweakList',
33
- currentComponentName: 'AccountInfo',
34
- });
35
-
36
- const nameRef = useRef<HTMLDivElement>(null);
37
- const dropdownRef = useRef<HTMLDivElement>(null);
38
-
39
- const [isMenuOpen, setIsMenuOpen] = useState(false);
40
-
41
- const toggleMenu = (event: MouseEvent<HTMLDivElement>) => {
42
- event.stopPropagation();
43
- setIsMenuOpen((v) => !v);
44
- };
45
-
46
- useOnClickOutsideWithRef(dropdownRef, () => setIsMenuOpen(false), nameRef);
47
-
48
- return (
49
- <div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
50
- {avatar ?? (
51
- <div className={classes.avatarIcon}>
52
- <Icon type="avatar" />
53
- </div>
54
- )}
55
- <div ref={nameRef} className={classes.account} onClick={toggleMenu}>
56
- <div className={clsx(classes.accountName, isMenuOpen && classes.accountNameOpened)}>
57
- {accountName}
58
- </div>
59
- <div className={clsx(classes.accountChevron, isMenuOpen && classes.accountChevronOpened)}>
60
- <Icon type="chevron-down-small" />
61
- </div>
62
- <CSSTransition
63
- in={isMenuOpen}
64
- timeout={ANIMATION_TIMEOUT}
65
- unmountOnExit
66
- classNames={{
67
- enter: classes['slide-up-enter'],
68
- enterActive: classes['slide-up-enter-active'],
69
- exit: classes['slide-up-exit'],
70
- exitActive: classes['slide-up-exit-active'],
71
- }}
72
- >
73
- <div ref={dropdownRef} className={classes.accountMenu} onClick={toggleMenu}>
74
- <List items={options} tweakStyles={tweakListStyles} />
75
- </div>
76
- </CSSTransition>
77
- </div>
78
- </div>
79
- );
80
- };
1
+ import { FC, ReactNode, useRef, useState, MouseEvent } from 'react';
2
+ import { CSSTransition } from 'react-transition-group';
3
+ import clsx from 'clsx';
4
+ import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
5
+ import { addDataAttributes } from '../../helpers';
6
+ import { useOnClickOutsideWithRef, useTweakStyles } from '../../hooks';
7
+ import { ICommonProps } from '../../types';
8
+ import { Icon } from '../Icon';
9
+ import { IListProps, List } from '../List';
10
+ import { ANIMATION_TIMEOUT } from './constants';
11
+ import { useStyles, IAccountInfoStyles } from './AccountInfo.styles';
12
+
13
+ export interface IAccountInfoProps extends ICommonProps<IAccountInfoStyles> {
14
+ /** @default `<Icon type='avatar' />` */
15
+ avatar?: ReactNode;
16
+ accountName: ReactNode;
17
+ options: IListProps['items'];
18
+ }
19
+
20
+ export const AccountInfo: FC<IAccountInfoProps> = ({
21
+ data,
22
+ testId,
23
+ avatar,
24
+ tweakStyles,
25
+ accountName,
26
+ options,
27
+ }) => {
28
+ const classes = useStyles({ theme: tweakStyles });
29
+
30
+ const tweakListStyles = useTweakStyles({
31
+ tweakStyles,
32
+ className: 'tweakList',
33
+ currentComponentName: 'AccountInfo',
34
+ });
35
+
36
+ const nameRef = useRef<HTMLDivElement>(null);
37
+ const dropdownRef = useRef<HTMLDivElement>(null);
38
+
39
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
40
+
41
+ const toggleMenu = (event: MouseEvent<HTMLDivElement>) => {
42
+ event.stopPropagation();
43
+ setIsMenuOpen((v) => !v);
44
+ };
45
+
46
+ useOnClickOutsideWithRef(dropdownRef, () => setIsMenuOpen(false), nameRef);
47
+
48
+ return (
49
+ <div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
50
+ {avatar ?? (
51
+ <div className={classes.avatarIcon}>
52
+ <Icon type="avatar" />
53
+ </div>
54
+ )}
55
+ <div ref={nameRef} className={classes.account} onClick={toggleMenu}>
56
+ <div className={clsx(classes.accountName, isMenuOpen && classes.accountNameOpened)}>
57
+ {accountName}
58
+ </div>
59
+ <div className={clsx(classes.accountChevron, isMenuOpen && classes.accountChevronOpened)}>
60
+ <Icon type="chevron-down-small" />
61
+ </div>
62
+ <CSSTransition
63
+ in={isMenuOpen}
64
+ timeout={ANIMATION_TIMEOUT}
65
+ unmountOnExit
66
+ classNames={{
67
+ enter: classes['slide-up-enter'],
68
+ enterActive: classes['slide-up-enter-active'],
69
+ exit: classes['slide-up-exit'],
70
+ exitActive: classes['slide-up-exit-active'],
71
+ }}
72
+ >
73
+ <div ref={dropdownRef} className={classes.accountMenu} onClick={toggleMenu}>
74
+ <List items={options} tweakStyles={tweakListStyles} />
75
+ </div>
76
+ </CSSTransition>
77
+ </div>
78
+ </div>
79
+ );
80
+ };
@@ -1,21 +1,21 @@
1
- import { ComponentStory } from '@storybook/react';
2
- import { AddButton } from './AddButton';
3
-
4
- export default {
5
- title: 'Buttons/AddButton',
6
- component: AddButton,
7
- };
8
-
9
- const Template: ComponentStory<typeof AddButton> = (args) => (
10
- <AddButton {...args} onClick={console.log} />
11
- );
12
-
13
- export const Default = Template.bind({});
14
-
15
- Default.args = {
16
- text: 'Добавить билет',
17
- isDisabled: false,
18
- isFullWidth: false,
19
- };
20
-
21
- Default.parameters = { controls: { exclude: ['onClick'] } };
1
+ import { ComponentStory } from '@storybook/react';
2
+ import { AddButton } from './AddButton';
3
+
4
+ export default {
5
+ title: 'Buttons/AddButton',
6
+ component: AddButton,
7
+ };
8
+
9
+ const Template: ComponentStory<typeof AddButton> = (args) => (
10
+ <AddButton {...args} onClick={console.log} />
11
+ );
12
+
13
+ export const Default = Template.bind({});
14
+
15
+ Default.args = {
16
+ text: 'Добавить билет',
17
+ isDisabled: false,
18
+ isFullWidth: false,
19
+ };
20
+
21
+ Default.parameters = { controls: { exclude: ['onClick'] } };
@@ -1,52 +1,52 @@
1
- import { FC } from 'react';
2
- import clsx from 'clsx';
3
- import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes } from '../../helpers';
5
- import { ICommonProps } from '../../types';
6
- import { Icon } from '../Icon';
7
- import { useStyles, IAddButtonStyles } from './AddButton.styles';
8
-
9
- export interface IAddButtonProps extends ICommonProps<IAddButtonStyles> {
10
- text: string;
11
- /** @default 'button' */
12
- type?: 'submit' | 'button';
13
- /** @default false */
14
- isDisabled?: boolean;
15
- /** @default false */
16
- isFullWidth?: boolean;
17
- onClick?: () => void | Promise<void>;
18
- }
19
-
20
- // TODO: Весьма сомнительный компонент
21
- export const AddButton: FC<IAddButtonProps> = ({
22
- text,
23
- type = 'button',
24
- isDisabled = false,
25
- onClick,
26
- isFullWidth = false,
27
- data,
28
- testId,
29
- tweakStyles,
30
- }) => {
31
- const classes = useStyles({ theme: tweakStyles });
32
-
33
- return (
34
- <button
35
- type={type}
36
- className={clsx(
37
- classes.root,
38
- isDisabled && classes.disabled,
39
- isFullWidth && classes.fullWidth,
40
- )}
41
- onClick={!isDisabled ? onClick : undefined}
42
- disabled={isDisabled}
43
- {...addDataTestId(testId)}
44
- {...addDataAttributes(data)}
45
- >
46
- <div className={classes.icon}>
47
- <Icon type="plus" />
48
- </div>
49
- <div>{text}</div>
50
- </button>
51
- );
52
- };
1
+ import { FC } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
4
+ import { addDataAttributes } from '../../helpers';
5
+ import { ICommonProps } from '../../types';
6
+ import { Icon } from '../Icon';
7
+ import { useStyles, IAddButtonStyles } from './AddButton.styles';
8
+
9
+ export interface IAddButtonProps extends ICommonProps<IAddButtonStyles> {
10
+ text: string;
11
+ /** @default 'button' */
12
+ type?: 'submit' | 'button';
13
+ /** @default false */
14
+ isDisabled?: boolean;
15
+ /** @default false */
16
+ isFullWidth?: boolean;
17
+ onClick?: () => void | Promise<void>;
18
+ }
19
+
20
+ // TODO: Весьма сомнительный компонент
21
+ export const AddButton: FC<IAddButtonProps> = ({
22
+ text,
23
+ type = 'button',
24
+ isDisabled = false,
25
+ onClick,
26
+ isFullWidth = false,
27
+ data,
28
+ testId,
29
+ tweakStyles,
30
+ }) => {
31
+ const classes = useStyles({ theme: tweakStyles });
32
+
33
+ return (
34
+ <button
35
+ type={type}
36
+ className={clsx(
37
+ classes.root,
38
+ isDisabled && classes.disabled,
39
+ isFullWidth && classes.fullWidth,
40
+ )}
41
+ onClick={!isDisabled ? onClick : undefined}
42
+ disabled={isDisabled}
43
+ {...addDataTestId(testId)}
44
+ {...addDataAttributes(data)}
45
+ >
46
+ <div className={classes.icon}>
47
+ <Icon type="plus" />
48
+ </div>
49
+ <div>{text}</div>
50
+ </button>
51
+ );
52
+ };
@@ -1,7 +1,7 @@
1
- import { Colors } from './Colors';
2
-
3
- export default {
4
- title: 'Data Display/Colors',
5
- };
6
-
7
- export const Default = (): JSX.Element => <Colors />;
1
+ import { Colors } from './Colors';
2
+
3
+ export default {
4
+ title: 'Data Display/Colors',
5
+ };
6
+
7
+ export const Default = (): JSX.Element => <Colors />;
@@ -1,90 +1,90 @@
1
- import { FormEvent, MouseEvent, forwardRef, ChangeEvent } from 'react';
2
- import clsx from 'clsx';
3
- import { addDataAttributes } from '../../helpers';
4
- import { useTweakStyles } from '../../hooks';
5
- import { ICommonProps } from '../../types';
6
- import { IInputProps, Input } from '../Input';
7
- import { EMPTY_DATE_INPUT_VALUE, EMPTY_DATE_RANGE_INPUT_VALUE } from './constants';
8
- import { useStyles, IDateInputStyles } from './DateInput.styles';
9
-
10
- export interface IDateInputProps
11
- extends Omit<IInputProps, 'value' | 'beforeMaskedStateChange' | 'onChange' | 'tweakStyles'>,
12
- ICommonProps<IDateInputStyles> {
13
- date?: string;
14
- /** @default '' */
15
- startDate?: string;
16
- /** @default '' */
17
- endDate?: string;
18
- className?: string;
19
- /** @default false */
20
- isRange?: boolean;
21
- onClick?: (event: MouseEvent<HTMLDivElement>) => void;
22
- // react-datepicker ожидает event первым аргументом
23
- onChange?: (event: FormEvent<HTMLInputElement>, value: string) => void;
24
- }
25
-
26
- export const DateInput = forwardRef<HTMLInputElement, IDateInputProps>(
27
- (
28
- {
29
- date,
30
- startDate = '',
31
- endDate = '',
32
- mask,
33
- className,
34
- placeholder,
35
- data,
36
- isRange = false,
37
- tweakStyles,
38
- onClick,
39
- onChange,
40
- ...inputProps
41
- },
42
- ref,
43
- ) => {
44
- const classes = useStyles({ theme: tweakStyles });
45
-
46
- const tweakInputStyles = useTweakStyles({
47
- tweakStyles,
48
- className: 'tweakInput',
49
- currentComponentName: 'DateInput',
50
- });
51
-
52
- const beforeMaskedStateChange: IInputProps['beforeMaskedStateChange'] = ({ nextState }) => {
53
- // Если в инпуте отсутствует введенное значение, то выставляем
54
- // пустую строку для корректной работы react-datepicker
55
- if (
56
- nextState.value === EMPTY_DATE_INPUT_VALUE ||
57
- nextState.value === EMPTY_DATE_RANGE_INPUT_VALUE
58
- ) {
59
- return { value: '', selection: { start: 0, end: 0 } };
60
- }
61
- return nextState;
62
- };
63
-
64
- const handleChange: IInputProps['onChange'] = (value, event) => {
65
- // Событие click срабатывает только при нажатии на кнопку очистки
66
- if (event.type === 'click') {
67
- // react-datepicker ожидает пустую строку в event.target.value
68
- (event as ChangeEvent<HTMLInputElement>).target.value = '';
69
- }
70
- onChange?.(event, value);
71
- };
72
-
73
- return (
74
- <div className={clsx(classes.root, className)} onClick={onClick} {...addDataAttributes(data)}>
75
- <Input
76
- {...inputProps}
77
- ref={ref}
78
- value={isRange ? `${startDate}${endDate}` : date}
79
- mask={mask ?? (isRange ? '99.99.9999 - 99.99.9999' : '99.99.9999')}
80
- placeholder={
81
- placeholder ?? (isRange ? EMPTY_DATE_RANGE_INPUT_VALUE : EMPTY_DATE_INPUT_VALUE)
82
- }
83
- tweakStyles={tweakInputStyles}
84
- onChange={handleChange}
85
- beforeMaskedStateChange={beforeMaskedStateChange}
86
- />
87
- </div>
88
- );
89
- },
90
- );
1
+ import { FormEvent, MouseEvent, forwardRef, ChangeEvent } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataAttributes } from '../../helpers';
4
+ import { useTweakStyles } from '../../hooks';
5
+ import { ICommonProps } from '../../types';
6
+ import { IInputProps, Input } from '../Input';
7
+ import { EMPTY_DATE_INPUT_VALUE, EMPTY_DATE_RANGE_INPUT_VALUE } from './constants';
8
+ import { useStyles, IDateInputStyles } from './DateInput.styles';
9
+
10
+ export interface IDateInputProps
11
+ extends Omit<IInputProps, 'value' | 'beforeMaskedStateChange' | 'onChange' | 'tweakStyles'>,
12
+ ICommonProps<IDateInputStyles> {
13
+ date?: string;
14
+ /** @default '' */
15
+ startDate?: string;
16
+ /** @default '' */
17
+ endDate?: string;
18
+ className?: string;
19
+ /** @default false */
20
+ isRange?: boolean;
21
+ onClick?: (event: MouseEvent<HTMLDivElement>) => void;
22
+ // react-datepicker ожидает event первым аргументом
23
+ onChange?: (event: FormEvent<HTMLInputElement>, value: string) => void;
24
+ }
25
+
26
+ export const DateInput = forwardRef<HTMLInputElement, IDateInputProps>(
27
+ (
28
+ {
29
+ date,
30
+ startDate = '',
31
+ endDate = '',
32
+ mask,
33
+ className,
34
+ placeholder,
35
+ data,
36
+ isRange = false,
37
+ tweakStyles,
38
+ onClick,
39
+ onChange,
40
+ ...inputProps
41
+ },
42
+ ref,
43
+ ) => {
44
+ const classes = useStyles({ theme: tweakStyles });
45
+
46
+ const tweakInputStyles = useTweakStyles({
47
+ tweakStyles,
48
+ className: 'tweakInput',
49
+ currentComponentName: 'DateInput',
50
+ });
51
+
52
+ const beforeMaskedStateChange: IInputProps['beforeMaskedStateChange'] = ({ nextState }) => {
53
+ // Если в инпуте отсутствует введенное значение, то выставляем
54
+ // пустую строку для корректной работы react-datepicker
55
+ if (
56
+ nextState.value === EMPTY_DATE_INPUT_VALUE ||
57
+ nextState.value === EMPTY_DATE_RANGE_INPUT_VALUE
58
+ ) {
59
+ return { value: '', selection: { start: 0, end: 0 } };
60
+ }
61
+ return nextState;
62
+ };
63
+
64
+ const handleChange: IInputProps['onChange'] = (value, event) => {
65
+ // Событие click срабатывает только при нажатии на кнопку очистки
66
+ if (event.type === 'click') {
67
+ // react-datepicker ожидает пустую строку в event.target.value
68
+ (event as ChangeEvent<HTMLInputElement>).target.value = '';
69
+ }
70
+ onChange?.(event, value);
71
+ };
72
+
73
+ return (
74
+ <div className={clsx(classes.root, className)} onClick={onClick} {...addDataAttributes(data)}>
75
+ <Input
76
+ {...inputProps}
77
+ ref={ref}
78
+ value={isRange ? `${startDate}${endDate}` : date}
79
+ mask={mask ?? (isRange ? '99.99.9999 - 99.99.9999' : '99.99.9999')}
80
+ placeholder={
81
+ placeholder ?? (isRange ? EMPTY_DATE_RANGE_INPUT_VALUE : EMPTY_DATE_INPUT_VALUE)
82
+ }
83
+ tweakStyles={tweakInputStyles}
84
+ onChange={handleChange}
85
+ beforeMaskedStateChange={beforeMaskedStateChange}
86
+ />
87
+ </div>
88
+ );
89
+ },
90
+ );
@@ -1,2 +1,2 @@
1
- export const EMPTY_DATE_INPUT_VALUE = '__.__.____';
2
- export const EMPTY_DATE_RANGE_INPUT_VALUE = `${EMPTY_DATE_INPUT_VALUE} - ${EMPTY_DATE_INPUT_VALUE}`;
1
+ export const EMPTY_DATE_INPUT_VALUE = '__.__.____';
2
+ export const EMPTY_DATE_RANGE_INPUT_VALUE = `${EMPTY_DATE_INPUT_VALUE} - ${EMPTY_DATE_INPUT_VALUE}`;
@@ -1,27 +1,27 @@
1
- import { ComponentStory } from '@storybook/react';
2
- import { Description } from './Description';
3
-
4
- export default {
5
- title: 'Data Display/Description',
6
- component: Description,
7
- argTypes: {
8
- truncateIndex: {
9
- control: { type: 'range', min: 20, max: 600, step: 10 },
10
- },
11
- },
12
- };
13
-
14
- const lorem =
15
- 'Lorem ipsum dolor, sit amet consectetur adipisicing. Alias necessitatibus quidem nobis molestiae dolor sed at, voluptatum nulla qui enim maiores consectetur dolorum atque odit id ratione pariatur ut nihil. http://google.com';
16
-
17
- const Template: ComponentStory<typeof Description> = (args) => <Description {...args} />;
18
-
19
- export const Default = Template.bind({});
20
-
21
- Default.args = {
22
- text: lorem,
23
- moreTitle: 'подробнее',
24
- lessTitle: 'скрыть',
25
- truncateIndex: 150,
26
- isAlwaysOpen: false,
27
- };
1
+ import { ComponentStory } from '@storybook/react';
2
+ import { Description } from './Description';
3
+
4
+ export default {
5
+ title: 'Data Display/Description',
6
+ component: Description,
7
+ argTypes: {
8
+ truncateIndex: {
9
+ control: { type: 'range', min: 20, max: 600, step: 10 },
10
+ },
11
+ },
12
+ };
13
+
14
+ const lorem =
15
+ 'Lorem ipsum dolor, sit amet consectetur adipisicing. Alias necessitatibus quidem nobis molestiae dolor sed at, voluptatum nulla qui enim maiores consectetur dolorum atque odit id ratione pariatur ut nihil. http://google.com';
16
+
17
+ const Template: ComponentStory<typeof Description> = (args) => <Description {...args} />;
18
+
19
+ export const Default = Template.bind({});
20
+
21
+ Default.args = {
22
+ text: lorem,
23
+ moreTitle: 'подробнее',
24
+ lessTitle: 'скрыть',
25
+ truncateIndex: 150,
26
+ isAlwaysOpen: false,
27
+ };