@true-engineering/true-react-common-ui-kit 3.24.0 → 3.25.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/README.md +21 -0
- package/dist/components/Select/CustomSelect.stories.d.ts +1 -1
- package/dist/components/Select/MultiSelect.stories.d.ts +2 -2
- package/dist/components/Select/Select.d.ts +14 -9
- package/dist/components/Select/Select.styles.d.ts +5 -5
- package/dist/components/Select/components/SelectList/SelectList.d.ts +7 -6
- package/dist/components/Select/components/SelectList/SelectList.styles.d.ts +1 -1
- package/dist/components/Select/components/SelectListItem/SelectListItem.d.ts +4 -3
- package/dist/components/Select/helpers.d.ts +0 -3
- package/dist/true-react-common-ui-kit.js +140 -114
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +139 -113
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/package.json +2 -2
- package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +21 -38
- package/src/components/Select/CustomSelect.stories.tsx +52 -16
- package/src/components/Select/MultiSelect.stories.tsx +3 -3
- package/src/components/Select/Select.styles.ts +8 -7
- package/src/components/Select/Select.tsx +106 -62
- package/src/components/Select/components/SelectList/SelectList.styles.ts +6 -4
- package/src/components/Select/components/SelectList/SelectList.tsx +25 -29
- package/src/components/Select/components/SelectListItem/SelectListItem.tsx +23 -19
- package/src/components/Select/helpers.ts +0 -7
- package/src/components/TextWithTooltip/TextWithTooltip.tsx +2 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@true-engineering/true-react-common-ui-kit",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0",
|
|
4
4
|
"description": "True Engineering React UI Kit with theming support",
|
|
5
5
|
"author": "True Engineering (https://trueengineering.ru)",
|
|
6
6
|
"keywords": [
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@floating-ui/react": "0.26.12",
|
|
46
|
-
"@true-engineering/true-react-platform-helpers": "0.
|
|
46
|
+
"@true-engineering/true-react-platform-helpers": "0.2.2",
|
|
47
47
|
"clsx": "1.2.1",
|
|
48
48
|
"country-flag-icons": "1.5.5",
|
|
49
49
|
"date-fns": "2.29.3",
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { ReactNode, useState, memo, MouseEvent } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
4
|
-
isEmpty,
|
|
5
|
-
isFunction,
|
|
6
|
-
isNotEmpty,
|
|
7
|
-
isReactNodeNotEmpty,
|
|
8
|
-
} from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
import { applyAction, isEmpty, isNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
9
4
|
import { addDataAttributes } from '../../../../helpers';
|
|
10
5
|
import { useTweakStyles } from '../../../../hooks';
|
|
11
6
|
import { ICommonProps, IDataAttributes } from '../../../../types';
|
|
@@ -68,19 +63,9 @@ function FlexibleTableRowInner<Row extends ITableRow>({
|
|
|
68
63
|
});
|
|
69
64
|
|
|
70
65
|
const [isFocused, setFocused] = useState(false);
|
|
71
|
-
const [nestedComponent, setNestedComponent] = useState<INestedComponent>(() => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
: isExpandableRowComponentInitiallyOpen;
|
|
75
|
-
|
|
76
|
-
const component = isOpen
|
|
77
|
-
? expandableRowComponent?.(item, true, () => {
|
|
78
|
-
setNestedComponent({ isOpen: false });
|
|
79
|
-
})
|
|
80
|
-
: undefined;
|
|
81
|
-
|
|
82
|
-
return isReactNodeNotEmpty(component) ? { isOpen: true, component } : { isOpen: false };
|
|
83
|
-
});
|
|
66
|
+
const [nestedComponent, setNestedComponent] = useState<INestedComponent>(() => ({
|
|
67
|
+
isOpen: applyAction(isExpandableRowComponentInitiallyOpen, item, index),
|
|
68
|
+
}));
|
|
84
69
|
|
|
85
70
|
const isActive = activeRows?.includes(index) ?? false;
|
|
86
71
|
const isEditable = !isLoading && (isNotEmpty(onRowClick) || isNotEmpty(onRowHover));
|
|
@@ -108,33 +93,30 @@ function FlexibleTableRowInner<Row extends ITableRow>({
|
|
|
108
93
|
setFocused(false);
|
|
109
94
|
};
|
|
110
95
|
|
|
111
|
-
const updateNestedComponent = (component?: ReactNode, cellKey?: string) => {
|
|
112
|
-
setNestedComponent(
|
|
113
|
-
component === undefined ? { isOpen: false } : { isOpen: true, component, cellKey },
|
|
114
|
-
);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
96
|
const closeNestedComponent = () => {
|
|
118
97
|
setNestedComponent({ isOpen: false });
|
|
119
98
|
};
|
|
120
99
|
|
|
100
|
+
const updateNestedComponent = (component: ReactNode, cellKey: string) => {
|
|
101
|
+
if (isEmpty(component)) {
|
|
102
|
+
closeNestedComponent();
|
|
103
|
+
} else {
|
|
104
|
+
setNestedComponent({ isOpen: true, component, cellKey });
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
121
108
|
const handleRowClick = () => {
|
|
122
109
|
if (isNotEmpty(uniqueField)) {
|
|
123
110
|
onRowClick?.(item[uniqueField]);
|
|
124
111
|
}
|
|
112
|
+
if (isEmpty(expandableRowComponent)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
125
115
|
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
updateNestedComponent(newNestedComponent);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (isNestedComponentExpanded && isEmpty(nestedComponentCellKey)) {
|
|
135
|
-
closeNestedComponent();
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
116
|
+
if (!isNestedComponentExpanded) {
|
|
117
|
+
setNestedComponent({ isOpen: true });
|
|
118
|
+
} else if (isEmpty(nestedComponentCellKey)) {
|
|
119
|
+
closeNestedComponent();
|
|
138
120
|
}
|
|
139
121
|
};
|
|
140
122
|
|
|
@@ -185,7 +167,8 @@ function FlexibleTableRowInner<Row extends ITableRow>({
|
|
|
185
167
|
{isNestedComponentExpanded && (
|
|
186
168
|
<TableRow className={classes.root}>
|
|
187
169
|
<TableCell className={classes.nestedComponent} colSpan={columns.length}>
|
|
188
|
-
{nestedComponent.component
|
|
170
|
+
{nestedComponent.component ??
|
|
171
|
+
expandableRowComponent?.(item, true, closeNestedComponent)}
|
|
189
172
|
</TableCell>
|
|
190
173
|
</TableRow>
|
|
191
174
|
)}
|
|
@@ -7,7 +7,7 @@ import { Input, type IInputStyles } from '../Input';
|
|
|
7
7
|
import { TextButton } from '../TextButton';
|
|
8
8
|
import { Select, type ISelectProps } from './Select';
|
|
9
9
|
|
|
10
|
-
interface ISelectWithCustomProps<
|
|
10
|
+
interface ISelectWithCustomProps<Option> extends ISelectProps<Option> {
|
|
11
11
|
shouldUsePopper?: boolean;
|
|
12
12
|
shouldRenderInBody?: boolean;
|
|
13
13
|
shouldHideOnScroll?: boolean;
|
|
@@ -25,14 +25,10 @@ const useSelectStyles = createUseStyles({
|
|
|
25
25
|
},
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
width: '100%',
|
|
28
|
+
const useCustomListHeaderStyles = createUseStyles({
|
|
29
|
+
customListHeader: {
|
|
31
30
|
padding: [10, 20],
|
|
32
|
-
|
|
33
|
-
alignSelf: 'stretch',
|
|
34
|
-
backgroundColor: '#ffffff',
|
|
35
|
-
cursor: 'default',
|
|
31
|
+
boxSizing: 'border-box',
|
|
36
32
|
},
|
|
37
33
|
|
|
38
34
|
defaultView: {
|
|
@@ -47,6 +43,16 @@ const useDefaultOptionStyles = createUseStyles({
|
|
|
47
43
|
},
|
|
48
44
|
});
|
|
49
45
|
|
|
46
|
+
const useCustomListFooterStyles = createUseStyles({
|
|
47
|
+
customListFooter: {
|
|
48
|
+
gap: 10,
|
|
49
|
+
padding: [6, 20],
|
|
50
|
+
boxSizing: 'border-box',
|
|
51
|
+
display: 'flex',
|
|
52
|
+
justifyContent: 'center',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
50
56
|
const inputTweakStyles: IInputStyles = {
|
|
51
57
|
inputWrapper: {
|
|
52
58
|
height: 24,
|
|
@@ -67,12 +73,12 @@ const buttonTweakStyles: IButtonStyles = {
|
|
|
67
73
|
},
|
|
68
74
|
};
|
|
69
75
|
|
|
70
|
-
interface
|
|
76
|
+
interface ICustomListHeaderProps {
|
|
71
77
|
onAdd?: (option?: string) => void;
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
function
|
|
75
|
-
const classes =
|
|
80
|
+
function CustomListHeader({ onAdd }: ICustomListHeaderProps) {
|
|
81
|
+
const classes = useCustomListHeaderStyles();
|
|
76
82
|
|
|
77
83
|
const [isAdding, setIsAdding] = useState(false);
|
|
78
84
|
const [inputValue, setInputValue] = useState('');
|
|
@@ -84,7 +90,7 @@ function CustomDefaultOption({ onAdd }: ICustomDefaultOptionProps) {
|
|
|
84
90
|
};
|
|
85
91
|
|
|
86
92
|
return (
|
|
87
|
-
<div className={classes.
|
|
93
|
+
<div className={classes.customListHeader} onClick={(event) => event.stopPropagation()}>
|
|
88
94
|
{!isAdding && (
|
|
89
95
|
<div className={classes.defaultView}>
|
|
90
96
|
<TextButton icon="plus" hasCircleUnderIcon isBold onClick={() => setIsAdding(true)}>
|
|
@@ -109,6 +115,26 @@ function CustomDefaultOption({ onAdd }: ICustomDefaultOptionProps) {
|
|
|
109
115
|
);
|
|
110
116
|
}
|
|
111
117
|
|
|
118
|
+
interface ICustomListFooterProps {
|
|
119
|
+
onReset?: () => void;
|
|
120
|
+
onClear?: () => void;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function CustomListFooter({ onReset, onClear }: ICustomListFooterProps) {
|
|
124
|
+
const classes = useCustomListFooterStyles();
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div className={classes.customListFooter}>
|
|
128
|
+
<Button view="secondary" size="s" onClick={onReset}>
|
|
129
|
+
Reset
|
|
130
|
+
</Button>
|
|
131
|
+
<Button view="secondary" size="s" onClick={onClear}>
|
|
132
|
+
Clear
|
|
133
|
+
</Button>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
112
138
|
function SelectWithCustomProps({
|
|
113
139
|
noMatchesLabel,
|
|
114
140
|
shouldUsePopper,
|
|
@@ -122,13 +148,22 @@ function SelectWithCustomProps({
|
|
|
122
148
|
const [inputValue, setInputValue] = useState<string>();
|
|
123
149
|
const [options, setOptions] = useState<string[]>([]);
|
|
124
150
|
|
|
125
|
-
const
|
|
151
|
+
const handleAdd = (option?: string) => {
|
|
126
152
|
if (isStringNotEmpty(option)) {
|
|
127
153
|
setOptions((prevOptions) => [...prevOptions, option]);
|
|
128
154
|
}
|
|
129
155
|
};
|
|
130
156
|
|
|
131
|
-
const
|
|
157
|
+
const handleReset = () => {
|
|
158
|
+
setInputValue(undefined);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const handleClear = () => {
|
|
162
|
+
setInputValue(undefined);
|
|
163
|
+
setOptions([]);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const handleRemove = (option: string) => {
|
|
132
167
|
setOptions((prevOptions) => prevOptions.filter((entry) => entry !== option));
|
|
133
168
|
};
|
|
134
169
|
|
|
@@ -142,7 +177,7 @@ function SelectWithCustomProps({
|
|
|
142
177
|
onClick={(event) => {
|
|
143
178
|
event.stopPropagation();
|
|
144
179
|
|
|
145
|
-
|
|
180
|
+
handleRemove(value);
|
|
146
181
|
}}
|
|
147
182
|
/>
|
|
148
183
|
</div>
|
|
@@ -159,7 +194,8 @@ function SelectWithCustomProps({
|
|
|
159
194
|
return (
|
|
160
195
|
<Select
|
|
161
196
|
{...props}
|
|
162
|
-
|
|
197
|
+
header={<CustomListHeader onAdd={handleAdd} />}
|
|
198
|
+
footer={<CustomListFooter onReset={handleReset} onClear={handleClear} />}
|
|
163
199
|
noMatchesLabel={isStringNotEmpty(noMatchesLabel) ? noMatchesLabel : undefined}
|
|
164
200
|
tweakStyles={{
|
|
165
201
|
tweakSelectList: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReactNode, useEffect, useState } from 'react';
|
|
2
2
|
import { isStringNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
3
3
|
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
4
|
-
import { Select, ISelectProps } from './Select';
|
|
4
|
+
import { Select, ISelectProps, IMultipleSelectProps } from './Select';
|
|
5
5
|
|
|
6
6
|
interface ObjectValue {
|
|
7
7
|
name: string;
|
|
@@ -60,7 +60,7 @@ const objectOptions: ObjectValue[] = [
|
|
|
60
60
|
const getRandomInt = (min: number, max: number) =>
|
|
61
61
|
Math.floor(Math.random() * (Math.floor(max) - Math.ceil(min))) + Math.ceil(min);
|
|
62
62
|
|
|
63
|
-
interface ISelectWithCustomProps<T> extends
|
|
63
|
+
interface ISelectWithCustomProps<T> extends IMultipleSelectProps<T> {
|
|
64
64
|
valuesType: 'strings' | 'objects';
|
|
65
65
|
shouldUseReactNodes?: boolean;
|
|
66
66
|
shouldUsePopper?: boolean;
|
|
@@ -160,7 +160,7 @@ function SelectWithCustomProps<T>({
|
|
|
160
160
|
return (
|
|
161
161
|
<Select
|
|
162
162
|
{...rest}
|
|
163
|
-
{...(props as unknown as
|
|
163
|
+
{...(props as unknown as IMultipleSelectProps<any>)}
|
|
164
164
|
{...(shouldRenderSearchInputInList && {
|
|
165
165
|
searchInput: { shouldRenderInList: true },
|
|
166
166
|
})}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { mergeStyles } from '@true-engineering/true-react-platform-helpers';
|
|
2
|
-
import {
|
|
3
|
-
import { IInputStyles } from '../Input';
|
|
4
|
-
import { ISearchInputStyles } from '../SearchInput';
|
|
5
|
-
import { ISelectListStyles } from './components';
|
|
2
|
+
import { animations, createThemedStyles, type ITweakStyles } from '../../theme';
|
|
3
|
+
import { type IInputStyles } from '../Input';
|
|
4
|
+
import { type ISearchInputStyles } from '../SearchInput';
|
|
5
|
+
import { type ISelectListStyles } from './components';
|
|
6
6
|
|
|
7
7
|
export const useStyles = createThemedStyles('Select', {
|
|
8
8
|
root: {
|
|
@@ -26,7 +26,7 @@ export const useStyles = createThemedStyles('Select', {
|
|
|
26
26
|
|
|
27
27
|
withoutPopper: {
|
|
28
28
|
position: 'absolute',
|
|
29
|
-
top: 'calc(100% + 6px)',
|
|
29
|
+
top: 'calc(var(--dropdown-offset, 100%) + 6px)',
|
|
30
30
|
},
|
|
31
31
|
|
|
32
32
|
listWrapperInBody: {
|
|
@@ -43,7 +43,8 @@ export const useStyles = createThemedStyles('Select', {
|
|
|
43
43
|
height: 20,
|
|
44
44
|
cursor: 'pointer',
|
|
45
45
|
zIndex: 1,
|
|
46
|
-
transition:
|
|
46
|
+
transition: animations.defaultTransition,
|
|
47
|
+
transitionProperty: 'transform',
|
|
47
48
|
},
|
|
48
49
|
|
|
49
50
|
activeArrow: {
|
|
@@ -111,7 +112,7 @@ export const getInputStyles = ({
|
|
|
111
112
|
isMultiSelect,
|
|
112
113
|
}: {
|
|
113
114
|
hasReadonlyInput: boolean;
|
|
114
|
-
isMultiSelect
|
|
115
|
+
isMultiSelect?: boolean;
|
|
115
116
|
}): IInputStyles => {
|
|
116
117
|
if (hasReadonlyInput && isMultiSelect) {
|
|
117
118
|
return readonlyMultiSelectStyles;
|