@true-engineering/true-react-common-ui-kit 4.0.0-alpha0 → 4.0.0-alpha10
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/README.md +11 -567
- package/dist/components/Button/Button.styles.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
- package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +2 -2
- package/dist/components/DatePicker/helpers.d.ts +3 -0
- package/dist/components/DatePicker/types.d.ts +3 -1
- package/dist/components/FiltersPane/FiltersPane.d.ts +4 -2
- package/dist/components/FiltersPane/FiltersPane.stories.d.ts +3 -3
- package/dist/components/FiltersPane/components/Filter/Filter.d.ts +2 -2
- package/dist/components/FiltersPane/components/Filter/helpers.d.ts +4 -0
- package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
- package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +1 -1
- package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.d.ts +3 -1
- package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
- package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +2 -2
- package/dist/components/FiltersPane/types.d.ts +15 -5
- package/dist/components/Flag/customFlags/customFlags.d.ts +10 -0
- package/dist/components/Flag/customFlags/index.d.ts +1 -0
- package/dist/components/FlexibleTable/FlexibleTable.d.ts +4 -2
- package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +6 -6
- package/dist/components/FlexibleTable/constants.d.ts +18 -2
- package/dist/components/FlexibleTable/types.d.ts +1 -1
- package/dist/components/Input/Input.d.ts +3 -3
- package/dist/components/Input/Input.stories.d.ts +2 -2
- package/dist/components/Input/Input.styles.d.ts +3 -3
- package/dist/components/List/List.d.ts +1 -1
- package/dist/components/List/index.d.ts +2 -1
- package/dist/components/List/types.d.ts +4 -0
- package/dist/components/SearchInput/SearchInput.d.ts +2 -2
- package/dist/components/SearchInput/SearchInput.stories.d.ts +3 -12
- package/dist/components/SearchInput/SearchInput.styles.d.ts +3 -5
- package/dist/components/Select/Select.d.ts +5 -3
- package/dist/components/Select/Select.styles.d.ts +8 -8
- package/dist/components/Select/index.d.ts +1 -1
- package/dist/components/TextArea/TextArea.d.ts +2 -2
- package/dist/components/TextArea/TextArea.styles.d.ts +3 -3
- package/dist/components/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.styles.d.ts +1 -1
- package/dist/components/WithMessages/WithMessages.d.ts +10 -0
- package/dist/components/{ControlGroup/ControlGroup.stories.d.ts → WithMessages/WithMessages.stories.d.ts} +2 -2
- package/dist/components/WithMessages/WithMessages.styles.d.ts +3 -0
- package/dist/components/WithMessages/index.d.ts +2 -0
- package/dist/components/WithPopup/WithPopup.d.ts +21 -6
- package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
- package/dist/components/WithPopup/helpers.d.ts +2 -0
- package/dist/components/WithPopup/types.d.ts +3 -0
- package/dist/components/WithTooltip/WithTooltip.styles.d.ts +1 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-merge.d.ts +1 -0
- package/dist/hooks/use-mixed-styles.d.ts +3 -1
- package/dist/hooks/use-tweak-styles.d.ts +5 -5
- package/dist/theme/Provider.d.ts +6 -3
- package/dist/theme/common.d.ts +4 -2
- package/dist/theme/create-themed-styles.d.ts +2 -0
- package/dist/theme/helpers.d.ts +9 -3
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/true-jss/ThemedStylesManager.d.ts +18 -0
- package/dist/theme/true-jss/TweakStylesManager.d.ts +34 -0
- package/dist/theme/true-jss/index.d.ts +2 -0
- package/dist/theme/true-jss/jss-context.d.ts +9 -0
- package/dist/theme/types.d.ts +6 -4
- package/dist/true-react-common-ui-kit.js +7304 -6380
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +7071 -6148
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/ControlWrapper/ControlWrapper.styles.ts +5 -5
- package/src/components/ControlWrapper/ControlWrapper.tsx +1 -1
- package/src/components/DatePicker/DatePicker.tsx +9 -4
- package/src/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.ts +1 -1
- package/src/components/DatePicker/helpers.ts +13 -1
- package/src/components/DatePicker/types.ts +4 -1
- package/src/components/FiltersPane/FiltersPane.stories.tsx +4 -2
- package/src/components/FiltersPane/FiltersPane.tsx +14 -9
- package/src/components/FiltersPane/components/Filter/Filter.tsx +24 -17
- package/src/components/FiltersPane/components/Filter/helpers.ts +18 -0
- package/src/components/FiltersPane/components/FilterInterval/FilterInterval.styles.ts +1 -1
- package/src/components/FiltersPane/components/FilterInterval/FilterInterval.tsx +6 -1
- package/src/components/FiltersPane/components/FilterSelect/FilterSelect.styles.ts +2 -2
- package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +27 -22
- package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.ts +1 -0
- package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +1 -1
- package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +7 -5
- package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.ts +8 -2
- package/src/components/FiltersPane/types.ts +23 -5
- package/src/components/Flag/Flag.stories.tsx +2 -1
- package/src/components/Flag/Flag.styles.ts +4 -0
- package/src/components/Flag/Flag.tsx +23 -9
- package/src/components/Flag/customFlags/AB.svg +1 -0
- package/src/components/Flag/customFlags/OS.svg +1 -0
- package/src/components/Flag/customFlags/augment.d.ts +1 -0
- package/src/components/Flag/customFlags/customFlags.ts +13 -0
- package/src/components/Flag/customFlags/index.ts +1 -0
- package/src/components/FlexibleTable/FlexibleTable.tsx +13 -12
- package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +9 -8
- package/src/components/FlexibleTable/constants.ts +6 -3
- package/src/components/FlexibleTable/types.ts +1 -5
- package/src/components/IncrementInput/IncrementInput.styles.ts +1 -1
- package/src/components/Input/Input.styles.ts +5 -2
- package/src/components/Input/Input.tsx +9 -8
- package/src/components/Input/InputBase.tsx +2 -1
- package/src/components/List/List.tsx +5 -2
- package/src/components/List/index.ts +2 -1
- package/src/components/List/types.ts +5 -0
- package/src/components/MultiSelectList/MultiSelectList.styles.ts +1 -1
- package/src/components/PhoneInput/PhoneInput.stories.tsx +2 -1
- package/src/components/PhoneInput/PhoneInput.styles.ts +2 -2
- package/src/components/PhoneInput/PhoneInput.tsx +5 -2
- package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.styles.ts +1 -1
- package/src/components/SearchInput/SearchInput.styles.ts +17 -30
- package/src/components/SearchInput/SearchInput.tsx +17 -30
- package/src/components/Select/CustomSelect.stories.tsx +2 -2
- package/src/components/Select/Select.styles.ts +8 -2
- package/src/components/Select/Select.tsx +19 -31
- package/src/components/Select/components/SelectList/SelectList.tsx +1 -1
- package/src/components/Select/index.ts +1 -1
- package/src/components/TextArea/TextArea.styles.ts +7 -3
- package/src/components/TextArea/TextArea.tsx +16 -11
- package/src/components/Tooltip/Tooltip.styles.ts +2 -0
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/{ControlGroup/ControlGroup.stories.tsx → WithMessages/WithMessages.stories.tsx} +10 -10
- package/src/components/{ControlGroup/ControlGroup.styles.ts → WithMessages/WithMessages.styles.ts} +4 -3
- package/src/components/{ControlGroup/ControlGroup.tsx → WithMessages/WithMessages.tsx} +13 -9
- package/src/components/WithMessages/index.ts +2 -0
- package/src/components/WithPopup/WithPopup.stories.tsx +1 -0
- package/src/components/WithPopup/WithPopup.styles.ts +2 -0
- package/src/components/WithPopup/WithPopup.tsx +64 -16
- package/src/components/WithPopup/helpers.ts +9 -0
- package/src/components/WithPopup/types.ts +7 -0
- package/src/components/WithTooltip/WithTooltip.styles.ts +6 -0
- package/src/components/WithTooltip/WithTooltip.tsx +7 -2
- package/src/components/index.ts +1 -1
- package/src/constants/phone-info.ts +20 -33
- package/src/helpers/phone.ts +19 -15
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-merge.ts +8 -0
- package/src/hooks/use-mixed-styles.ts +9 -11
- package/src/hooks/use-tweak-styles.ts +49 -27
- package/src/theme/Provider.tsx +10 -5
- package/src/theme/common.ts +5 -2
- package/src/theme/create-themed-styles.ts +78 -0
- package/src/theme/helpers.ts +39 -39
- package/src/theme/index.ts +2 -0
- package/src/theme/true-jss/ThemedStylesManager.ts +92 -0
- package/src/theme/true-jss/TweakStylesManager.ts +157 -0
- package/src/theme/true-jss/index.ts +2 -0
- package/src/theme/true-jss/jss-context.tsx +34 -0
- package/src/theme/types.ts +6 -4
- package/src/types.ts +2 -1
- package/dist/components/ControlGroup/ControlGroup.d.ts +0 -10
- package/dist/components/ControlGroup/ControlGroup.styles.d.ts +0 -3
- package/dist/components/ControlGroup/index.d.ts +0 -2
- package/src/components/ControlGroup/index.ts +0 -2
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
KeyboardEvent,
|
|
6
6
|
MouseEvent,
|
|
7
7
|
ReactNode,
|
|
8
|
+
Ref,
|
|
8
9
|
SyntheticEvent,
|
|
9
10
|
useCallback,
|
|
10
11
|
useEffect,
|
|
@@ -18,7 +19,6 @@ import { debounce } from 'ts-debounce';
|
|
|
18
19
|
import {
|
|
19
20
|
createFilter,
|
|
20
21
|
getTestId,
|
|
21
|
-
isEmpty,
|
|
22
22
|
isNotEmpty,
|
|
23
23
|
isReactNodeNotEmpty,
|
|
24
24
|
isStringNotEmpty,
|
|
@@ -26,10 +26,10 @@ import {
|
|
|
26
26
|
import { hasExactParent } from '../../helpers';
|
|
27
27
|
import { useDropdown, useIsMounted, useOnClickOutsideWithRef, useTweakStyles } from '../../hooks';
|
|
28
28
|
import { ICommonProps, IDropdownWithPopperOptions } from '../../types';
|
|
29
|
-
import { ControlGroup } from '../ControlGroup';
|
|
30
29
|
import { IIcon, renderIcon } from '../Icon';
|
|
31
30
|
import { IChangeInputEvent, IInputProps, InputBase } from '../Input';
|
|
32
31
|
import { ISearchInputProps, SearchInput } from '../SearchInput';
|
|
32
|
+
import { WithMessages } from '../WithMessages';
|
|
33
33
|
import { SelectList } from './components';
|
|
34
34
|
import { ALL_OPTION_INDEX, DEFAULT_OPTION_INDEX } from './constants';
|
|
35
35
|
import {
|
|
@@ -64,7 +64,11 @@ export interface ISelectProps<Value>
|
|
|
64
64
|
/** @default true */
|
|
65
65
|
shouldScrollToList?: boolean;
|
|
66
66
|
isMultiSelect?: false;
|
|
67
|
-
searchInput?: {
|
|
67
|
+
searchInput?: {
|
|
68
|
+
/** @default false */
|
|
69
|
+
shouldRenderInList?: boolean;
|
|
70
|
+
ref?: Ref<HTMLInputElement>;
|
|
71
|
+
} & Pick<ISearchInputProps, 'placeholder' | 'shouldFocusOnMount'>;
|
|
68
72
|
isOptionDisabled?: (option: Value) => boolean;
|
|
69
73
|
onChange: (value: Value | undefined, event: IChangeSelectEvent) => void; // подумать как возвращать индекс
|
|
70
74
|
onBlur?: (event: Event | SyntheticEvent) => void;
|
|
@@ -142,9 +146,9 @@ export function Select<Value>(
|
|
|
142
146
|
const hasSearchInputInList = optionsMode !== 'normal' && shouldRenderSearchInputInList;
|
|
143
147
|
const hasReadonlyInput = isReadonly || optionsMode === 'normal' || shouldRenderSearchInputInList;
|
|
144
148
|
|
|
145
|
-
const
|
|
149
|
+
const tweakWithMessagesStyles = useTweakStyles({
|
|
146
150
|
tweakStyles,
|
|
147
|
-
className: '
|
|
151
|
+
className: 'tweakWithMessages',
|
|
148
152
|
currentComponentName: 'Select',
|
|
149
153
|
});
|
|
150
154
|
|
|
@@ -241,44 +245,27 @@ export function Select<Value>(
|
|
|
241
245
|
[convertValueToId, convertValueToString],
|
|
242
246
|
);
|
|
243
247
|
|
|
244
|
-
const getDropdownOffset = () => {
|
|
245
|
-
if (isEmpty(input.current)) {
|
|
246
|
-
return 0;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Высота элемента inputWrapper у компонента Input
|
|
250
|
-
return input.current.parentElement?.offsetHeight ?? 0;
|
|
251
|
-
};
|
|
252
|
-
|
|
253
248
|
const closeList = useCallback(() => {
|
|
254
249
|
setIsListOpen(false);
|
|
255
250
|
setSearchValue('');
|
|
256
251
|
setShouldShowDefaultOption(true);
|
|
257
|
-
|
|
258
|
-
if (!dropdownOptions?.shouldUsePopper) {
|
|
259
|
-
root.current?.style.removeProperty('--dropdown-offset');
|
|
260
|
-
}
|
|
261
252
|
}, [dropdownOptions?.shouldUsePopper]);
|
|
262
253
|
|
|
263
254
|
const handleListClose = useCallback(
|
|
264
255
|
(event: Event | SyntheticEvent) => {
|
|
256
|
+
if (!isListOpen) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
265
260
|
closeList();
|
|
266
261
|
onBlur?.(event);
|
|
267
262
|
},
|
|
268
|
-
[closeList, onBlur],
|
|
263
|
+
[isListOpen, closeList, onBlur],
|
|
269
264
|
);
|
|
270
265
|
|
|
271
266
|
const handleListOpen = () => {
|
|
272
|
-
if (isReadonly) {
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (!isListOpen) {
|
|
267
|
+
if (!isReadonly && !isListOpen) {
|
|
277
268
|
setIsListOpen(true);
|
|
278
|
-
|
|
279
|
-
if (!dropdownOptions?.shouldUsePopper) {
|
|
280
|
-
root.current?.style.setProperty('--dropdown-offset', `${getDropdownOffset()}px`);
|
|
281
|
-
}
|
|
282
269
|
}
|
|
283
270
|
};
|
|
284
271
|
|
|
@@ -599,10 +586,11 @@ export function Select<Value>(
|
|
|
599
586
|
) : undefined;
|
|
600
587
|
|
|
601
588
|
return (
|
|
602
|
-
<
|
|
589
|
+
<WithMessages
|
|
603
590
|
errorMessage={errorMessage}
|
|
604
591
|
infoMessage={infoMessage}
|
|
605
|
-
tweakStyles={
|
|
592
|
+
tweakStyles={tweakWithMessagesStyles}
|
|
593
|
+
testId={getTestId(testId, 'wrapper')}
|
|
606
594
|
>
|
|
607
595
|
<div className={classes.root} onKeyDown={handleKeyDown} ref={root}>
|
|
608
596
|
<div
|
|
@@ -645,6 +633,6 @@ export function Select<Value>(
|
|
|
645
633
|
<>{isOpen && listEl}</>
|
|
646
634
|
)}
|
|
647
635
|
</div>
|
|
648
|
-
</
|
|
636
|
+
</WithMessages>
|
|
649
637
|
);
|
|
650
638
|
}
|
|
@@ -84,7 +84,7 @@ export function SelectList<Value>({
|
|
|
84
84
|
})}
|
|
85
85
|
>
|
|
86
86
|
{isHeaderNotEmpty && <div className={classes.listHeader}>{customListHeader}</div>}
|
|
87
|
-
<div className={classes.list} {...addDataTestId(testId)}>
|
|
87
|
+
<div className={classes.list} {...addDataTestId(testId)} tabIndex={-1}>
|
|
88
88
|
{isLoading ? (
|
|
89
89
|
<div className={clsx(classes.cell, classes.loading)}>{loadingLabel}</div>
|
|
90
90
|
) : (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { animations, createThemedStyles, helpers, ITweakStyles } from '../../theme';
|
|
2
|
-
import { IControlGroupStyles } from '../ControlGroup';
|
|
3
2
|
import { IControlWrapperStyles } from '../ControlWrapper';
|
|
3
|
+
import { IWithMessagesStyles } from '../WithMessages';
|
|
4
4
|
|
|
5
5
|
export const useStyles = createThemedStyles('TextArea', {
|
|
6
6
|
textarea: {
|
|
@@ -32,12 +32,16 @@ export const useStyles = createThemedStyles('TextArea', {
|
|
|
32
32
|
},
|
|
33
33
|
},
|
|
34
34
|
|
|
35
|
+
wrapper: {
|
|
36
|
+
width: '100%',
|
|
37
|
+
},
|
|
38
|
+
|
|
35
39
|
autoSized: {
|
|
36
40
|
display: 'grid',
|
|
37
41
|
gridTemplateRows: 'minmax(0, 100%)',
|
|
38
42
|
|
|
39
43
|
'& > $textarea, &::after': {
|
|
40
|
-
gridArea: '1 /
|
|
44
|
+
gridArea: '1 / 1',
|
|
41
45
|
},
|
|
42
46
|
|
|
43
47
|
'&::after': {
|
|
@@ -72,7 +76,7 @@ export const controlWrapperStyles: IControlWrapperStyles = {
|
|
|
72
76
|
export type ITextAreaStyles = ITweakStyles<
|
|
73
77
|
typeof useStyles,
|
|
74
78
|
{
|
|
75
|
-
|
|
79
|
+
tweakWithMessages: IWithMessagesStyles;
|
|
76
80
|
tweakControlWrapper: IControlWrapperStyles;
|
|
77
81
|
}
|
|
78
82
|
>;
|
|
@@ -2,21 +2,22 @@ import { ChangeEvent, FocusEvent, FormEvent, forwardRef, useState } from 'react'
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import {
|
|
4
4
|
addDataAttributes,
|
|
5
|
+
getTestId,
|
|
5
6
|
isNotEmpty,
|
|
6
7
|
isReactNodeNotEmpty,
|
|
7
8
|
isStringNotEmpty,
|
|
8
9
|
} from '@true-engineering/true-react-platform-helpers';
|
|
9
10
|
import { useTweakStyles } from '../../hooks';
|
|
10
11
|
import { ICommonProps } from '../../types';
|
|
11
|
-
import { ControlGroup, IControlGroupProps } from '../ControlGroup';
|
|
12
12
|
import { ControlWrapper, IControlWrapperProps } from '../ControlWrapper';
|
|
13
|
+
import { IWithMessagesProps, WithMessages } from '../WithMessages';
|
|
13
14
|
import { ITextAreaHTMLBaseProps } from './types';
|
|
14
15
|
import { controlWrapperStyles, ITextAreaStyles, useStyles } from './TextArea.styles';
|
|
15
16
|
|
|
16
17
|
export interface ITextAreaProps
|
|
17
18
|
extends ICommonProps<ITextAreaStyles>,
|
|
18
19
|
Pick<IControlWrapperProps, 'label' | 'isInvalid' | 'isRequired' | 'isDisabled'>,
|
|
19
|
-
Pick<
|
|
20
|
+
Pick<IWithMessagesProps, 'infoMessage' | 'errorMessage'>,
|
|
20
21
|
Pick<ITextAreaHTMLBaseProps, 'name' | 'maxLength' | 'rows' | 'onPaste' | 'onFocus' | 'onBlur'> {
|
|
21
22
|
value?: string;
|
|
22
23
|
placeholder?: string;
|
|
@@ -73,9 +74,9 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
73
74
|
) => {
|
|
74
75
|
const classes = useStyles({ theme: tweakStyles });
|
|
75
76
|
|
|
76
|
-
const
|
|
77
|
+
const tweakWithMessagesStyles = useTweakStyles({
|
|
77
78
|
tweakStyles,
|
|
78
|
-
className: '
|
|
79
|
+
className: 'tweakWithMessages',
|
|
79
80
|
currentComponentName: 'TextArea',
|
|
80
81
|
});
|
|
81
82
|
|
|
@@ -92,7 +93,8 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
92
93
|
// в hasValue нельзя использовать isStringNotEmpty из-за того что isStringNotEmpty делает trim
|
|
93
94
|
const hasValue = value !== undefined && value !== '';
|
|
94
95
|
const hasLabel = isReactNodeNotEmpty(label);
|
|
95
|
-
const hasPlaceholder =
|
|
96
|
+
const hasPlaceholder =
|
|
97
|
+
(!hasLabel || hasFocus || shouldAlwaysShowPlaceholder) && isStringNotEmpty(placeholder);
|
|
96
98
|
|
|
97
99
|
const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
|
|
98
100
|
onChange(event.currentTarget.value, event);
|
|
@@ -109,10 +111,11 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
109
111
|
};
|
|
110
112
|
|
|
111
113
|
return (
|
|
112
|
-
<
|
|
114
|
+
<WithMessages
|
|
113
115
|
errorMessage={errorMessage}
|
|
114
116
|
infoMessage={infoMessage}
|
|
115
|
-
tweakStyles={
|
|
117
|
+
tweakStyles={tweakWithMessagesStyles}
|
|
118
|
+
testId={getTestId(testId, 'wrapper')}
|
|
116
119
|
>
|
|
117
120
|
<ControlWrapper
|
|
118
121
|
label={label}
|
|
@@ -121,10 +124,12 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
121
124
|
isDisabled={isDisabled}
|
|
122
125
|
hasValue={hasValue}
|
|
123
126
|
isFullWidth
|
|
124
|
-
testId={testId}
|
|
125
127
|
{...controlProps}
|
|
126
128
|
>
|
|
127
|
-
<div
|
|
129
|
+
<div
|
|
130
|
+
className={clsx(classes.wrapper, { [classes.autoSized]: isAutoSized })}
|
|
131
|
+
{...(isAutoSized && { 'data-value': value })}
|
|
132
|
+
>
|
|
128
133
|
<textarea
|
|
129
134
|
ref={ref}
|
|
130
135
|
className={classes.textarea}
|
|
@@ -138,7 +143,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
138
143
|
onFocus={handleFocus}
|
|
139
144
|
onBlur={handleBlur}
|
|
140
145
|
onChange={handleChange}
|
|
141
|
-
{...addDataAttributes(data, testId
|
|
146
|
+
{...addDataAttributes(data, testId)}
|
|
142
147
|
/>
|
|
143
148
|
</div>
|
|
144
149
|
</ControlWrapper>
|
|
@@ -151,7 +156,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
151
156
|
{value.length} / {maxLength}
|
|
152
157
|
</span>
|
|
153
158
|
)}
|
|
154
|
-
</
|
|
159
|
+
</WithMessages>
|
|
155
160
|
);
|
|
156
161
|
},
|
|
157
162
|
);
|
|
@@ -8,7 +8,7 @@ import { useStyles, ITooltipStyles } from './Tooltip.styles';
|
|
|
8
8
|
export interface ITooltipProps extends ICommonProps<ITooltipStyles> {
|
|
9
9
|
text: ReactNode;
|
|
10
10
|
/** @default 'tooltip' */
|
|
11
|
-
view?: 'tooltip' | 'hint';
|
|
11
|
+
view?: 'tooltip' | 'hint' | 'custom';
|
|
12
12
|
/** @default 'info' */
|
|
13
13
|
type?: 'info' | 'error';
|
|
14
14
|
}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { doNothing } from '@true-engineering/true-react-platform-helpers';
|
|
2
2
|
import { ComponentStory } from '@storybook/react';
|
|
3
3
|
import { IInputProps, Input } from '../Input';
|
|
4
|
-
import {
|
|
4
|
+
import { WithMessages } from './WithMessages';
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
|
-
title: '
|
|
8
|
-
component:
|
|
7
|
+
title: 'WithMessages',
|
|
8
|
+
component: WithMessages,
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const Template: ComponentStory<typeof
|
|
11
|
+
const Template: ComponentStory<typeof WithMessages> = ({ controlsDirection, ...args }) => {
|
|
12
12
|
let groupPlacement: Array<IInputProps['groupPlacement']> = [];
|
|
13
|
-
if (
|
|
13
|
+
if (controlsDirection === 'horizontal') {
|
|
14
14
|
groupPlacement = ['left', 'right'];
|
|
15
15
|
}
|
|
16
|
-
if (
|
|
16
|
+
if (controlsDirection === 'vertical') {
|
|
17
17
|
groupPlacement = ['top', 'bottom'];
|
|
18
18
|
}
|
|
19
19
|
return (
|
|
20
|
-
<
|
|
20
|
+
<WithMessages {...args} controlsDirection={controlsDirection}>
|
|
21
21
|
<Input value="value" groupPlacement={groupPlacement[0]} onChange={doNothing} />
|
|
22
22
|
<Input value="value" groupPlacement={groupPlacement[1]} onChange={doNothing} />
|
|
23
|
-
</
|
|
23
|
+
</WithMessages>
|
|
24
24
|
);
|
|
25
25
|
};
|
|
26
26
|
|
|
@@ -29,11 +29,11 @@ export const Default = Template.bind({});
|
|
|
29
29
|
Default.args = {
|
|
30
30
|
infoMessage: 'Message Info',
|
|
31
31
|
errorMessage: 'Error Text',
|
|
32
|
-
|
|
32
|
+
controlsDirection: undefined,
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
Default.argTypes = {
|
|
36
|
-
|
|
36
|
+
controlsDirection: {
|
|
37
37
|
options: [undefined, 'horizontal', 'vertical'],
|
|
38
38
|
control: 'radio',
|
|
39
39
|
},
|
package/src/components/{ControlGroup/ControlGroup.styles.ts → WithMessages/WithMessages.styles.ts}
RENAMED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createThemedStyles, ITweakStyles } from '../../theme';
|
|
2
2
|
|
|
3
|
-
export const useStyles = createThemedStyles('
|
|
4
|
-
|
|
3
|
+
export const useStyles = createThemedStyles('WithMessages', {
|
|
4
|
+
withMessages: {
|
|
5
5
|
display: 'flex',
|
|
6
6
|
flexDirection: 'column',
|
|
7
7
|
width: '100%',
|
|
8
|
+
position: 'relative',
|
|
8
9
|
},
|
|
9
10
|
|
|
10
11
|
error: {
|
|
@@ -43,4 +44,4 @@ export const useStyles = createThemedStyles('ControlGroup', {
|
|
|
43
44
|
children: {},
|
|
44
45
|
});
|
|
45
46
|
|
|
46
|
-
export type
|
|
47
|
+
export type IWithMessagesStyles = ITweakStyles<typeof useStyles>;
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { forwardRef, ReactNode } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addDataAttributes,
|
|
5
|
+
addDataTestId,
|
|
6
|
+
isReactNodeNotEmpty,
|
|
7
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
4
8
|
import { ICommonProps } from '../../types';
|
|
5
|
-
import {
|
|
9
|
+
import { IWithMessagesStyles, useStyles } from './WithMessages.styles';
|
|
6
10
|
|
|
7
|
-
export interface
|
|
11
|
+
export interface IWithMessagesProps extends ICommonProps<IWithMessagesStyles> {
|
|
8
12
|
children: ReactNode;
|
|
9
13
|
infoMessage?: ReactNode;
|
|
10
14
|
errorMessage?: ReactNode;
|
|
11
|
-
|
|
15
|
+
controlsDirection?: 'horizontal' | 'vertical';
|
|
12
16
|
}
|
|
13
17
|
|
|
14
|
-
export const
|
|
15
|
-
({ children, infoMessage, errorMessage,
|
|
18
|
+
export const WithMessages = forwardRef<HTMLDivElement, IWithMessagesProps>(
|
|
19
|
+
({ children, infoMessage, errorMessage, controlsDirection, tweakStyles, testId, data }, ref) => {
|
|
16
20
|
const classes = useStyles({ theme: tweakStyles });
|
|
17
21
|
|
|
18
22
|
const shouldShowError = isReactNodeNotEmpty(errorMessage);
|
|
@@ -21,15 +25,15 @@ export const ControlGroup = forwardRef<HTMLDivElement, IControlGroupProps>(
|
|
|
21
25
|
return (
|
|
22
26
|
<div
|
|
23
27
|
ref={ref}
|
|
24
|
-
className={classes.
|
|
28
|
+
className={classes.withMessages}
|
|
25
29
|
data-invalid={shouldShowError ? true : undefined}
|
|
26
30
|
{...addDataAttributes(data, testId)}
|
|
27
31
|
>
|
|
28
32
|
{isReactNodeNotEmpty(children) && (
|
|
29
33
|
<div
|
|
30
34
|
className={clsx(classes.children, {
|
|
31
|
-
[classes.horizontal]:
|
|
32
|
-
[classes.vertical]:
|
|
35
|
+
[classes.horizontal]: controlsDirection === 'horizontal',
|
|
36
|
+
[classes.vertical]: controlsDirection === 'vertical',
|
|
33
37
|
})}
|
|
34
38
|
>
|
|
35
39
|
{children}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { FC, useState } from 'react';
|
|
1
|
+
import { FC, useRef, useState } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import {
|
|
4
|
-
addDataTestId,
|
|
5
4
|
applyAction,
|
|
6
5
|
stopPropagation,
|
|
7
6
|
addDataAttributes,
|
|
@@ -23,10 +22,18 @@ import {
|
|
|
23
22
|
UseHoverProps,
|
|
24
23
|
safePolygon,
|
|
25
24
|
useFocus,
|
|
25
|
+
FloatingArrow,
|
|
26
|
+
arrow,
|
|
27
|
+
UseClickProps,
|
|
28
|
+
UseFocusProps,
|
|
29
|
+
UseDismissProps,
|
|
30
|
+
UseTransitionStatusProps,
|
|
26
31
|
} from '@floating-ui/react';
|
|
27
|
-
import { ICommonProps, IRenderNode } from '../../types';
|
|
32
|
+
import { ICommonProps, IDataAttributes, IRenderNode } from '../../types';
|
|
28
33
|
import { DEFAULT_OFFSET } from './constants';
|
|
34
|
+
import { minWidthRelativeToTrigger } from './helpers';
|
|
29
35
|
import {
|
|
36
|
+
IPopupArrowProps,
|
|
30
37
|
IPopupEventType,
|
|
31
38
|
IReferenceProps,
|
|
32
39
|
IWithPopupChildrenProps,
|
|
@@ -43,11 +50,16 @@ export interface IWithPopupProps extends ICommonProps<IWithPopupStyles> {
|
|
|
43
50
|
placement?: Placement;
|
|
44
51
|
/** @default 'click' */
|
|
45
52
|
eventType?: IPopupEventType;
|
|
46
|
-
/**
|
|
47
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated Используйте hoverOptions
|
|
55
|
+
* @default 0
|
|
56
|
+
*/
|
|
57
|
+
hoverDelay?: number;
|
|
48
58
|
/** @default 6 */
|
|
49
59
|
popupOffset?: OffsetOptions;
|
|
50
|
-
|
|
60
|
+
arrowProps?: IPopupArrowProps;
|
|
61
|
+
popupData?: IDataAttributes;
|
|
62
|
+
/** @default true, if eventType === click */
|
|
51
63
|
shouldStopPropagation?: boolean;
|
|
52
64
|
/** @default false */
|
|
53
65
|
shouldHideOnScroll?: boolean;
|
|
@@ -60,6 +72,16 @@ export interface IWithPopupProps extends ICommonProps<IWithPopupStyles> {
|
|
|
60
72
|
canBeFlipped?: boolean;
|
|
61
73
|
/** @default false */
|
|
62
74
|
isDisabled?: boolean;
|
|
75
|
+
/** @default false */
|
|
76
|
+
shouldShowArrow?: boolean;
|
|
77
|
+
/** Должна ли минимальная ширина попапа быть равна ширине триггера
|
|
78
|
+
* @default false */
|
|
79
|
+
isMinWidthSameAsTrigger?: boolean;
|
|
80
|
+
hoverOptions?: UseHoverProps;
|
|
81
|
+
clickOptions?: UseClickProps;
|
|
82
|
+
focusOptions?: UseFocusProps;
|
|
83
|
+
dismissOptions?: UseDismissProps;
|
|
84
|
+
transitionOptions?: UseTransitionStatusProps;
|
|
63
85
|
onToggle?: (isActive: boolean, event?: IWithPopupToggleEvent) => void;
|
|
64
86
|
}
|
|
65
87
|
|
|
@@ -71,12 +93,21 @@ export const WithPopup: FC<IWithPopupProps> = ({
|
|
|
71
93
|
placement = eventType === 'click' ? 'bottom-end' : 'top',
|
|
72
94
|
hoverDelay = 0,
|
|
73
95
|
popupOffset = DEFAULT_OFFSET,
|
|
74
|
-
|
|
96
|
+
arrowProps,
|
|
97
|
+
popupData,
|
|
98
|
+
shouldStopPropagation = eventType === 'click',
|
|
75
99
|
shouldHideOnScroll = false,
|
|
76
100
|
shouldRenderInBody = true,
|
|
77
101
|
canBeFlipped = true,
|
|
78
102
|
isTriggerWrapped = eventType === 'hover',
|
|
79
103
|
isDisabled = false,
|
|
104
|
+
shouldShowArrow = false,
|
|
105
|
+
isMinWidthSameAsTrigger = false,
|
|
106
|
+
hoverOptions,
|
|
107
|
+
clickOptions,
|
|
108
|
+
focusOptions,
|
|
109
|
+
dismissOptions,
|
|
110
|
+
transitionOptions,
|
|
80
111
|
tweakStyles,
|
|
81
112
|
data,
|
|
82
113
|
testId,
|
|
@@ -86,6 +117,8 @@ export const WithPopup: FC<IWithPopupProps> = ({
|
|
|
86
117
|
|
|
87
118
|
const [isOpen, setIsOpen] = useState(false);
|
|
88
119
|
|
|
120
|
+
const arrowRef = useRef<SVGSVGElement>(null);
|
|
121
|
+
|
|
89
122
|
const handleToggle = (isActive: boolean, event?: IWithPopupToggleEvent) => {
|
|
90
123
|
event?.stopPropagation();
|
|
91
124
|
if (!isDisabled) {
|
|
@@ -103,7 +136,9 @@ export const WithPopup: FC<IWithPopupProps> = ({
|
|
|
103
136
|
middleware: [
|
|
104
137
|
offset(popupOffset),
|
|
105
138
|
canBeFlipped && flip({ fallbackAxisSideDirection: 'start' }),
|
|
139
|
+
isMinWidthSameAsTrigger && minWidthRelativeToTrigger,
|
|
106
140
|
...middlewares,
|
|
141
|
+
shouldShowArrow && arrow({ element: arrowRef }),
|
|
107
142
|
],
|
|
108
143
|
whileElementsMounted: autoUpdate,
|
|
109
144
|
placement,
|
|
@@ -112,22 +147,27 @@ export const WithPopup: FC<IWithPopupProps> = ({
|
|
|
112
147
|
|
|
113
148
|
const hover = useHover(context, {
|
|
114
149
|
enabled: eventType === 'hover',
|
|
115
|
-
delay:
|
|
150
|
+
delay: { open: hoverDelay, close: 0 },
|
|
116
151
|
handleClose: safePolygon(),
|
|
152
|
+
...hoverOptions,
|
|
117
153
|
});
|
|
118
154
|
|
|
119
|
-
const focus = useFocus(context, { enabled: eventType === 'hover' });
|
|
155
|
+
const focus = useFocus(context, { enabled: eventType === 'hover', ...focusOptions });
|
|
120
156
|
|
|
121
|
-
const click = useClick(context, { enabled: eventType === 'click' });
|
|
157
|
+
const click = useClick(context, { enabled: eventType === 'click', ...clickOptions });
|
|
122
158
|
|
|
123
159
|
const dismiss = useDismiss(context, {
|
|
124
160
|
enabled: eventType === 'click',
|
|
125
161
|
ancestorScroll: shouldHideOnScroll,
|
|
162
|
+
...dismissOptions,
|
|
126
163
|
});
|
|
127
164
|
|
|
128
165
|
const { getFloatingProps, getReferenceProps } = useInteractions([hover, click, focus, dismiss]);
|
|
129
166
|
|
|
130
|
-
const { isMounted, status } = useTransitionStatus(context, {
|
|
167
|
+
const { isMounted, status } = useTransitionStatus(context, {
|
|
168
|
+
duration: { close: 500 },
|
|
169
|
+
...transitionOptions,
|
|
170
|
+
});
|
|
131
171
|
|
|
132
172
|
const referenceProps: IReferenceProps = getReferenceProps({
|
|
133
173
|
ref: refs.setReference,
|
|
@@ -155,8 +195,7 @@ export const WithPopup: FC<IWithPopupProps> = ({
|
|
|
155
195
|
[classes.active]: isOpen,
|
|
156
196
|
})}
|
|
157
197
|
{...referenceProps}
|
|
158
|
-
{...
|
|
159
|
-
{...addDataAttributes(data)}
|
|
198
|
+
{...addDataAttributes(data, testId)}
|
|
160
199
|
>
|
|
161
200
|
{triggerElement}
|
|
162
201
|
</div>
|
|
@@ -165,16 +204,25 @@ export const WithPopup: FC<IWithPopupProps> = ({
|
|
|
165
204
|
)}
|
|
166
205
|
{isMounted && (
|
|
167
206
|
<FloatingPortal
|
|
168
|
-
root={
|
|
207
|
+
root={shouldRenderInBody ? document.body : (refs.reference.current as HTMLElement)}
|
|
169
208
|
>
|
|
170
209
|
<div
|
|
210
|
+
ref={refs.setFloating}
|
|
171
211
|
style={floatingStyles}
|
|
172
212
|
className={classes.popup}
|
|
173
|
-
ref={refs.setFloating}
|
|
174
213
|
{...getFloatingProps()}
|
|
214
|
+
{...addDataAttributes(popupData, testId, 'popup')}
|
|
175
215
|
>
|
|
176
216
|
<div className={classes[`dropdown-${status}`]}>
|
|
177
|
-
{
|
|
217
|
+
{shouldShowArrow && (
|
|
218
|
+
<FloatingArrow
|
|
219
|
+
{...arrowProps}
|
|
220
|
+
ref={arrowRef}
|
|
221
|
+
context={context}
|
|
222
|
+
className={classes.arrow}
|
|
223
|
+
/>
|
|
224
|
+
)}
|
|
225
|
+
{applyAction(children, { floatingContext: context, onClose: handleClose })}
|
|
178
226
|
</div>
|
|
179
227
|
</div>
|
|
180
228
|
</FloatingPortal>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MouseEvent, KeyboardEvent } from 'react';
|
|
2
|
+
import type { FloatingArrowProps, UseFloatingReturn } from '@floating-ui/react';
|
|
2
3
|
import type { IDataAttributesProps, IDomElementInteractions } from '../../types';
|
|
3
4
|
import type { POPUP_EVENT_TYPES } from './constants';
|
|
4
5
|
|
|
@@ -21,5 +22,11 @@ export interface IWithPopupTriggerProps {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export interface IWithPopupChildrenProps {
|
|
25
|
+
floatingContext: UseFloatingReturn['context'];
|
|
24
26
|
onClose: (event?: IWithPopupToggleEvent) => void;
|
|
25
27
|
}
|
|
28
|
+
|
|
29
|
+
export type IPopupArrowProps = Pick<
|
|
30
|
+
FloatingArrowProps,
|
|
31
|
+
'width' | 'height' | 'tipRadius' | 'staticOffset' | 'd' | 'stroke' | 'strokeWidth'
|
|
32
|
+
>;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { ITooltipStyles } from '../Tooltip';
|
|
2
2
|
import { IWithPopupStyles } from '../WithPopup';
|
|
3
3
|
|
|
4
|
+
export const withPopupStyles: IWithPopupStyles = {
|
|
5
|
+
popup: {
|
|
6
|
+
zIndex: 9999,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
|
|
4
10
|
export interface IWithTooltipStyles {
|
|
5
11
|
tweakWithPopup?: IWithPopupStyles;
|
|
6
12
|
tweakTooltip?: ITooltipStyles;
|