@true-engineering/true-react-common-ui-kit 3.31.0 → 3.32.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.
- package/LICENSE +201 -201
- package/README.md +7 -0
- package/dist/components/Notification/Notification.d.ts +2 -0
- package/dist/components/Notification/Notification.styles.d.ts +1 -1
- package/dist/components/Notification/types.d.ts +1 -1
- package/dist/true-react-common-ui-kit.js +64 -61
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +64 -61
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/package.json +98 -98
- package/src/components/AccountInfo/AccountInfo.stories.tsx +32 -32
- package/src/components/AccountInfo/AccountInfo.tsx +80 -80
- package/src/components/AddButton/AddButton.stories.tsx +21 -21
- package/src/components/AddButton/AddButton.tsx +52 -52
- package/src/components/Colors/Colors.stories.tsx +7 -7
- package/src/components/DateInput/DateInput.tsx +90 -90
- package/src/components/DateInput/constants.ts +2 -2
- package/src/components/Description/Description.stories.tsx +27 -27
- package/src/components/Description/Description.tsx +61 -61
- package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +166 -166
- package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +210 -210
- package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +177 -177
- package/src/components/Flag/Flag.stories.tsx +29 -29
- package/src/components/Flag/Flag.tsx +26 -26
- package/src/components/Flag/augment.d.ts +1 -1
- package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.ts +38 -38
- package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.ts +25 -25
- package/src/components/FlexibleTable/types.ts +70 -70
- package/src/components/Icon/Icon.stories.tsx +86 -86
- package/src/components/Icon/complexIcons/augment.d.ts +1 -1
- package/src/components/Icon/complexIcons/avatarGreen.svg +57 -57
- package/src/components/Icon/complexIcons/index.ts +1 -1
- package/src/components/Icon/icons-list.ts +856 -856
- package/src/components/IncrementInput/IncrementInput.tsx +105 -105
- package/src/components/Input/types.ts +32 -32
- package/src/components/Modal/Modal.stories.tsx +105 -105
- package/src/components/MultiSelect/MultiSelect.stories.tsx +46 -46
- package/src/components/MultiSelect/MultiSelect.tsx +106 -106
- package/src/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.tsx +53 -53
- package/src/components/Notification/Notification.stories.tsx +55 -46
- package/src/components/Notification/Notification.styles.ts +57 -55
- package/src/components/Notification/Notification.tsx +77 -69
- package/src/components/Notification/types.ts +1 -1
- package/src/components/NumberInput/NumberInput.tsx +137 -137
- package/src/components/NumberInput/index.ts +1 -1
- package/src/components/PhoneInput/PhoneInput.tsx +214 -214
- package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +155 -155
- package/src/components/PhoneInput/types.ts +16 -16
- package/src/components/RadioButton/RadioButton.stories.tsx +46 -46
- package/src/components/RadioButton/RadioButton.tsx +57 -57
- package/src/components/ScrollIntoViewIfNeeded/index.ts +1 -1
- package/src/components/Select/Select.stories.tsx +235 -235
- package/src/components/Select/constants.ts +2 -2
- package/src/components/Select/types.ts +1 -1
- package/src/components/Selector/Selector.stories.tsx +62 -62
- package/src/components/Selector/Selector.tsx +115 -115
- package/src/components/Selector/index.ts +2 -2
- package/src/components/Selector/types.ts +12 -12
- package/src/components/Skeleton/Skeleton.stories.tsx +19 -19
- package/src/components/SmartInput/SmartInput.tsx +134 -134
- package/src/components/Status/Status.stories.tsx +73 -73
- package/src/components/Status/Status.styles.ts +143 -143
- package/src/components/Status/Status.tsx +49 -49
- package/src/components/Status/constants.ts +11 -11
- package/src/components/Status/index.ts +3 -3
- package/src/components/Status/types.ts +5 -5
- package/src/components/Switch/Switch.stories.tsx +40 -40
- package/src/components/Switch/Switch.tsx +75 -75
- package/src/components/TextWithInfo/TextWithInfo.stories.tsx +53 -53
- package/src/components/TextWithInfo/TextWithInfo.tsx +62 -62
- package/src/components/TextWithTooltip/TextWithTooltip.stories.tsx +58 -58
- package/src/components/ThemedPreloader/ThemedPreloader.stories.tsx +41 -41
- package/src/components/ThemedPreloader/ThemedPreloader.tsx +54 -54
- package/src/components/ThemedPreloader/components/DefaultPreloader/index.ts +1 -1
- package/src/components/Toaster/Toaster.stories.tsx +30 -30
- package/src/components/Tooltip/Tooltip.stories.tsx +19 -19
- package/src/components/Tooltip/Tooltip.tsx +35 -35
- package/src/components/Tooltip/types.ts +1 -1
- package/src/helpers/popper-helpers.ts +17 -17
- package/src/hooks/use-dropdown.ts +84 -84
- package/src/hooks/use-is-mounted.ts +15 -15
- package/src/theme/helpers.ts +76 -76
- package/src/vite-env.d.ts +1 -1
|
@@ -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
|
+
};
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
import { FC, useState } from 'react';
|
|
2
|
-
import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
-
import { addDataAttributes } from '../../helpers';
|
|
4
|
-
import { ICommonProps } from '../../types';
|
|
5
|
-
import { LINK_REGEXP } from './constants';
|
|
6
|
-
import { useStyles, IDescriptionStyles } from './Description.styles';
|
|
7
|
-
|
|
8
|
-
export interface IDescriptionProps extends ICommonProps<IDescriptionStyles> {
|
|
9
|
-
text: string;
|
|
10
|
-
moreTitle?: string;
|
|
11
|
-
lessTitle?: string;
|
|
12
|
-
/** @default 150 */
|
|
13
|
-
truncateIndex?: number;
|
|
14
|
-
/** @default true */
|
|
15
|
-
isAlwaysOpen?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const Description: FC<IDescriptionProps> = ({
|
|
19
|
-
text,
|
|
20
|
-
moreTitle,
|
|
21
|
-
lessTitle,
|
|
22
|
-
truncateIndex = 150,
|
|
23
|
-
isAlwaysOpen = true,
|
|
24
|
-
testId,
|
|
25
|
-
data,
|
|
26
|
-
tweakStyles,
|
|
27
|
-
}) => {
|
|
28
|
-
const classes = useStyles({ theme: tweakStyles });
|
|
29
|
-
|
|
30
|
-
const isTooShort = text.length < truncateIndex;
|
|
31
|
-
const [isOpen, setIsOpen] = useState(isAlwaysOpen);
|
|
32
|
-
const link = text.match(LINK_REGEXP);
|
|
33
|
-
const linkText = link && link[0];
|
|
34
|
-
const textWithNoLink = text.replace(LINK_REGEXP, '');
|
|
35
|
-
|
|
36
|
-
const shortText = text.slice(0, text.slice(0, truncateIndex).lastIndexOf(' '));
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
|
|
40
|
-
{isAlwaysOpen || isOpen || isTooShort ? (
|
|
41
|
-
<div>
|
|
42
|
-
<span>{textWithNoLink} </span>
|
|
43
|
-
{!!linkText && (
|
|
44
|
-
<a className={classes.link} href={linkText} target="_blank" rel="noopener noreferrer">
|
|
45
|
-
{linkText}
|
|
46
|
-
</a>
|
|
47
|
-
)}
|
|
48
|
-
</div>
|
|
49
|
-
) : (
|
|
50
|
-
<div>
|
|
51
|
-
<span>{shortText}</span>
|
|
52
|
-
</div>
|
|
53
|
-
)}
|
|
54
|
-
{isAlwaysOpen || isTooShort ? undefined : (
|
|
55
|
-
<div className={classes.button} onClick={() => setIsOpen(!isOpen)}>
|
|
56
|
-
{isOpen ? lessTitle : moreTitle}
|
|
57
|
-
</div>
|
|
58
|
-
)}
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
1
|
+
import { FC, useState } from 'react';
|
|
2
|
+
import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
import { addDataAttributes } from '../../helpers';
|
|
4
|
+
import { ICommonProps } from '../../types';
|
|
5
|
+
import { LINK_REGEXP } from './constants';
|
|
6
|
+
import { useStyles, IDescriptionStyles } from './Description.styles';
|
|
7
|
+
|
|
8
|
+
export interface IDescriptionProps extends ICommonProps<IDescriptionStyles> {
|
|
9
|
+
text: string;
|
|
10
|
+
moreTitle?: string;
|
|
11
|
+
lessTitle?: string;
|
|
12
|
+
/** @default 150 */
|
|
13
|
+
truncateIndex?: number;
|
|
14
|
+
/** @default true */
|
|
15
|
+
isAlwaysOpen?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Description: FC<IDescriptionProps> = ({
|
|
19
|
+
text,
|
|
20
|
+
moreTitle,
|
|
21
|
+
lessTitle,
|
|
22
|
+
truncateIndex = 150,
|
|
23
|
+
isAlwaysOpen = true,
|
|
24
|
+
testId,
|
|
25
|
+
data,
|
|
26
|
+
tweakStyles,
|
|
27
|
+
}) => {
|
|
28
|
+
const classes = useStyles({ theme: tweakStyles });
|
|
29
|
+
|
|
30
|
+
const isTooShort = text.length < truncateIndex;
|
|
31
|
+
const [isOpen, setIsOpen] = useState(isAlwaysOpen);
|
|
32
|
+
const link = text.match(LINK_REGEXP);
|
|
33
|
+
const linkText = link && link[0];
|
|
34
|
+
const textWithNoLink = text.replace(LINK_REGEXP, '');
|
|
35
|
+
|
|
36
|
+
const shortText = text.slice(0, text.slice(0, truncateIndex).lastIndexOf(' '));
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
|
|
40
|
+
{isAlwaysOpen || isOpen || isTooShort ? (
|
|
41
|
+
<div>
|
|
42
|
+
<span>{textWithNoLink} </span>
|
|
43
|
+
{!!linkText && (
|
|
44
|
+
<a className={classes.link} href={linkText} target="_blank" rel="noopener noreferrer">
|
|
45
|
+
{linkText}
|
|
46
|
+
</a>
|
|
47
|
+
)}
|
|
48
|
+
</div>
|
|
49
|
+
) : (
|
|
50
|
+
<div>
|
|
51
|
+
<span>{shortText}</span>
|
|
52
|
+
</div>
|
|
53
|
+
)}
|
|
54
|
+
{isAlwaysOpen || isTooShort ? undefined : (
|
|
55
|
+
<div className={classes.button} onClick={() => setIsOpen(!isOpen)}>
|
|
56
|
+
{isOpen ? lessTitle : moreTitle}
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|