@qoretechnologies/reqore 0.34.12 → 0.35.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/__tests__/collection.test.tsx +2 -2
- package/__tests__/helpers/table.test.tsx +47 -0
- package/__tests__/pagination.test.tsx +35 -4
- package/__tests__/table.test.tsx +158 -123
- package/dist/components/Button/index.d.ts +2 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +7 -4
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Collection/index.d.ts +2 -1
- package/dist/components/Collection/index.d.ts.map +1 -1
- package/dist/components/Collection/index.js +5 -11
- package/dist/components/Collection/index.js.map +1 -1
- package/dist/components/ControlGroup/index.d.ts.map +1 -1
- package/dist/components/ControlGroup/index.js +4 -3
- package/dist/components/ControlGroup/index.js.map +1 -1
- package/dist/components/Dropdown/index.d.ts +4 -1
- package/dist/components/Dropdown/index.d.ts.map +1 -1
- package/dist/components/Dropdown/index.js +2 -2
- package/dist/components/Dropdown/index.js.map +1 -1
- package/dist/components/Dropdown/list.d.ts +4 -1
- package/dist/components/Dropdown/list.d.ts.map +1 -1
- package/dist/components/Dropdown/list.js +10 -5
- package/dist/components/Dropdown/list.js.map +1 -1
- package/dist/components/Input/index.js +4 -4
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Paging/index.d.ts +4 -1
- package/dist/components/Paging/index.d.ts.map +1 -1
- package/dist/components/Paging/index.js +8 -6
- package/dist/components/Paging/index.js.map +1 -1
- package/dist/components/Panel/index.d.ts +4 -1
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/Table/cell.d.ts +12 -0
- package/dist/components/Table/cell.d.ts.map +1 -0
- package/dist/components/Table/cell.js +89 -0
- package/dist/components/Table/cell.js.map +1 -0
- package/dist/components/Table/header.d.ts +15 -2
- package/dist/components/Table/header.d.ts.map +1 -1
- package/dist/components/Table/header.js +31 -14
- package/dist/components/Table/header.js.map +1 -1
- package/dist/components/Table/headerCell.d.ts +8 -6
- package/dist/components/Table/headerCell.d.ts.map +1 -1
- package/dist/components/Table/headerCell.js +60 -51
- package/dist/components/Table/headerCell.js.map +1 -1
- package/dist/components/Table/helpers.d.ts +39 -1
- package/dist/components/Table/helpers.d.ts.map +1 -1
- package/dist/components/Table/helpers.js +145 -1
- package/dist/components/Table/helpers.js.map +1 -1
- package/dist/components/Table/index.d.ts +39 -25
- package/dist/components/Table/index.d.ts.map +1 -1
- package/dist/components/Table/index.js +139 -52
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Table/row.d.ts +9 -4
- package/dist/components/Table/row.d.ts.map +1 -1
- package/dist/components/Table/row.js +30 -54
- package/dist/components/Table/row.js.map +1 -1
- package/dist/hooks/useQueryWithDelay.d.ts +8 -0
- package/dist/hooks/useQueryWithDelay.d.ts.map +1 -0
- package/dist/hooks/useQueryWithDelay.js +25 -0
- package/dist/hooks/useQueryWithDelay.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/index.tsx +6 -1
- package/src/components/Collection/index.tsx +9 -15
- package/src/components/ControlGroup/index.tsx +10 -5
- package/src/components/Dropdown/index.tsx +9 -0
- package/src/components/Dropdown/list.tsx +18 -6
- package/src/components/Input/index.tsx +3 -3
- package/src/components/Paging/index.tsx +35 -13
- package/src/components/Panel/index.tsx +3 -1
- package/src/components/Table/cell.tsx +117 -0
- package/src/components/Table/header.tsx +102 -45
- package/src/components/Table/headerCell.tsx +123 -80
- package/src/components/Table/helpers.ts +206 -1
- package/src/components/Table/index.tsx +288 -90
- package/src/components/Table/row.tsx +47 -125
- package/src/hooks/useQueryWithDelay.ts +30 -0
- package/src/index.tsx +3 -0
- package/src/mock/tableData.ts +40 -20
- package/src/stories/Breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/stories/Button/Button.stories.tsx +1 -1
- package/src/stories/Checkbox/Checkbox.stories.tsx +1 -1
- package/src/stories/Collection/Collection.stories.tsx +19 -1
- package/src/stories/Columns/Columns.stories.tsx +1 -1
- package/src/stories/Comment/Comment.stories.tsx +1 -1
- package/src/stories/ControlGroup/ControlGroup.stories.tsx +1 -1
- package/src/stories/Drawer/Drawer.stories.tsx +5 -5
- package/src/stories/Dropdown/Dropdown.stories.tsx +11 -1
- package/src/stories/Header/Header.stories.tsx +1 -1
- package/src/stories/Icon/Icon.stories.tsx +1 -1
- package/src/stories/Input/Input.stories.tsx +1 -1
- package/src/stories/Menu/Menu.stories.tsx +1 -1
- package/src/stories/Message/Message.stories.tsx +1 -1
- package/src/stories/Modal/Modal.stories.tsx +1 -1
- package/src/stories/MultiSelect/MultiSelect.stories.tsx +1 -1
- package/src/stories/Navbar/Navbar.stories.tsx +1 -1
- package/src/stories/Notifications/Interactive.stories.tsx +1 -1
- package/src/stories/Notifications/Notification.stories.tsx +1 -1
- package/src/stories/Notifications/Notifications.stories.tsx +1 -1
- package/src/stories/Paging/Paging.stories.tsx +6 -2
- package/src/stories/Panel/Panel.stories.tsx +5 -5
- package/src/stories/Paragraph/Paragraph.stories.tsx +1 -1
- package/src/stories/Popover/Popover.stories.tsx +2 -2
- package/src/stories/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/src/stories/Sidebar/Sidebar.stories.tsx +2 -2
- package/src/stories/Spacer/Spacer.stories.tsx +1 -1
- package/src/stories/Spinner/Spinner.stories.tsx +1 -1
- package/src/stories/Table/Table.stories.tsx +277 -78
- package/src/stories/Tabs/Tabs.stories.tsx +1 -1
- package/src/stories/Tag/Tag.stories.tsx +1 -1
- package/src/stories/TextArea/TextArea.stories.tsx +2 -2
- package/src/stories/Tree/Tree.stories.tsx +2 -2
- package/src/stories/utils/args.ts +1 -1
- package/tests.json +1 -1
|
@@ -1,12 +1,33 @@
|
|
|
1
|
+
import { omit } from 'lodash';
|
|
1
2
|
import styled, { css } from 'styled-components';
|
|
2
3
|
import { IReqoreTableColumn, IReqoreTableSort } from '.';
|
|
3
4
|
import { IReqoreTheme } from '../../constants/theme';
|
|
4
5
|
import { changeLightness } from '../../helpers/colors';
|
|
5
6
|
import { alignToFlexAlign } from '../../helpers/utils';
|
|
7
|
+
import { IWithReqoreSize } from '../../types/global';
|
|
6
8
|
import { IReqoreIconName } from '../../types/icons';
|
|
7
|
-
import
|
|
9
|
+
import { IReqoreButtonProps } from '../Button';
|
|
10
|
+
import { IReqoreTableHeaderCellProps, ReqoreTableHeaderCell } from './headerCell';
|
|
11
|
+
import { calculateMinimumCellWidth, getOnlyShownColumns } from './helpers';
|
|
12
|
+
|
|
13
|
+
export type TColumnsUpdater = <T extends keyof IReqoreTableColumn>(
|
|
14
|
+
id: string,
|
|
15
|
+
key: T,
|
|
16
|
+
value: IReqoreTableColumn[T]
|
|
17
|
+
) => void;
|
|
18
|
+
|
|
19
|
+
export interface IReqoreCustomHeaderCellProps
|
|
20
|
+
extends Pick<
|
|
21
|
+
IReqoreTableHeaderCellProps,
|
|
22
|
+
'sortData' | 'onSortChange' | 'onColumnsUpdate' | 'onFilterChange'
|
|
23
|
+
>,
|
|
24
|
+
Omit<IReqoreTableColumn, 'cell' | 'header'>,
|
|
25
|
+
IReqoreButtonProps {
|
|
26
|
+
hasColumns?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface IReqoreCustomHeaderCellComponent extends React.FC<IReqoreCustomHeaderCellProps> {}
|
|
8
29
|
|
|
9
|
-
export interface IReqoreTableSectionProps {
|
|
30
|
+
export interface IReqoreTableSectionProps extends IWithReqoreSize {
|
|
10
31
|
columns: IReqoreTableColumn[];
|
|
11
32
|
leftScroll: number;
|
|
12
33
|
onSortChange?: (sort: string) => void;
|
|
@@ -16,6 +37,9 @@ export interface IReqoreTableSectionProps {
|
|
|
16
37
|
onToggleSelectClick: () => void;
|
|
17
38
|
hasVerticalScroll: boolean;
|
|
18
39
|
selectToggleTooltip?: string;
|
|
40
|
+
onColumnsUpdate: TColumnsUpdater;
|
|
41
|
+
onFilterChange?: (dataId: string, value: any) => void;
|
|
42
|
+
component?: IReqoreCustomHeaderCellComponent;
|
|
19
43
|
}
|
|
20
44
|
|
|
21
45
|
export interface IReqoreTableSectionStyle {
|
|
@@ -70,11 +94,7 @@ const StyledTableHeaderRow = styled.div<{ theme: IReqoreTheme }>`
|
|
|
70
94
|
display: flex;
|
|
71
95
|
flex: 1;
|
|
72
96
|
|
|
73
|
-
${
|
|
74
|
-
transform: translate3d(${-leftScroll}px, 0, 0);
|
|
75
|
-
`}
|
|
76
|
-
|
|
77
|
-
${StyledTableHeader}, ${StyledColumnGroupHeader} {
|
|
97
|
+
${StyledColumnGroupHeader} {
|
|
78
98
|
font-size: 13px;
|
|
79
99
|
font-weight: 600;
|
|
80
100
|
padding: 5px 10px;
|
|
@@ -95,39 +115,72 @@ const ReqoreTableHeader = ({
|
|
|
95
115
|
onToggleSelectClick,
|
|
96
116
|
selectToggleTooltip,
|
|
97
117
|
hasVerticalScroll,
|
|
118
|
+
onColumnsUpdate,
|
|
119
|
+
onFilterChange,
|
|
120
|
+
size,
|
|
121
|
+
component,
|
|
98
122
|
}: IReqoreTableSectionProps) => {
|
|
123
|
+
const renderHeaderCell = (
|
|
124
|
+
headerCellComponent: IReqoreCustomHeaderCellComponent,
|
|
125
|
+
props: IReqoreCustomHeaderCellProps
|
|
126
|
+
) => {
|
|
127
|
+
const HeaderCell = headerCellComponent || component || ReqoreTableHeaderCell;
|
|
128
|
+
|
|
129
|
+
return <HeaderCell key={props.dataId} {...props} />;
|
|
130
|
+
};
|
|
131
|
+
|
|
99
132
|
const renderColumns = (columns: IReqoreTableColumn[]) =>
|
|
100
|
-
columns.map(
|
|
101
|
-
(
|
|
102
|
-
|
|
133
|
+
getOnlyShownColumns(columns).map(
|
|
134
|
+
(
|
|
135
|
+
{
|
|
136
|
+
grow,
|
|
137
|
+
align,
|
|
138
|
+
dataId,
|
|
139
|
+
header: { columns, onClick, component: headerComponent, ...rest },
|
|
140
|
+
...colRest
|
|
141
|
+
},
|
|
142
|
+
index
|
|
143
|
+
) =>
|
|
144
|
+
columns ? (
|
|
103
145
|
<StyledColumnGroup
|
|
104
|
-
width={cols.reduce((wid, col) => wid + (col.width || 80), 0)}
|
|
105
146
|
grow={grow}
|
|
106
147
|
key={index}
|
|
107
148
|
className='reqore-table-column-group'
|
|
149
|
+
width={getOnlyShownColumns(columns).reduce(
|
|
150
|
+
(wid, col) => wid + (col.resizedWidth || col.width || 80),
|
|
151
|
+
0
|
|
152
|
+
)}
|
|
108
153
|
>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
154
|
+
{renderHeaderCell(headerComponent, {
|
|
155
|
+
...rest,
|
|
156
|
+
...omit(colRest, ['cell']),
|
|
157
|
+
dataId,
|
|
158
|
+
size,
|
|
159
|
+
readOnly: !onClick,
|
|
160
|
+
rounded: false,
|
|
161
|
+
textAlign: align,
|
|
162
|
+
className: 'reqore-table-column-group-header',
|
|
163
|
+
resizable: false,
|
|
164
|
+
hideable: false,
|
|
165
|
+
hasColumns: true,
|
|
166
|
+
})}
|
|
116
167
|
<StyledColumnGroupHeaders className='reqore-table-headers'>
|
|
117
|
-
{renderColumns(
|
|
168
|
+
{renderColumns(columns)}
|
|
118
169
|
</StyledColumnGroupHeaders>
|
|
119
170
|
</StyledColumnGroup>
|
|
120
171
|
) : (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
onSortChange
|
|
130
|
-
|
|
172
|
+
renderHeaderCell(headerComponent, {
|
|
173
|
+
...rest,
|
|
174
|
+
...omit(colRest, ['cell']),
|
|
175
|
+
dataId,
|
|
176
|
+
size,
|
|
177
|
+
sortData,
|
|
178
|
+
grow,
|
|
179
|
+
align,
|
|
180
|
+
onSortChange,
|
|
181
|
+
onColumnsUpdate,
|
|
182
|
+
onFilterChange,
|
|
183
|
+
})
|
|
131
184
|
)
|
|
132
185
|
);
|
|
133
186
|
|
|
@@ -147,23 +200,27 @@ const ReqoreTableHeader = ({
|
|
|
147
200
|
className='reqore-table-header-wrapper'
|
|
148
201
|
hasVerticalScroll={hasVerticalScroll}
|
|
149
202
|
>
|
|
150
|
-
<StyledTableHeaderRow
|
|
151
|
-
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
203
|
+
<StyledTableHeaderRow
|
|
204
|
+
style={{
|
|
205
|
+
transform: `translate3d(${leftScroll ? -leftScroll : 0}px, 0, 0)`,
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
{selectable &&
|
|
209
|
+
renderHeaderCell(component, {
|
|
210
|
+
dataId: 'selectbox',
|
|
211
|
+
sortData,
|
|
212
|
+
align: 'center',
|
|
213
|
+
size,
|
|
214
|
+
onSortChange,
|
|
215
|
+
icon: getSelectedIcon(),
|
|
216
|
+
width: calculateMinimumCellWidth(50, size),
|
|
217
|
+
resizable: false,
|
|
218
|
+
hideable: false,
|
|
219
|
+
tooltip: selectToggleTooltip || 'Toggle selection on all data',
|
|
220
|
+
onClick: () => {
|
|
163
221
|
onToggleSelectClick();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
)}
|
|
222
|
+
},
|
|
223
|
+
})}
|
|
167
224
|
{renderColumns(columns)}
|
|
168
225
|
</StyledTableHeaderRow>
|
|
169
226
|
</StyledTableHeaderWrapper>
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
/* @flow */
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import { rgba } from 'polished';
|
|
3
|
+
import { Resizable } from 're-resizable';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
import styled from 'styled-components';
|
|
4
6
|
import { IReqoreTableColumn, IReqoreTableSort } from '.';
|
|
7
|
+
import { ReqoreButton, ReqoreControlGroup, ReqoreDropdown } from '../..';
|
|
5
8
|
import { IReqoreTheme } from '../../constants/theme';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
9
|
+
import { getReadableColor } from '../../helpers/colors';
|
|
10
|
+
import { IReqoreButtonProps } from '../Button';
|
|
11
|
+
import { IReqoreDropdownItem } from '../Dropdown/list';
|
|
12
|
+
import { TColumnsUpdater } from './header';
|
|
10
13
|
|
|
11
14
|
export interface IReqoreTableHeaderCellProps
|
|
12
|
-
extends
|
|
13
|
-
|
|
15
|
+
extends Omit<IReqoreTableColumn, 'cell'>,
|
|
16
|
+
IReqoreButtonProps {
|
|
14
17
|
onSortChange?: (sort: string) => void;
|
|
15
|
-
sortData
|
|
18
|
+
sortData?: IReqoreTableSort;
|
|
19
|
+
onColumnsUpdate?: TColumnsUpdater;
|
|
20
|
+
onFilterChange?: (dataId: string, filter: string) => void;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
export interface IReqoreTableHeaderStyle {
|
|
@@ -23,95 +28,133 @@ export interface IReqoreTableHeaderStyle {
|
|
|
23
28
|
interactive?: boolean;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
export const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
${({ interactive, theme }) =>
|
|
39
|
-
interactive &&
|
|
40
|
-
css`
|
|
41
|
-
cursor: pointer;
|
|
42
|
-
transition: background-color 0.2s ease-out;
|
|
43
|
-
|
|
44
|
-
&:hover {
|
|
45
|
-
color: ${getReadableColor(theme, undefined, undefined)};
|
|
46
|
-
background-color: ${changeLightness(theme.main, 0.06)};
|
|
47
|
-
}
|
|
48
|
-
`};
|
|
49
|
-
`;
|
|
50
|
-
|
|
51
|
-
const StyledTableHeaderLabel = styled.span`
|
|
52
|
-
overflow: hidden;
|
|
53
|
-
text-overflow: ellipsis;
|
|
54
|
-
white-space: nowrap;
|
|
31
|
+
export const StyledTableHeaderResize = styled.div`
|
|
32
|
+
&:before {
|
|
33
|
+
content: '';
|
|
34
|
+
position: absolute;
|
|
35
|
+
left: 50%;
|
|
36
|
+
top: 50%;
|
|
37
|
+
transform: translateX(-50%) translateY(-50%);
|
|
38
|
+
width: 1px;
|
|
39
|
+
height: 70%;
|
|
40
|
+
border-left: 1px dashed ${({ theme }) => rgba(getReadableColor(theme), 0.3)};
|
|
41
|
+
}
|
|
55
42
|
`;
|
|
56
43
|
|
|
57
|
-
const ReqoreTableHeaderCell = ({
|
|
44
|
+
export const ReqoreTableHeaderCell = ({
|
|
58
45
|
width,
|
|
46
|
+
resizedWidth,
|
|
59
47
|
grow,
|
|
60
48
|
align,
|
|
61
|
-
header,
|
|
62
49
|
onSortChange,
|
|
63
50
|
dataId,
|
|
64
51
|
sortable,
|
|
65
52
|
sortData,
|
|
66
|
-
onClick,
|
|
67
53
|
className,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
54
|
+
onClick,
|
|
55
|
+
onColumnsUpdate,
|
|
56
|
+
resizable = true,
|
|
57
|
+
filterPlaceholder,
|
|
58
|
+
filterable,
|
|
59
|
+
hideable = true,
|
|
60
|
+
filter,
|
|
61
|
+
onFilterChange,
|
|
62
|
+
...rest
|
|
72
63
|
}: IReqoreTableHeaderCellProps) => {
|
|
73
|
-
const
|
|
64
|
+
const items = useMemo(() => {
|
|
65
|
+
const _items: IReqoreDropdownItem[] = [];
|
|
74
66
|
|
|
75
|
-
|
|
67
|
+
if (resizable || hideable) {
|
|
68
|
+
_items.push({
|
|
69
|
+
divider: true,
|
|
70
|
+
label: 'Options',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (resizable) {
|
|
74
|
+
_items.push({
|
|
75
|
+
label: 'Reset size',
|
|
76
|
+
icon: 'HistoryLine',
|
|
77
|
+
disabled: !resizedWidth || width === resizedWidth,
|
|
78
|
+
onClick: () => {
|
|
79
|
+
onColumnsUpdate?.(dataId, 'resizedWidth', width);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (hideable) {
|
|
85
|
+
_items.push({
|
|
86
|
+
label: 'Hide column',
|
|
87
|
+
icon: 'EyeCloseLine',
|
|
88
|
+
onClick: () => {
|
|
89
|
+
onColumnsUpdate?.(dataId, 'show', false);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return _items;
|
|
96
|
+
}, [resizable, hideable, width, resizedWidth, onColumnsUpdate, dataId]);
|
|
76
97
|
|
|
77
98
|
return (
|
|
78
|
-
<
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
<Resizable
|
|
100
|
+
minWidth={width}
|
|
101
|
+
onResize={(_event, _direction, _component) => {
|
|
102
|
+
onColumnsUpdate?.(dataId, 'resizedWidth', parseInt(_component.style.width));
|
|
103
|
+
}}
|
|
104
|
+
handleComponent={{
|
|
105
|
+
right: <StyledTableHeaderResize />,
|
|
106
|
+
}}
|
|
107
|
+
style={{
|
|
108
|
+
overflow: 'hidden',
|
|
109
|
+
flexGrow: grow,
|
|
110
|
+
}}
|
|
111
|
+
size={{
|
|
112
|
+
width: resizedWidth || width,
|
|
113
|
+
height: undefined,
|
|
114
|
+
}}
|
|
115
|
+
enable={{
|
|
116
|
+
right: resizable,
|
|
93
117
|
}}
|
|
94
118
|
>
|
|
95
|
-
{
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
119
|
+
<ReqoreControlGroup fluid stack rounded={false} fill style={{ height: '100%' }}>
|
|
120
|
+
<ReqoreButton
|
|
121
|
+
{...rest}
|
|
122
|
+
readOnly={!sortable && !onClick}
|
|
123
|
+
className={`${className || ''} reqore-table-header-cell`}
|
|
124
|
+
rounded={false}
|
|
125
|
+
textAlign={align}
|
|
126
|
+
rightIcon={
|
|
127
|
+
sortable && sortData.by === dataId
|
|
128
|
+
? (`Arrow${sortData.direction === 'desc' ? 'Down' : 'Up'}Fill` as
|
|
129
|
+
| 'ArrowDownFill'
|
|
130
|
+
| 'ArrowUpFill')
|
|
131
|
+
: rest.rightIcon
|
|
105
132
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
133
|
+
onClick={(e) => {
|
|
134
|
+
if (sortable) {
|
|
135
|
+
onSortChange?.(dataId);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
onClick?.(e);
|
|
110
139
|
}}
|
|
111
140
|
/>
|
|
112
|
-
|
|
113
|
-
|
|
141
|
+
{filterable || hideable || resizable ? (
|
|
142
|
+
<ReqoreDropdown<IReqoreButtonProps>
|
|
143
|
+
icon='MoreLine'
|
|
144
|
+
className='reqore-table-header-cell-options'
|
|
145
|
+
fixed
|
|
146
|
+
rounded={false}
|
|
147
|
+
intent={filter ? 'info' : undefined}
|
|
148
|
+
filterable={filterable}
|
|
149
|
+
filterPlaceholder={filterPlaceholder || 'Filter by this column...'}
|
|
150
|
+
filter={filter}
|
|
151
|
+
onFilterChange={(value) => {
|
|
152
|
+
onFilterChange?.(dataId, value);
|
|
153
|
+
}}
|
|
154
|
+
items={items}
|
|
155
|
+
/>
|
|
156
|
+
) : null}
|
|
157
|
+
</ReqoreControlGroup>
|
|
158
|
+
</Resizable>
|
|
114
159
|
);
|
|
115
160
|
};
|
|
116
|
-
|
|
117
|
-
export default ReqoreTableHeaderCell;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { size } from 'lodash';
|
|
1
2
|
import { firstBy } from 'thenby';
|
|
2
|
-
import { IReqoreTableSort } from '.';
|
|
3
|
+
import { IReqoreTableColumn, IReqoreTableSort } from '.';
|
|
4
|
+
import { ICON_FROM_SIZE, SIZE_TO_PX, TSizes } from '../../constants/sizes';
|
|
5
|
+
import { IReqoreIconName } from '../../types/icons';
|
|
6
|
+
import { IReqorePanelAction } from '../Panel';
|
|
3
7
|
|
|
4
8
|
export const flipSortDirection = (direction: 'asc' | 'desc'): 'asc' | 'desc' =>
|
|
5
9
|
direction === 'asc' ? 'desc' : 'asc';
|
|
@@ -23,3 +27,204 @@ export const sortTableData = (data: any[], sort: IReqoreTableSort) => {
|
|
|
23
27
|
|
|
24
28
|
return [...data].sort(firstBy(by, { ignoreCase: true, direction }));
|
|
25
29
|
};
|
|
30
|
+
|
|
31
|
+
export const updateColumnData = (
|
|
32
|
+
columns: IReqoreTableColumn[],
|
|
33
|
+
columnId: string,
|
|
34
|
+
key: keyof IReqoreTableColumn,
|
|
35
|
+
value: any
|
|
36
|
+
): IReqoreTableColumn[] => {
|
|
37
|
+
const newColumns: IReqoreTableColumn[] = columns.map((column): IReqoreTableColumn => {
|
|
38
|
+
if (column.dataId === columnId) {
|
|
39
|
+
return { ...column, [key]: value };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (column.header?.columns) {
|
|
43
|
+
return {
|
|
44
|
+
...column,
|
|
45
|
+
header: {
|
|
46
|
+
...column.header,
|
|
47
|
+
columns: updateColumnData(column.header.columns, columnId, key, value),
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return column;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return newColumns;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const sizeToZoom = {
|
|
59
|
+
tiny: 0,
|
|
60
|
+
small: 0.5,
|
|
61
|
+
normal: 1,
|
|
62
|
+
big: 1.5,
|
|
63
|
+
huge: 2,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const zoomToSize = {
|
|
67
|
+
0: 'tiny',
|
|
68
|
+
0.5: 'small',
|
|
69
|
+
1: 'normal',
|
|
70
|
+
1.5: 'big',
|
|
71
|
+
2: 'huge',
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const zoomToWidth = {
|
|
75
|
+
0: '200px',
|
|
76
|
+
0.5: '300px',
|
|
77
|
+
1: '400px',
|
|
78
|
+
1.5: '500px',
|
|
79
|
+
2: '600px',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// This code converts a zoom level to a label.
|
|
83
|
+
export const zoomToLabel = {
|
|
84
|
+
0: '0.6x',
|
|
85
|
+
0.5: '0.8x',
|
|
86
|
+
1: '1x',
|
|
87
|
+
1.5: '1.2x',
|
|
88
|
+
2: '1.4x',
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const getZoomActions = (
|
|
92
|
+
type: string,
|
|
93
|
+
zoom: number,
|
|
94
|
+
setter: (zoom: number) => void
|
|
95
|
+
): IReqorePanelAction[] => [
|
|
96
|
+
{
|
|
97
|
+
icon: 'ZoomInLine',
|
|
98
|
+
tooltip: 'Zoom in',
|
|
99
|
+
disabled: zoom === 2,
|
|
100
|
+
className: `${type}-zoom-in`,
|
|
101
|
+
onClick: () => {
|
|
102
|
+
setter(zoom + 0.5);
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
icon: 'RestartLine',
|
|
107
|
+
label: zoomToLabel[zoom],
|
|
108
|
+
tooltip: 'Reset zoom',
|
|
109
|
+
disabled: zoom === 1,
|
|
110
|
+
className: `${type}-zoom-reset`,
|
|
111
|
+
onClick: () => {
|
|
112
|
+
setter(1);
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
icon: 'ZoomOutLine',
|
|
117
|
+
tooltip: 'Zoom out',
|
|
118
|
+
disabled: zoom === 0,
|
|
119
|
+
className: `${type}-zoom-out`,
|
|
120
|
+
onClick: () => {
|
|
121
|
+
setter(zoom - 0.5);
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
export const getColumnsCount = (columns: IReqoreTableColumn[]): number => {
|
|
127
|
+
let count = 0;
|
|
128
|
+
|
|
129
|
+
columns.forEach((column) => {
|
|
130
|
+
if (column.header.columns) {
|
|
131
|
+
count += getColumnsCount(column.header.columns);
|
|
132
|
+
} else {
|
|
133
|
+
count += 1;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return count;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const hasHiddenColumns = (columns: IReqoreTableColumn[]): boolean => {
|
|
141
|
+
return columns.some((column) => {
|
|
142
|
+
if (column.header.columns) {
|
|
143
|
+
return column.header.columns.some((subColumn) => subColumn.show === false);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return column.show === false;
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const getOnlyShownColumns = (columns: IReqoreTableColumn[]): IReqoreTableColumn[] => {
|
|
151
|
+
return columns.reduce((newColumns, column) => {
|
|
152
|
+
if (column.header.columns) {
|
|
153
|
+
const subColumns = getOnlyShownColumns(column.header.columns);
|
|
154
|
+
|
|
155
|
+
if (size(subColumns)) {
|
|
156
|
+
return [
|
|
157
|
+
...newColumns,
|
|
158
|
+
{
|
|
159
|
+
...column,
|
|
160
|
+
header: { ...column.header, columns: getOnlyShownColumns(column.header.columns) },
|
|
161
|
+
},
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return newColumns;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (column.show !== false) {
|
|
169
|
+
return [...newColumns, column];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return newColumns;
|
|
173
|
+
}, []);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export const prepareColumns = (
|
|
177
|
+
columns: IReqoreTableColumn[],
|
|
178
|
+
size: TSizes = 'normal'
|
|
179
|
+
): IReqoreTableColumn[] => {
|
|
180
|
+
// We need to set the width of each column
|
|
181
|
+
return columns.map((column) => {
|
|
182
|
+
if (column.header.columns) {
|
|
183
|
+
return {
|
|
184
|
+
...column,
|
|
185
|
+
header: { ...column.header, columns: prepareColumns(column.header.columns) },
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let newWidth = calculateMinimumCellWidth(
|
|
190
|
+
column.width || 50,
|
|
191
|
+
size,
|
|
192
|
+
column.header.icon,
|
|
193
|
+
column.sortable,
|
|
194
|
+
column.filterable,
|
|
195
|
+
column.hideable,
|
|
196
|
+
column.resizable
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
...column,
|
|
201
|
+
width: newWidth,
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export const calculateMinimumCellWidth = (
|
|
207
|
+
currentWidth: number = 50,
|
|
208
|
+
size?: TSizes,
|
|
209
|
+
icon?: IReqoreIconName,
|
|
210
|
+
sortable?: boolean,
|
|
211
|
+
filterable?: boolean,
|
|
212
|
+
hideable?: boolean,
|
|
213
|
+
resizable?: boolean
|
|
214
|
+
): number => {
|
|
215
|
+
let width = currentWidth;
|
|
216
|
+
|
|
217
|
+
if (icon) {
|
|
218
|
+
width += ICON_FROM_SIZE[size];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (sortable) {
|
|
222
|
+
width += ICON_FROM_SIZE[size];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (filterable || hideable || resizable) {
|
|
226
|
+
width += SIZE_TO_PX[size];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return width;
|
|
230
|
+
};
|