@true-engineering/true-react-common-ui-kit 3.0.0-alpha.9 → 3.0.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 +26 -0
- package/dist/components/Button/Button.d.ts +2 -1
- package/dist/components/Button/Button.styles.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
- package/dist/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.d.ts +1 -1
- package/dist/components/Description/Description.styles.d.ts +1 -1
- package/dist/components/FiltersPane/FiltersPane.styles.d.ts +1 -1
- package/dist/components/FiltersPane/components/Filter/Filter.d.ts +1 -1
- package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +2 -2
- package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +3 -3
- package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.d.ts +1 -1
- package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +4 -4
- package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.d.ts +1 -1
- package/dist/components/FiltersPane/constants.d.ts +1 -1
- package/dist/components/FiltersPane/types.d.ts +1 -1
- package/dist/components/FlexibleTable/FlexibleTable.d.ts +3 -2
- package/dist/components/FlexibleTable/FlexibleTable.styles.d.ts +2 -2
- package/dist/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.d.ts +2 -3
- package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +1 -1
- package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.d.ts +1 -1
- package/dist/components/FlexibleTable/helpers.d.ts +3 -0
- package/dist/components/FlexibleTable/types.d.ts +1 -1
- package/dist/components/Icon/helpers.d.ts +1 -1
- package/dist/components/Icon/icons-list.d.ts +1 -1
- package/dist/components/Icon/index.d.ts +1 -0
- package/dist/{helpers/snippets.d.ts → components/Icon/snippet.d.ts} +1 -1
- package/dist/components/Icon/types.d.ts +2 -1
- package/dist/components/Input/Input.d.ts +2 -1
- package/dist/components/Input/Input.styles.d.ts +1 -1
- package/dist/components/List/List.d.ts +3 -3
- package/dist/components/List/components/ListItem/ListItem.d.ts +15 -0
- package/dist/components/List/components/ListItem/ListItem.styles.d.ts +3 -0
- package/dist/components/List/components/ListItem/index.d.ts +2 -0
- package/dist/components/List/components/index.d.ts +1 -0
- package/dist/components/List/index.d.ts +1 -1
- package/dist/components/Modal/Modal.styles.d.ts +1 -1
- package/dist/components/MoreMenu/MoreMenu.styles.d.ts +1 -1
- package/dist/components/MultiSelect/MultiSelect.styles.d.ts +1 -1
- package/dist/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.d.ts +2 -1
- package/dist/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.styles.d.ts +1 -1
- package/dist/components/MultiSelectList/MultiSelectList.styles.d.ts +1 -1
- package/dist/components/Notification/Notification.styles.d.ts +1 -1
- package/dist/components/NumberInput/helpers.d.ts +1 -1
- package/dist/components/PhoneInput/PhoneInput.styles.d.ts +1 -1
- package/dist/components/PhoneInput/index.d.ts +0 -1
- package/dist/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.d.ts +5 -5
- package/dist/components/Select/Select.d.ts +2 -1
- package/dist/components/Select/Select.styles.d.ts +7 -7
- package/dist/components/Select/components/SelectList/SelectList.styles.d.ts +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +7 -0
- package/dist/components/Skeleton/Skeleton.styles.d.ts +3 -0
- package/dist/components/Skeleton/index.d.ts +2 -0
- package/dist/components/Switch/Switch.styles.d.ts +1 -1
- package/dist/components/TextArea/TextArea.styles.d.ts +1 -1
- package/dist/components/ThemedPreloader/ThemedPreloader.styles.d.ts +1 -1
- package/dist/components/Toaster/Toaster.styles.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.styles.d.ts +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/phone-info.d.ts +2 -0
- package/dist/helpers/phone.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-merged-refs.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/theme/types.d.ts +3 -1
- package/dist/true-react-common-ui-kit.js +24269 -24084
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +24268 -24083
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/dist/types.d.ts +0 -3
- package/package.json +2 -1
- package/src/components/Button/Button.tsx +2 -2
- package/src/components/FiltersPane/components/Filter/Filter.tsx +1 -1
- package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +1 -1
- package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.ts +1 -1
- package/src/components/FiltersPane/constants.ts +1 -1
- package/src/components/FiltersPane/types.ts +1 -1
- package/src/components/FlexibleTable/FlexibleTable.stories.tsx +1 -0
- package/src/components/FlexibleTable/FlexibleTable.styles.ts +6 -1
- package/src/components/FlexibleTable/FlexibleTable.tsx +118 -55
- package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.tsx +26 -30
- package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.ts +4 -0
- package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +13 -12
- package/src/components/FlexibleTable/helpers.ts +15 -0
- package/src/components/FlexibleTable/types.ts +1 -1
- package/src/components/Icon/{helpers.ts → helpers.tsx} +1 -1
- package/src/components/Icon/icons-list.ts +30 -0
- package/src/components/Icon/index.ts +1 -0
- package/src/{helpers/snippets.tsx → components/Icon/snippet.tsx} +2 -2
- package/src/components/Icon/types.ts +3 -1
- package/src/components/Input/Input.tsx +2 -3
- package/src/components/List/List.stories.tsx +11 -4
- package/src/components/List/List.tsx +9 -32
- package/src/components/List/components/ListItem/ListItem.styles.ts +47 -0
- package/src/components/List/components/ListItem/ListItem.tsx +57 -0
- package/src/components/List/components/ListItem/index.ts +2 -0
- package/src/components/List/components/index.ts +1 -0
- package/src/components/List/index.ts +1 -1
- package/src/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.tsx +3 -2
- package/src/components/NumberInput/helpers.ts +1 -1
- package/src/components/PhoneInput/PhoneInput.stories.tsx +1 -1
- package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +1 -1
- package/src/components/PhoneInput/index.ts +0 -1
- package/src/components/Select/Select.tsx +2 -2
- package/src/components/Skeleton/Skeleton.stories.tsx +19 -0
- package/src/components/Skeleton/Skeleton.styles.ts +46 -0
- package/src/components/Skeleton/Skeleton.tsx +12 -0
- package/src/components/Skeleton/index.ts +2 -0
- package/src/components/index.ts +1 -0
- package/src/constants/index.ts +1 -0
- package/src/{components/PhoneInput → constants}/phone-info.ts +1 -1
- package/src/helpers/phone.ts +2 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-merged-refs.ts +4 -0
- package/src/index.ts +1 -1
- package/src/theme/types.ts +4 -0
- package/src/types.ts +0 -4
- package/dist/components/List/types.d.ts +0 -12
- package/dist/components/PhoneInput/phone-info.d.ts +0 -2
- package/src/components/List/types.ts +0 -13
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
1
|
import { Modifier, Placement } from 'react-overlays/usePopper';
|
|
3
|
-
import type { IIconType } from './components';
|
|
4
2
|
export interface IDataAttributes {
|
|
5
3
|
[key: string]: unknown;
|
|
6
4
|
}
|
|
@@ -19,4 +17,3 @@ export interface IDropdownWithPopperOptions {
|
|
|
19
17
|
placement?: Placement;
|
|
20
18
|
flipOptions?: Record<string, any>;
|
|
21
19
|
}
|
|
22
|
-
export declare type IIcon = IIconType | ReactElement;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@true-engineering/true-react-common-ui-kit",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "True Engineering React UI Kit with theming support",
|
|
5
5
|
"author": "True Engineering (https://trueengineering.ru)",
|
|
6
6
|
"keywords": [
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"eslint": "8.36.0",
|
|
84
84
|
"eslint-config-prettier": "8.7.0",
|
|
85
85
|
"eslint-plugin-react": "7.32.2",
|
|
86
|
+
"eslint-plugin-import": "2.29.0",
|
|
86
87
|
"prettier": "2.8.3",
|
|
87
88
|
"rollup-plugin-swc3": "0.3.0",
|
|
88
89
|
"typescript": "4.9.3",
|
|
@@ -2,9 +2,9 @@ import { ReactNode, ButtonHTMLAttributes, MouseEvent, forwardRef } from 'react';
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { addDataTestId, isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
4
4
|
import { addDataAttributes } from '../../helpers';
|
|
5
|
-
import { renderIcon } from '../../helpers/snippets';
|
|
6
5
|
import { useTweakStyles } from '../../hooks';
|
|
7
|
-
import { ICommonProps
|
|
6
|
+
import { ICommonProps } from '../../types';
|
|
7
|
+
import { renderIcon, IIcon } from '../Icon';
|
|
8
8
|
import { ThemedPreloader, IThemedPreloaderProps } from '../ThemedPreloader';
|
|
9
9
|
import { IButtonSize, IButtonView } from './types';
|
|
10
10
|
import { useStyles, IButtonStyles, getPreloaderStyles } from './Button.styles';
|
|
@@ -9,7 +9,7 @@ import { FilterMultiSelect } from '../FilterMultiSelect';
|
|
|
9
9
|
import { FilterSelect } from '../FilterSelect';
|
|
10
10
|
import { FilterWithDates } from '../FilterWithDates';
|
|
11
11
|
import { FilterWithPeriod } from '../FilterWithPeriod';
|
|
12
|
-
import { IFilterWrapperProps } from '../FilterWrapper';
|
|
12
|
+
import type { IFilterWrapperProps } from '../FilterWrapper';
|
|
13
13
|
|
|
14
14
|
export interface IFilterProps<Values, Key extends keyof Values>
|
|
15
15
|
extends IFilterWrapperProps<Values, Key> {
|
|
@@ -5,7 +5,7 @@ import { IMultiSelectListValues } from '../../../MultiSelectList';
|
|
|
5
5
|
import { DEFAULT_DATE_FORMAT } from '../../constants';
|
|
6
6
|
import { defaultConvertFunction, getLocale } from '../../helpers';
|
|
7
7
|
import { IDateRangeConfigItem, IFilterWithDatesValue, IPeriod } from '../../types';
|
|
8
|
-
import { IFilterWrapperProps } from '../FilterWrapper';
|
|
8
|
+
import type { IFilterWrapperProps } from '../FilterWrapper';
|
|
9
9
|
import { IFilterValueViewStyles, useStyles } from './FilterValueView.styles';
|
|
10
10
|
|
|
11
11
|
export function FilterValueView<Values, Key extends keyof Values>({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { colors, createThemedStyles, ITweakStyles } from '../../../../theme';
|
|
2
|
-
import { IFilterValueViewStyles } from '../FilterValueView';
|
|
2
|
+
import type { IFilterValueViewStyles } from '../FilterValueView';
|
|
3
3
|
import { FILTER_HEIGHT } from '../../FiltersPane.styles';
|
|
4
4
|
|
|
5
5
|
export const useStyles = createThemedStyles('FilterWrapper', {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { rgba } from '../../helpers';
|
|
2
2
|
import { colors, ITweakStyles, createThemedStyles } from '../../theme';
|
|
3
|
-
import { IFlexibleTableRowStyles } from './components';
|
|
3
|
+
import type { IFlexibleTableRowStyles } from './components';
|
|
4
4
|
|
|
5
5
|
export const STICKY_SHADOW_PADDING = 12;
|
|
6
6
|
|
|
@@ -90,6 +90,11 @@ export const useStyles = createThemedStyles('FlexibleTable', {
|
|
|
90
90
|
headerSecond: {
|
|
91
91
|
paddingLeft: STICKY_SHADOW_PADDING,
|
|
92
92
|
},
|
|
93
|
+
|
|
94
|
+
skeleton: {
|
|
95
|
+
height: 21,
|
|
96
|
+
padding: [14, 7],
|
|
97
|
+
},
|
|
93
98
|
});
|
|
94
99
|
|
|
95
100
|
export type IFlexibleTableStyles = ITweakStyles<
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import { ReactNode, RefObject, useCallback, useEffect,
|
|
1
|
+
import { ReactNode, RefObject, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addDataTestId,
|
|
5
|
+
indexMap,
|
|
6
|
+
isArrayNotEmpty,
|
|
7
|
+
isEmpty,
|
|
8
|
+
isNotEmpty,
|
|
9
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
4
10
|
import { addDataAttributes } from '../../helpers';
|
|
5
|
-
import { useTweakStyles } from '../../hooks';
|
|
11
|
+
import { useMergedRefs, useTweakStyles } from '../../hooks';
|
|
6
12
|
import { ICommonProps } from '../../types';
|
|
13
|
+
import { Skeleton } from '../Skeleton';
|
|
7
14
|
import { ThemedPreloader } from '../ThemedPreloader';
|
|
8
15
|
import { FlexibleTableRow } from './components';
|
|
16
|
+
import { hasHorizontalScrollBar } from './helpers';
|
|
9
17
|
import { IFlexibleTableConfigType, IInfinityScrollConfig, ITitleComponent } from './types';
|
|
10
18
|
import { useStyles, IFlexibleTableStyles } from './FlexibleTable.styles';
|
|
11
19
|
|
|
@@ -16,7 +24,7 @@ export interface IFlexibleTableProps<Values extends Record<string, any>>
|
|
|
16
24
|
headerContent?: Partial<Record<keyof Values, any>>;
|
|
17
25
|
enabledColumns?: Array<keyof Values>;
|
|
18
26
|
activeRows?: number[];
|
|
19
|
-
config
|
|
27
|
+
config: IFlexibleTableConfigType<Values>;
|
|
20
28
|
isHorizontallyScrollable?: boolean;
|
|
21
29
|
isFirstColumnSticky?: boolean;
|
|
22
30
|
infinityScrollConfig?: IInfinityScrollConfig;
|
|
@@ -25,6 +33,7 @@ export interface IFlexibleTableProps<Values extends Record<string, any>>
|
|
|
25
33
|
*/
|
|
26
34
|
uniqueField?: keyof Values;
|
|
27
35
|
onHeadClick?: (column: keyof Values) => void;
|
|
36
|
+
isLoading?: boolean;
|
|
28
37
|
// TODO: Заменить string на Generic Values[uniqueField]
|
|
29
38
|
onRowClick?: (id: string) => void;
|
|
30
39
|
onRowHover?: (id?: string) => void;
|
|
@@ -46,6 +55,7 @@ export function FlexibleTable<Values extends Record<string, any>>({
|
|
|
46
55
|
isFirstColumnSticky,
|
|
47
56
|
infinityScrollConfig,
|
|
48
57
|
uniqueField,
|
|
58
|
+
isLoading,
|
|
49
59
|
onHeadClick,
|
|
50
60
|
onRowHover,
|
|
51
61
|
onRowClick,
|
|
@@ -63,11 +73,44 @@ export function FlexibleTable<Values extends Record<string, any>>({
|
|
|
63
73
|
currentComponentName: 'FlexibleTable',
|
|
64
74
|
});
|
|
65
75
|
|
|
66
|
-
const [isHorizontallyScrolled, setIsHorizontallyScrolled] = useState(false);
|
|
67
|
-
|
|
68
76
|
const observer = useRef<IntersectionObserver>();
|
|
69
77
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
70
78
|
|
|
79
|
+
const showedColumns = useMemo(
|
|
80
|
+
() => enabledColumns ?? Object.keys(config),
|
|
81
|
+
[enabledColumns, config],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const getDataScrollAttributeSetter = useCallback(
|
|
85
|
+
(key: string, setter: (el: HTMLDivElement) => boolean) => (el?: HTMLDivElement) => {
|
|
86
|
+
if (isHorizontallyScrollable && isNotEmpty(el) && setter(el)) {
|
|
87
|
+
el.dataset[key] = 'true';
|
|
88
|
+
} else {
|
|
89
|
+
el?.removeAttribute(`data-${key}`);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
[isHorizontallyScrollable],
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Когда таблица имеет скроллбар - добавляем аттрибут scrollable
|
|
96
|
+
const setHasScrollBarAttribute = useCallback(
|
|
97
|
+
getDataScrollAttributeSetter('scrollable', hasHorizontalScrollBar),
|
|
98
|
+
[getDataScrollAttributeSetter],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Когда таблица проскроллена - добавляем аттрибут scrolled
|
|
102
|
+
const setIsScrolledAttribute = useCallback(
|
|
103
|
+
getDataScrollAttributeSetter('scrolled', (el) => el.scrollLeft > 0),
|
|
104
|
+
[getDataScrollAttributeSetter],
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const ref = useMergedRefs([
|
|
108
|
+
refForScroll,
|
|
109
|
+
scrollRef,
|
|
110
|
+
setHasScrollBarAttribute,
|
|
111
|
+
setIsScrolledAttribute,
|
|
112
|
+
]);
|
|
113
|
+
|
|
71
114
|
const initIntersectionObserver = useCallback(
|
|
72
115
|
(node: HTMLDivElement) => {
|
|
73
116
|
if (infinityScrollConfig) {
|
|
@@ -101,27 +144,34 @@ export function FlexibleTable<Values extends Record<string, any>>({
|
|
|
101
144
|
);
|
|
102
145
|
|
|
103
146
|
useEffect(() => {
|
|
104
|
-
const scrollContainer =
|
|
105
|
-
if (scrollContainer
|
|
147
|
+
const scrollContainer = scrollRef.current;
|
|
148
|
+
if (isEmpty(scrollContainer) || !isHorizontallyScrollable) {
|
|
106
149
|
return;
|
|
107
150
|
}
|
|
108
|
-
|
|
109
|
-
|
|
151
|
+
|
|
152
|
+
const scrollHandler = () => {
|
|
153
|
+
setIsScrolledAttribute(scrollContainer);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const resizeHandler = () => {
|
|
157
|
+
setHasScrollBarAttribute(scrollContainer);
|
|
110
158
|
};
|
|
159
|
+
|
|
111
160
|
scrollContainer.addEventListener('scroll', scrollHandler);
|
|
112
|
-
|
|
113
|
-
|
|
161
|
+
window.addEventListener('resize', resizeHandler);
|
|
162
|
+
|
|
163
|
+
return () => {
|
|
164
|
+
scrollContainer.removeEventListener('scroll', scrollHandler);
|
|
165
|
+
window.removeEventListener('resize', resizeHandler);
|
|
166
|
+
};
|
|
167
|
+
}, [scrollRef, setIsScrolledAttribute, setHasScrollBarAttribute]);
|
|
114
168
|
|
|
115
169
|
return (
|
|
116
|
-
<div
|
|
117
|
-
ref={refForScroll ?? scrollRef}
|
|
118
|
-
className={clsx({ [classes.scroll]: isHorizontallyScrollable })}
|
|
119
|
-
data-scrolled={isHorizontallyScrolled ? true : undefined}
|
|
120
|
-
>
|
|
170
|
+
<div ref={ref} className={clsx({ [classes.scroll]: isHorizontallyScrollable })}>
|
|
121
171
|
<table className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
|
|
122
172
|
<thead>
|
|
123
173
|
<tr className={classes.headerRow}>
|
|
124
|
-
{
|
|
174
|
+
{showedColumns.map((key, i) => {
|
|
125
175
|
const itemConfig = config?.[key];
|
|
126
176
|
|
|
127
177
|
let titleContent = itemConfig?.title ?? '';
|
|
@@ -134,8 +184,8 @@ export function FlexibleTable<Values extends Record<string, any>>({
|
|
|
134
184
|
return (
|
|
135
185
|
<th
|
|
136
186
|
className={clsx(classes.header, {
|
|
137
|
-
[classes.headerSticky]: isFirstColumnSticky &&
|
|
138
|
-
[classes.headerSecond]: isFirstColumnSticky &&
|
|
187
|
+
[classes.headerSticky]: isFirstColumnSticky && i === 0,
|
|
188
|
+
[classes.headerSecond]: isFirstColumnSticky && i === 1,
|
|
139
189
|
})}
|
|
140
190
|
style={{
|
|
141
191
|
minWidth: itemConfig?.minWidth,
|
|
@@ -153,42 +203,55 @@ export function FlexibleTable<Values extends Record<string, any>>({
|
|
|
153
203
|
</tr>
|
|
154
204
|
</thead>
|
|
155
205
|
<tbody>
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
206
|
+
{isLoading ? (
|
|
207
|
+
indexMap(6, (i) => (
|
|
208
|
+
<tr key={i}>
|
|
209
|
+
{showedColumns.map((_, j) => (
|
|
210
|
+
<td key={j} className={classes.skeleton}>
|
|
211
|
+
<Skeleton />
|
|
212
|
+
</td>
|
|
213
|
+
))}
|
|
164
214
|
</tr>
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
215
|
+
))
|
|
216
|
+
) : (
|
|
217
|
+
<>
|
|
218
|
+
{!isArrayNotEmpty(content) &&
|
|
219
|
+
nothingFoundContent !== undefined &&
|
|
220
|
+
!infinityScrollConfig?.isLoading &&
|
|
221
|
+
(infinityScrollConfig?.isLastPage === undefined ||
|
|
222
|
+
infinityScrollConfig.isLastPage) && (
|
|
223
|
+
<tr>
|
|
224
|
+
<td colSpan={showedColumns.length}>{nothingFoundContent}</td>
|
|
225
|
+
</tr>
|
|
226
|
+
)}
|
|
227
|
+
|
|
228
|
+
{content.map((item, i) => (
|
|
229
|
+
<FlexibleTableRow
|
|
230
|
+
item={item}
|
|
231
|
+
uniqueField={uniqueField}
|
|
232
|
+
isActive={activeRows?.includes(i) ?? false}
|
|
233
|
+
isFirstColumnSticky={isFirstColumnSticky}
|
|
234
|
+
onRowClick={onRowClick}
|
|
235
|
+
onRowHover={onRowHover}
|
|
236
|
+
enabledColumns={enabledColumns}
|
|
237
|
+
config={config}
|
|
238
|
+
key={isNotEmpty(uniqueField) ? item[uniqueField] : i}
|
|
239
|
+
rowAttributes={rowAttributes}
|
|
240
|
+
tweakStyles={tweakTableRowStyles}
|
|
241
|
+
expandableRowComponent={expandableRowComponent}
|
|
242
|
+
/>
|
|
243
|
+
))}
|
|
244
|
+
|
|
245
|
+
{infinityScrollConfig !== undefined && !infinityScrollConfig.isLastPage && (
|
|
246
|
+
<tr>
|
|
247
|
+
<td colSpan={showedColumns.length}>
|
|
248
|
+
<div ref={initIntersectionObserver} className={classes.loader}>
|
|
249
|
+
<ThemedPreloader type="dots" />
|
|
250
|
+
</div>
|
|
251
|
+
</td>
|
|
252
|
+
</tr>
|
|
253
|
+
)}
|
|
254
|
+
</>
|
|
192
255
|
)}
|
|
193
256
|
</tbody>
|
|
194
257
|
</table>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
4
4
|
import type { ICommonProps } from '../../../../types';
|
|
5
|
-
import {
|
|
5
|
+
import { formatCellContent } from '../../helpers';
|
|
6
6
|
import type { IFlexibleTableConfigType } from '../../types';
|
|
7
7
|
import { useStyles, IFlexibleTableCellStyles } from './FlexibleTableCell.styles';
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ export interface IFlexibleTableCellProps<Values extends Record<string, any>>
|
|
|
10
10
|
extends Pick<ICommonProps<IFlexibleTableCellStyles>, 'tweakStyles'> {
|
|
11
11
|
item: Values;
|
|
12
12
|
columnName: keyof Values;
|
|
13
|
-
config
|
|
13
|
+
config: IFlexibleTableConfigType<Values>;
|
|
14
14
|
isFocusedRow?: boolean;
|
|
15
15
|
isSecond?: boolean;
|
|
16
16
|
isSticky?: boolean;
|
|
@@ -19,7 +19,7 @@ export interface IFlexibleTableCellProps<Values extends Record<string, any>>
|
|
|
19
19
|
onSetNestedComponent(component?: ReactNode): void;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function FlexibleTableCell<Values extends Record<string, any>>({
|
|
22
|
+
export function FlexibleTableCell<Values extends Record<string, any>>({
|
|
23
23
|
item,
|
|
24
24
|
columnName,
|
|
25
25
|
config,
|
|
@@ -33,41 +33,37 @@ function FlexibleTableCell<Values extends Record<string, any>>({
|
|
|
33
33
|
}: IFlexibleTableCellProps<Values>): JSX.Element {
|
|
34
34
|
const classes = useStyles({ theme: tweakStyles });
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
let content = null;
|
|
36
|
+
const { component, cellAlign, position, right, left, cellVerticalAlign } =
|
|
37
|
+
config[columnName] ?? {};
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
const ValueComponent = itemConfig?.component;
|
|
42
|
-
content = ValueComponent({
|
|
43
|
-
value,
|
|
44
|
-
row: item,
|
|
45
|
-
isFocusedRow,
|
|
46
|
-
isNestedComponentExpanded,
|
|
47
|
-
isRowNestedComponentExpanded,
|
|
48
|
-
onSetNestedComponent,
|
|
49
|
-
});
|
|
50
|
-
} else if (typeof value === 'string' || typeof value === 'number') {
|
|
51
|
-
content = value;
|
|
52
|
-
} else if ((value as any) instanceof Date) {
|
|
53
|
-
content = format(value, itemConfig?.dateFormat || DEFAULT_DATE_FORMAT);
|
|
54
|
-
}
|
|
39
|
+
const value = item[columnName];
|
|
55
40
|
|
|
56
41
|
return (
|
|
57
42
|
<td
|
|
58
43
|
key={columnName as string}
|
|
59
44
|
className={clsx(classes.root, { [classes.sticky]: isSticky, [classes.second]: isSecond })}
|
|
60
45
|
style={{
|
|
61
|
-
textAlign:
|
|
62
|
-
position: isSticky ? 'sticky' :
|
|
63
|
-
right
|
|
64
|
-
left: isSticky ? 0 :
|
|
65
|
-
verticalAlign:
|
|
46
|
+
textAlign: cellAlign,
|
|
47
|
+
position: isSticky ? 'sticky' : position,
|
|
48
|
+
right,
|
|
49
|
+
left: isSticky ? 0 : left,
|
|
50
|
+
verticalAlign: cellVerticalAlign,
|
|
66
51
|
}}
|
|
67
52
|
>
|
|
68
|
-
{
|
|
53
|
+
{isNotEmpty(value) && (
|
|
54
|
+
<>
|
|
55
|
+
{isNotEmpty(component)
|
|
56
|
+
? component({
|
|
57
|
+
value,
|
|
58
|
+
row: item,
|
|
59
|
+
isFocusedRow,
|
|
60
|
+
isNestedComponentExpanded,
|
|
61
|
+
isRowNestedComponentExpanded,
|
|
62
|
+
onSetNestedComponent,
|
|
63
|
+
})
|
|
64
|
+
: formatCellContent(value, config[columnName])}
|
|
65
|
+
</>
|
|
66
|
+
)}
|
|
69
67
|
</td>
|
|
70
68
|
);
|
|
71
69
|
}
|
|
72
|
-
|
|
73
|
-
export default FlexibleTableCell;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ReactNode, useState, memo } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
+
import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
3
4
|
import { addDataAttributes } from '../../../../helpers';
|
|
4
5
|
import { useTweakStyles } from '../../../../hooks';
|
|
5
6
|
import { ICommonProps, IDataAttributes } from '../../../../types';
|
|
6
7
|
import { IFlexibleTableConfigType, INestedComponent } from '../../types';
|
|
7
|
-
import FlexibleTableCell from '../FlexibleTableCell
|
|
8
|
+
import { FlexibleTableCell } from '../FlexibleTableCell';
|
|
8
9
|
import { useStyles, IFlexibleTableRowStyles } from './FlexibleTableRow.styles';
|
|
9
10
|
|
|
10
11
|
// TODO: Заменить Record<string, any> на Record<string, unknown>
|
|
@@ -14,7 +15,7 @@ export interface IFlexibleTableRowProps<Values extends Record<string, any>>
|
|
|
14
15
|
uniqueField?: keyof Values;
|
|
15
16
|
isFirstColumnSticky?: boolean;
|
|
16
17
|
isActive: boolean;
|
|
17
|
-
config
|
|
18
|
+
config: IFlexibleTableConfigType<Values>;
|
|
18
19
|
enabledColumns?: Array<keyof Values>;
|
|
19
20
|
rowAttributes?: Array<keyof Values>;
|
|
20
21
|
expandableRowComponent?(item: Values, isOpen: boolean, close: () => void): ReactNode;
|
|
@@ -81,7 +82,7 @@ function FlexibleTableRowInner<Values extends Record<string, any>>({
|
|
|
81
82
|
onRowClick?.(item[uniqueField]);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
if (expandableRowComponent
|
|
85
|
+
if (isNotEmpty(expandableRowComponent)) {
|
|
85
86
|
const newNestedComponent = expandableRowComponent(item, true, closeNestedComponent);
|
|
86
87
|
|
|
87
88
|
if (!nestedComponent.isOpen && newNestedComponent !== null) {
|
|
@@ -96,16 +97,16 @@ function FlexibleTableRowInner<Values extends Record<string, any>>({
|
|
|
96
97
|
}
|
|
97
98
|
};
|
|
98
99
|
|
|
99
|
-
const items = enabledColumns ?? Object.keys(
|
|
100
|
+
const items = enabledColumns ?? Object.keys(config);
|
|
100
101
|
|
|
101
102
|
return (
|
|
102
103
|
<>
|
|
103
104
|
<tr
|
|
104
|
-
className={clsx(
|
|
105
|
-
classes.
|
|
106
|
-
|
|
107
|
-
(onRowClick
|
|
108
|
-
)}
|
|
105
|
+
className={clsx(classes.root, {
|
|
106
|
+
[classes.active]: isActive,
|
|
107
|
+
[classes.editable]: isNotEmpty(onRowClick) || isNotEmpty(onRowHover),
|
|
108
|
+
[classes.clickable]: isNotEmpty(onRowClick) || isNotEmpty(expandableRowComponent),
|
|
109
|
+
})}
|
|
109
110
|
onMouseEnter={(e) => {
|
|
110
111
|
if (uniqueField !== undefined && onRowHover !== undefined) {
|
|
111
112
|
e.stopPropagation();
|
|
@@ -120,11 +121,11 @@ function FlexibleTableRowInner<Values extends Record<string, any>>({
|
|
|
120
121
|
isExpandableComponentActive: nestedComponent.isOpen ? true : undefined,
|
|
121
122
|
})}
|
|
122
123
|
>
|
|
123
|
-
{items.map((key,
|
|
124
|
+
{items.map((key, i) => (
|
|
124
125
|
<FlexibleTableCell
|
|
125
126
|
columnName={key}
|
|
126
|
-
isSticky={isFirstColumnSticky &&
|
|
127
|
-
isSecond={isFirstColumnSticky &&
|
|
127
|
+
isSticky={isFirstColumnSticky && i === 0}
|
|
128
|
+
isSecond={isFirstColumnSticky && i === 1}
|
|
128
129
|
key={key as string}
|
|
129
130
|
item={item}
|
|
130
131
|
config={config}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { format } from 'date-fns';
|
|
2
|
+
import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
import { DEFAULT_DATE_FORMAT } from './constants';
|
|
4
|
+
import { IFlexibleTableConfigType } from './types';
|
|
5
|
+
|
|
6
|
+
export const hasHorizontalScrollBar = (el: HTMLElement | null | undefined): boolean =>
|
|
7
|
+
isNotEmpty(el) && el.scrollWidth !== el.clientWidth;
|
|
8
|
+
|
|
9
|
+
export const formatCellContent = <Values>(
|
|
10
|
+
value: unknown,
|
|
11
|
+
config?: IFlexibleTableConfigType<Values>[keyof Values],
|
|
12
|
+
): string =>
|
|
13
|
+
value instanceof Date
|
|
14
|
+
? format(value as Date, config?.dateFormat ?? DEFAULT_DATE_FORMAT)
|
|
15
|
+
: String(value);
|
|
@@ -23,7 +23,7 @@ export type IFlexibleTableConfigType<Values> = {
|
|
|
23
23
|
[Key in keyof Values]?: {
|
|
24
24
|
title?: ReactNode;
|
|
25
25
|
titleComponent?: ITitleComponent<unknown>;
|
|
26
|
-
component?: IValueComponent<Values, Values[Key]
|
|
26
|
+
component?: IValueComponent<Values, NonNullable<Values[Key]>>;
|
|
27
27
|
dateFormat?: string;
|
|
28
28
|
minWidth?: string | number;
|
|
29
29
|
width?: string | number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { complexIcons } from './complexIcons';
|
|
2
|
-
import { IComplexIcon, IIconType, ISvgIcon } from './types';
|
|
2
|
+
import type { IComplexIcon, IIconType, ISvgIcon } from './types';
|
|
3
3
|
|
|
4
4
|
export const isComplexIcon = (type: IIconType): type is IComplexIcon => type in complexIcons;
|
|
5
5
|
|
|
@@ -370,6 +370,26 @@ export const iconsList = checkIcons({
|
|
|
370
370
|
},
|
|
371
371
|
],
|
|
372
372
|
},
|
|
373
|
+
folder: {
|
|
374
|
+
viewBox: '0 0 20 20',
|
|
375
|
+
paths: [
|
|
376
|
+
{
|
|
377
|
+
d: 'M16.9 5H10.009L8.716 3.795C8.25211 3.34264 7.714 3 7.069 3H3.1C1.942 3 1 3.942 1 5.1V15.9C1 17.058 1.942 18 3.1 18H16.9C18.058 18 19 17.058 19 15.9V7.1C19 5.942 18.058 5 16.9 5Z',
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
},
|
|
381
|
+
'folder-add': {
|
|
382
|
+
viewBox: '0 0 20 20',
|
|
383
|
+
paths: [
|
|
384
|
+
{
|
|
385
|
+
d: 'M16.9 5H10.009C10.009 5 9.19158 4.23037 8.716 3.795C8.24042 3.35963 7.714 3 7.069 3H3.1C1.942 3 1 3.942 1 5.1V15.9C1 17.058 1.942 18 3.1 18H16.9C18.058 18 19 17.058 19 15.9V7.1C19 5.942 18.058 5 16.9 5Z',
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
d: 'M13 13H11V15C11 15.5523 10.5523 16 10 16C9.44772 16 9 15.5523 9 15V13H7C6.44772 13 6 12.5523 6 12C6 11.4477 6.44772 11 7 11H9V9C9 8.44772 9.44772 8 10 8C10.5523 8 11 8.44772 11 9V11H13C13.5523 11 14 11.4477 14 12C14 12.5523 13.5523 13 13 13Z',
|
|
389
|
+
fill: 'white',
|
|
390
|
+
},
|
|
391
|
+
],
|
|
392
|
+
},
|
|
373
393
|
food: {
|
|
374
394
|
viewBox: '0 0 28 28',
|
|
375
395
|
paths: [
|
|
@@ -495,6 +515,16 @@ export const iconsList = checkIcons({
|
|
|
495
515
|
},
|
|
496
516
|
],
|
|
497
517
|
},
|
|
518
|
+
presentation: {
|
|
519
|
+
viewBox: '0 0 20 20',
|
|
520
|
+
paths: [
|
|
521
|
+
{ d: 'M8 10H12V11H8V10Z' },
|
|
522
|
+
{ d: 'M14 8H6V9H14V8Z' },
|
|
523
|
+
{
|
|
524
|
+
d: 'M4 2C2.89543 2 2 2.89543 2 4V13C2 14.1046 2.89543 15 4 15H7.6906L5.76795 18.3301L7.5 19.3301L10 15L12.5004 19.3301L14.2324 18.3301L12.3098 15H16C17.1046 15 18 14.1046 18 13V4C18 2.89543 17.1046 2 16 2H4ZM16 6H4V13H16V6Z',
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
},
|
|
498
528
|
print: {
|
|
499
529
|
paths: [
|
|
500
530
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { Icon } from '
|
|
3
|
-
import { IIcon } from '
|
|
2
|
+
import { Icon } from './Icon';
|
|
3
|
+
import { IIcon } from './types';
|
|
4
4
|
|
|
5
5
|
export const renderIcon = (icon: IIcon): ReactNode =>
|
|
6
6
|
typeof icon === 'string' ? <Icon type={icon} /> : icon;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SVGAttributes } from 'react';
|
|
1
|
+
import { ReactElement, SVGAttributes } from 'react';
|
|
2
2
|
import { complexIcons } from './complexIcons';
|
|
3
3
|
import { iconsList } from './icons-list';
|
|
4
4
|
|
|
@@ -14,3 +14,5 @@ export type ICommonIcon = keyof typeof iconsList;
|
|
|
14
14
|
export type IComplexIcon = keyof typeof complexIcons;
|
|
15
15
|
|
|
16
16
|
export type IIconType = ICommonIcon | IComplexIcon;
|
|
17
|
+
|
|
18
|
+
export type IIcon = IIconType | ReactElement;
|
|
@@ -19,10 +19,9 @@ import {
|
|
|
19
19
|
isStringNotEmpty,
|
|
20
20
|
} from '@true-engineering/true-react-platform-helpers';
|
|
21
21
|
import { addDataAttributes } from '../../helpers';
|
|
22
|
-
import { renderIcon } from '../../helpers/snippets';
|
|
23
22
|
import { useTweakStyles } from '../../hooks';
|
|
24
|
-
import { ICommonProps
|
|
25
|
-
import { Icon } from '../Icon';
|
|
23
|
+
import { ICommonProps } from '../../types';
|
|
24
|
+
import { renderIcon, Icon, IIcon } from '../Icon';
|
|
26
25
|
import { ThemedPreloader } from '../ThemedPreloader';
|
|
27
26
|
import { DEFAULT_SIZE } from './constants';
|
|
28
27
|
import { IReactInputMaskProps } from './types';
|