@equinor/eds-data-grid-react 0.7.6 → 0.8.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/dist/eds-data-grid-react.cjs +89 -48
- package/dist/esm/EdsDataGrid.js +11 -4
- package/dist/esm/components/DebouncedInput.js +0 -1
- package/dist/esm/components/FilterWrapper.js +4 -2
- package/dist/esm/components/Resizer.js +1 -1
- package/dist/esm/components/SortIndicator.js +1 -1
- package/dist/esm/components/TableCell.js +10 -4
- package/dist/esm/components/TableHeaderCell.js +54 -25
- package/dist/types/EdsDataGrid.d.ts +1 -1
- package/dist/types/EdsDataGridProps.d.ts +11 -1
- package/dist/types/components/TableCell.d.ts +2 -0
- package/package.json +27 -27
|
@@ -59,7 +59,6 @@ function DebouncedInput({
|
|
|
59
59
|
label: props.placeholder,
|
|
60
60
|
children: /*#__PURE__*/jsxRuntime.jsx(edsCoreReact.Input, {
|
|
61
61
|
type: 'number',
|
|
62
|
-
placeholder: '0',
|
|
63
62
|
value: value,
|
|
64
63
|
onChange: e => setValue(e.target.valueAsNumber)
|
|
65
64
|
})
|
|
@@ -161,6 +160,34 @@ function Filter({
|
|
|
161
160
|
});
|
|
162
161
|
}
|
|
163
162
|
|
|
163
|
+
const ResizeInner = styled__default.default.div.withConfig({
|
|
164
|
+
displayName: "Resizer__ResizeInner",
|
|
165
|
+
componentId: "sc-plcbjs-0"
|
|
166
|
+
})(["width:2px;opacity:0;height:100%;"]);
|
|
167
|
+
const Resizer = styled__default.default.div.withConfig({
|
|
168
|
+
displayName: "Resizer",
|
|
169
|
+
componentId: "sc-plcbjs-1"
|
|
170
|
+
})(["transform:", ";", "{opacity:", ";}position:absolute;right:0;top:0;height:100%;width:5px;cursor:col-resize;user-select:none;touch-action:none;display:flex;justify-content:flex-end;z-index:1;"], props => props.$columnResizeMode === 'onEnd' ? 'translateX(0px)' : 'none', ResizeInner, props => props.$isResizing ? 1 : 0);
|
|
171
|
+
|
|
172
|
+
const FilterVisibility = styled__default.default.div.withConfig({
|
|
173
|
+
displayName: "TableCell__FilterVisibility",
|
|
174
|
+
componentId: "sc-1g0k23m-0"
|
|
175
|
+
})([""]);
|
|
176
|
+
const TableCell = styled__default.default(edsCoreReact.Table.Cell).withConfig({
|
|
177
|
+
displayName: "TableCell",
|
|
178
|
+
componentId: "sc-1g0k23m-1"
|
|
179
|
+
})(["font-weight:bold;position:", ";top:0;", " ", ";&:hover ", "{background:", ";opacity:1;}", ":not(:focus-within){opacity:", ";}&:hover ", "{opacity:1;}", ":focus-within{opacity:1;}"], p => p.$sticky || p.$pinned ? 'sticky' : 'relative', p => {
|
|
180
|
+
if (p.$pinned) {
|
|
181
|
+
return `${p.$pinned}: ${p.$offset}px;`;
|
|
182
|
+
}
|
|
183
|
+
return '';
|
|
184
|
+
}, p => {
|
|
185
|
+
if (p.$sticky && p.$pinned) return 'z-index: 13';
|
|
186
|
+
if (p.$sticky || p.$pinned) return 'z-index: 12';
|
|
187
|
+
}, ResizeInner, edsTokens.tokens.colors.interactive.primary__hover.rgba, FilterVisibility, ({
|
|
188
|
+
$activeFilter
|
|
189
|
+
}) => $activeFilter ? 1 : 0, FilterVisibility, FilterVisibility);
|
|
190
|
+
|
|
164
191
|
/* istanbul ignore file */
|
|
165
192
|
|
|
166
193
|
function FilterWrapper({
|
|
@@ -189,7 +216,8 @@ function FilterWrapper({
|
|
|
189
216
|
return value;
|
|
190
217
|
};
|
|
191
218
|
const onChange = react.useCallback(value => column.setFilterValue(value), [column]);
|
|
192
|
-
return /*#__PURE__*/jsxRuntime.jsxs(
|
|
219
|
+
return /*#__PURE__*/jsxRuntime.jsxs(FilterVisibility, {
|
|
220
|
+
onClick: e => e.stopPropagation(),
|
|
193
221
|
children: [/*#__PURE__*/jsxRuntime.jsx(edsCoreReact.Button, {
|
|
194
222
|
"aria-haspopup": true,
|
|
195
223
|
"aria-expanded": open,
|
|
@@ -238,28 +266,14 @@ const SortIndicator = ({
|
|
|
238
266
|
}[column.getIsSorted()] ?? null;
|
|
239
267
|
};
|
|
240
268
|
|
|
241
|
-
const
|
|
242
|
-
displayName: "
|
|
243
|
-
componentId: "sc-
|
|
244
|
-
})(["width:
|
|
245
|
-
const
|
|
246
|
-
displayName: "
|
|
247
|
-
componentId: "sc-
|
|
248
|
-
})(["
|
|
249
|
-
|
|
250
|
-
const TableCell = styled__default.default(edsCoreReact.Table.Cell).withConfig({
|
|
251
|
-
displayName: "TableCell",
|
|
252
|
-
componentId: "sc-1g0k23m-0"
|
|
253
|
-
})(["font-weight:bold;position:", ";top:0;", " ", ";&:hover ", "{background:", ";opacity:1;}"], p => p.$sticky || p.$pinned ? 'sticky' : 'relative', p => {
|
|
254
|
-
if (p.$pinned) {
|
|
255
|
-
return `${p.$pinned}: ${p.$offset}px;`;
|
|
256
|
-
}
|
|
257
|
-
return '';
|
|
258
|
-
}, p => {
|
|
259
|
-
if (p.$sticky && p.$pinned) return 'z-index: 13';
|
|
260
|
-
if (p.$sticky || p.$pinned) return 'z-index: 12';
|
|
261
|
-
}, ResizeInner, edsTokens.tokens.colors.interactive.primary__hover.rgba);
|
|
262
|
-
|
|
269
|
+
const SortButton = styled__default.default.button.withConfig({
|
|
270
|
+
displayName: "TableHeaderCell__SortButton",
|
|
271
|
+
componentId: "sc-1n0j3v0-0"
|
|
272
|
+
})(["cursor:pointer;height:100%;width:calc(100% - 5px);display:flex;flex-direction:row;align-items:center;background:transparent;border:none;padding-left:var(--eds_table__cell__padding_x,16px);padding-right:var(--eds_table__cell__padding_x,16px);margin:0;outline:none;color:inherit;text-align:left;font:inherit;"]);
|
|
273
|
+
const TableHeaderCellLabel = styled__default.default.div.withConfig({
|
|
274
|
+
displayName: "TableHeaderCell__TableHeaderCellLabel",
|
|
275
|
+
componentId: "sc-1n0j3v0-1"
|
|
276
|
+
})(["display:flex;flex-direction:column;"]);
|
|
263
277
|
const getSortLabel = sorted => {
|
|
264
278
|
if (sorted) {
|
|
265
279
|
return `${sorted}ending`;
|
|
@@ -273,12 +287,32 @@ function TableHeaderCell({
|
|
|
273
287
|
const ctx = useTableContext();
|
|
274
288
|
const table = ctx.table;
|
|
275
289
|
const pinned = header.column.getIsPinned();
|
|
290
|
+
const isFiltered = header.column.getIsFiltered();
|
|
291
|
+
const filterValue = header.column.getFilterValue();
|
|
292
|
+
const hasActiveFilters = react.useMemo(() => {
|
|
293
|
+
if (!isFiltered) return false;
|
|
294
|
+
if (Array.isArray(filterValue)) {
|
|
295
|
+
return filterValue.length > 0 && filterValue.some(v => !!v || v === 0); // avoid empty strings counting
|
|
296
|
+
}
|
|
297
|
+
return !!filterValue;
|
|
298
|
+
}, [isFiltered, filterValue]);
|
|
299
|
+
const canSort = header.column.getCanSort();
|
|
300
|
+
const canFilter = header.column.getCanFilter();
|
|
276
301
|
const offset = react.useMemo(() => {
|
|
277
302
|
if (!pinned) {
|
|
278
303
|
return null;
|
|
279
304
|
}
|
|
280
305
|
return pinned === 'left' ? header.getStart() : table.getTotalSize() - header.getStart() - header.getSize();
|
|
281
306
|
}, [pinned, header, table]);
|
|
307
|
+
const tableCellPadding = react.useMemo(() => {
|
|
308
|
+
if (canSort && canFilter) {
|
|
309
|
+
return '0 var(--eds_table__cell__padding_x, 16px) 0 0';
|
|
310
|
+
}
|
|
311
|
+
if (canSort) {
|
|
312
|
+
return '0';
|
|
313
|
+
}
|
|
314
|
+
return '0 var(--eds_table__cell__padding_x, 16px) 0 var(--eds_table__cell__padding_x, 16px)';
|
|
315
|
+
}, [canSort, canFilter]);
|
|
282
316
|
return header.isPlaceholder ? /*#__PURE__*/jsxRuntime.jsx(TableCell, {
|
|
283
317
|
$sticky: ctx.stickyHeader,
|
|
284
318
|
$offset: offset,
|
|
@@ -292,39 +326,39 @@ function TableHeaderCell({
|
|
|
292
326
|
$sticky: ctx.stickyHeader,
|
|
293
327
|
$offset: offset,
|
|
294
328
|
$pinned: pinned,
|
|
329
|
+
$activeFilter: hasActiveFilters,
|
|
295
330
|
className: ctx.headerClass ? ctx.headerClass(header.column) : '',
|
|
296
331
|
"aria-sort": getSortLabel(header.column.getIsSorted()),
|
|
297
|
-
onClick: header.column.getToggleSortingHandler(),
|
|
298
332
|
colSpan: header.colSpan,
|
|
299
333
|
style: {
|
|
300
334
|
width: header.getSize(),
|
|
301
335
|
verticalAlign: ctx.enableColumnFiltering ? 'top' : 'middle',
|
|
302
|
-
...(ctx.headerStyle ? ctx.headerStyle(header.column) : {})
|
|
336
|
+
...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
|
|
337
|
+
padding: tableCellPadding
|
|
303
338
|
},
|
|
304
|
-
children: [/*#__PURE__*/jsxRuntime.jsxs(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
children:
|
|
311
|
-
className: "table-header-cell-label",
|
|
312
|
-
children: reactTable.flexRender(header.column.columnDef.header, header.getContext())
|
|
313
|
-
})
|
|
339
|
+
children: [canSort ? /*#__PURE__*/jsxRuntime.jsxs(SortButton, {
|
|
340
|
+
tabIndex: -1,
|
|
341
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
342
|
+
"data-testid": `sort-button-${header.id}`,
|
|
343
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(TableHeaderCellLabel, {
|
|
344
|
+
className: "table-header-cell-label",
|
|
345
|
+
children: reactTable.flexRender(header.column.columnDef.header, header.getContext())
|
|
314
346
|
}), !header.column.columnDef.meta?.customFilterInput && /*#__PURE__*/jsxRuntime.jsx(SortIndicator, {
|
|
315
347
|
column: header.column
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}) : null]
|
|
326
|
-
}), columnResizeMode && /*#__PURE__*/jsxRuntime.jsx(Resizer, {
|
|
348
|
+
})]
|
|
349
|
+
}) : /*#__PURE__*/jsxRuntime.jsx(TableHeaderCellLabel, {
|
|
350
|
+
className: "table-header-cell-label",
|
|
351
|
+
children: reactTable.flexRender(header.column.columnDef.header, header.getContext())
|
|
352
|
+
}), canFilter && !header.column.columnDef.meta?.customFilterInput ?
|
|
353
|
+
/*#__PURE__*/
|
|
354
|
+
// Supressing this warning - div is not interactive, but prevents propagation of events to avoid unintended sorting
|
|
355
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
|
356
|
+
jsxRuntime.jsx(FilterVisibility, {
|
|
327
357
|
onClick: e => e.stopPropagation(),
|
|
358
|
+
children: /*#__PURE__*/jsxRuntime.jsx(FilterWrapper, {
|
|
359
|
+
column: header.column
|
|
360
|
+
})
|
|
361
|
+
}) : null, columnResizeMode && /*#__PURE__*/jsxRuntime.jsx(Resizer, {
|
|
328
362
|
onMouseDown: header.getResizeHandler(),
|
|
329
363
|
onTouchStart: header.getResizeHandler(),
|
|
330
364
|
$isResizing: header.column.getIsResizing(),
|
|
@@ -550,6 +584,8 @@ function EdsDataGridInner({
|
|
|
550
584
|
selectedRows,
|
|
551
585
|
rowSelectionState,
|
|
552
586
|
enableColumnFiltering,
|
|
587
|
+
columnFiltersState,
|
|
588
|
+
onColumnFiltersChange,
|
|
553
589
|
debug,
|
|
554
590
|
enablePagination,
|
|
555
591
|
enableSorting,
|
|
@@ -636,6 +672,9 @@ function EdsDataGridInner({
|
|
|
636
672
|
react.useEffect(() => {
|
|
637
673
|
setVisible(columnVisibility ?? {});
|
|
638
674
|
}, [columnVisibility, setVisible]);
|
|
675
|
+
react.useEffect(() => {
|
|
676
|
+
setColumnFilters(columnFiltersState);
|
|
677
|
+
}, [columnFiltersState]);
|
|
639
678
|
react.useEffect(() => {
|
|
640
679
|
setColumnPin(s => columnPinState ?? s);
|
|
641
680
|
}, [columnPinState]);
|
|
@@ -716,6 +755,7 @@ function EdsDataGridInner({
|
|
|
716
755
|
},
|
|
717
756
|
state: {
|
|
718
757
|
sorting,
|
|
758
|
+
columnFilters: columnFilters,
|
|
719
759
|
columnPinning: columnPin,
|
|
720
760
|
rowSelection: internalRowSelectionState,
|
|
721
761
|
columnOrder: columnOrderState,
|
|
@@ -772,7 +812,7 @@ function EdsDataGridInner({
|
|
|
772
812
|
if (enableColumnFiltering) {
|
|
773
813
|
options.state.columnFilters = columnFilters;
|
|
774
814
|
options.state.globalFilter = globalFilter;
|
|
775
|
-
options.onColumnFiltersChange = setColumnFilters;
|
|
815
|
+
options.onColumnFiltersChange = onColumnFiltersChange ?? setColumnFilters;
|
|
776
816
|
options.onGlobalFilterChange = setGlobalFilter;
|
|
777
817
|
options.getFacetedRowModel = reactTable.getFacetedRowModel();
|
|
778
818
|
options.getFacetedUniqueValues = reactTable.getFacetedUniqueValues();
|
|
@@ -965,6 +1005,7 @@ function EdsDataGridInner({
|
|
|
965
1005
|
}, footerGroup.id))
|
|
966
1006
|
})]
|
|
967
1007
|
}), externalPaginator ? externalPaginator : enablePagination && /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1008
|
+
className: "table-pagination",
|
|
968
1009
|
style: {
|
|
969
1010
|
maxWidth: `${table.getTotalSize()}px`
|
|
970
1011
|
},
|
package/dist/esm/EdsDataGrid.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useEds, Table, Pagination, Typography } from '@equinor/eds-core-react';
|
|
2
|
+
import { getSortedRowModel, getCoreRowModel, getExpandedRowModel, getFacetedRowModel, getFacetedUniqueValues, getFacetedMinMaxValues, getFilteredRowModel, getPaginationRowModel, useReactTable } from '@tanstack/react-table';
|
|
3
3
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
4
4
|
import { forwardRef, useState, useEffect, useMemo, useRef, useCallback } from 'react';
|
|
5
5
|
import styled from 'styled-components';
|
|
@@ -9,7 +9,7 @@ import { TableFooterRow } from './components/TableFooterRow.js';
|
|
|
9
9
|
import { TableRow } from './components/TableRow.js';
|
|
10
10
|
import { addPxSuffixIfInputHasNoPrefix, logDevelopmentWarningOfPropUse } from './utils.js';
|
|
11
11
|
import { mergeRefs } from '@equinor/eds-utils';
|
|
12
|
-
import {
|
|
12
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
13
13
|
|
|
14
14
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
15
15
|
function EdsDataGridInner({
|
|
@@ -24,6 +24,8 @@ function EdsDataGridInner({
|
|
|
24
24
|
selectedRows,
|
|
25
25
|
rowSelectionState,
|
|
26
26
|
enableColumnFiltering,
|
|
27
|
+
columnFiltersState,
|
|
28
|
+
onColumnFiltersChange,
|
|
27
29
|
debug,
|
|
28
30
|
enablePagination,
|
|
29
31
|
enableSorting,
|
|
@@ -110,6 +112,9 @@ function EdsDataGridInner({
|
|
|
110
112
|
useEffect(() => {
|
|
111
113
|
setVisible(columnVisibility ?? {});
|
|
112
114
|
}, [columnVisibility, setVisible]);
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
setColumnFilters(columnFiltersState);
|
|
117
|
+
}, [columnFiltersState]);
|
|
113
118
|
useEffect(() => {
|
|
114
119
|
setColumnPin(s => columnPinState ?? s);
|
|
115
120
|
}, [columnPinState]);
|
|
@@ -190,6 +195,7 @@ function EdsDataGridInner({
|
|
|
190
195
|
},
|
|
191
196
|
state: {
|
|
192
197
|
sorting,
|
|
198
|
+
columnFilters: columnFilters,
|
|
193
199
|
columnPinning: columnPin,
|
|
194
200
|
rowSelection: internalRowSelectionState,
|
|
195
201
|
columnOrder: columnOrderState,
|
|
@@ -246,7 +252,7 @@ function EdsDataGridInner({
|
|
|
246
252
|
if (enableColumnFiltering) {
|
|
247
253
|
options.state.columnFilters = columnFilters;
|
|
248
254
|
options.state.globalFilter = globalFilter;
|
|
249
|
-
options.onColumnFiltersChange = setColumnFilters;
|
|
255
|
+
options.onColumnFiltersChange = onColumnFiltersChange ?? setColumnFilters;
|
|
250
256
|
options.onGlobalFilterChange = setGlobalFilter;
|
|
251
257
|
options.getFacetedRowModel = getFacetedRowModel();
|
|
252
258
|
options.getFacetedUniqueValues = getFacetedUniqueValues();
|
|
@@ -439,6 +445,7 @@ function EdsDataGridInner({
|
|
|
439
445
|
}, footerGroup.id))
|
|
440
446
|
})]
|
|
441
447
|
}), externalPaginator ? externalPaginator : enablePagination && /*#__PURE__*/jsx("div", {
|
|
448
|
+
className: "table-pagination",
|
|
442
449
|
style: {
|
|
443
450
|
maxWidth: `${table.getTotalSize()}px`
|
|
444
451
|
},
|
|
@@ -4,7 +4,8 @@ import { filter_alt_active, filter_alt } from '@equinor/eds-icons';
|
|
|
4
4
|
import { tokens } from '@equinor/eds-tokens';
|
|
5
5
|
import { Filter } from './Filter.js';
|
|
6
6
|
import { useTableContext } from '../EdsDataGridContext.js';
|
|
7
|
-
import {
|
|
7
|
+
import { FilterVisibility } from './TableCell.js';
|
|
8
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
9
|
|
|
9
10
|
/* istanbul ignore file */
|
|
10
11
|
|
|
@@ -34,7 +35,8 @@ function FilterWrapper({
|
|
|
34
35
|
return value;
|
|
35
36
|
};
|
|
36
37
|
const onChange = useCallback(value => column.setFilterValue(value), [column]);
|
|
37
|
-
return /*#__PURE__*/jsxs(
|
|
38
|
+
return /*#__PURE__*/jsxs(FilterVisibility, {
|
|
39
|
+
onClick: e => e.stopPropagation(),
|
|
38
40
|
children: [/*#__PURE__*/jsx(Button, {
|
|
39
41
|
"aria-haspopup": true,
|
|
40
42
|
"aria-expanded": open,
|
|
@@ -7,6 +7,6 @@ const ResizeInner = styled.div.withConfig({
|
|
|
7
7
|
const Resizer = styled.div.withConfig({
|
|
8
8
|
displayName: "Resizer",
|
|
9
9
|
componentId: "sc-plcbjs-1"
|
|
10
|
-
})(["transform:", ";", "{opacity:", ";}position:absolute;right:0;top:0;height:100%;width:5px;cursor:col-resize;user-select:none;touch-action:none;display:flex;justify-content:flex-end;"], props => props.$columnResizeMode === 'onEnd' ? 'translateX(0px)' : 'none', ResizeInner, props => props.$isResizing ? 1 : 0);
|
|
10
|
+
})(["transform:", ";", "{opacity:", ";}position:absolute;right:0;top:0;height:100%;width:5px;cursor:col-resize;user-select:none;touch-action:none;display:flex;justify-content:flex-end;z-index:1;"], props => props.$columnResizeMode === 'onEnd' ? 'translateX(0px)' : 'none', ResizeInner, props => props.$isResizing ? 1 : 0);
|
|
11
11
|
|
|
12
12
|
export { ResizeInner, Resizer };
|
|
@@ -3,10 +3,14 @@ import { tokens } from '@equinor/eds-tokens';
|
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { ResizeInner } from './Resizer.js';
|
|
5
5
|
|
|
6
|
+
const FilterVisibility = styled.div.withConfig({
|
|
7
|
+
displayName: "TableCell__FilterVisibility",
|
|
8
|
+
componentId: "sc-1g0k23m-0"
|
|
9
|
+
})([""]);
|
|
6
10
|
const TableCell = styled(Table.Cell).withConfig({
|
|
7
11
|
displayName: "TableCell",
|
|
8
|
-
componentId: "sc-1g0k23m-
|
|
9
|
-
})(["font-weight:bold;position:", ";top:0;", " ", ";&:hover ", "{background:", ";opacity:1;}"], p => p.$sticky || p.$pinned ? 'sticky' : 'relative', p => {
|
|
12
|
+
componentId: "sc-1g0k23m-1"
|
|
13
|
+
})(["font-weight:bold;position:", ";top:0;", " ", ";&:hover ", "{background:", ";opacity:1;}", ":not(:focus-within){opacity:", ";}&:hover ", "{opacity:1;}", ":focus-within{opacity:1;}"], p => p.$sticky || p.$pinned ? 'sticky' : 'relative', p => {
|
|
10
14
|
if (p.$pinned) {
|
|
11
15
|
return `${p.$pinned}: ${p.$offset}px;`;
|
|
12
16
|
}
|
|
@@ -14,6 +18,8 @@ const TableCell = styled(Table.Cell).withConfig({
|
|
|
14
18
|
}, p => {
|
|
15
19
|
if (p.$sticky && p.$pinned) return 'z-index: 13';
|
|
16
20
|
if (p.$sticky || p.$pinned) return 'z-index: 12';
|
|
17
|
-
}, ResizeInner, tokens.colors.interactive.primary__hover.rgba
|
|
21
|
+
}, ResizeInner, tokens.colors.interactive.primary__hover.rgba, FilterVisibility, ({
|
|
22
|
+
$activeFilter
|
|
23
|
+
}) => $activeFilter ? 1 : 0, FilterVisibility, FilterVisibility);
|
|
18
24
|
|
|
19
|
-
export { TableCell };
|
|
25
|
+
export { FilterVisibility, TableCell };
|
|
@@ -4,9 +4,18 @@ import { useMemo } from 'react';
|
|
|
4
4
|
import { FilterWrapper } from './FilterWrapper.js';
|
|
5
5
|
import { SortIndicator } from './SortIndicator.js';
|
|
6
6
|
import { Resizer, ResizeInner } from './Resizer.js';
|
|
7
|
-
import { TableCell } from './TableCell.js';
|
|
8
|
-
import
|
|
7
|
+
import { TableCell, FilterVisibility } from './TableCell.js';
|
|
8
|
+
import styled from 'styled-components';
|
|
9
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
10
|
|
|
11
|
+
const SortButton = styled.button.withConfig({
|
|
12
|
+
displayName: "TableHeaderCell__SortButton",
|
|
13
|
+
componentId: "sc-1n0j3v0-0"
|
|
14
|
+
})(["cursor:pointer;height:100%;width:calc(100% - 5px);display:flex;flex-direction:row;align-items:center;background:transparent;border:none;padding-left:var(--eds_table__cell__padding_x,16px);padding-right:var(--eds_table__cell__padding_x,16px);margin:0;outline:none;color:inherit;text-align:left;font:inherit;"]);
|
|
15
|
+
const TableHeaderCellLabel = styled.div.withConfig({
|
|
16
|
+
displayName: "TableHeaderCell__TableHeaderCellLabel",
|
|
17
|
+
componentId: "sc-1n0j3v0-1"
|
|
18
|
+
})(["display:flex;flex-direction:column;"]);
|
|
10
19
|
const getSortLabel = sorted => {
|
|
11
20
|
if (sorted) {
|
|
12
21
|
return `${sorted}ending`;
|
|
@@ -20,12 +29,32 @@ function TableHeaderCell({
|
|
|
20
29
|
const ctx = useTableContext();
|
|
21
30
|
const table = ctx.table;
|
|
22
31
|
const pinned = header.column.getIsPinned();
|
|
32
|
+
const isFiltered = header.column.getIsFiltered();
|
|
33
|
+
const filterValue = header.column.getFilterValue();
|
|
34
|
+
const hasActiveFilters = useMemo(() => {
|
|
35
|
+
if (!isFiltered) return false;
|
|
36
|
+
if (Array.isArray(filterValue)) {
|
|
37
|
+
return filterValue.length > 0 && filterValue.some(v => !!v || v === 0); // avoid empty strings counting
|
|
38
|
+
}
|
|
39
|
+
return !!filterValue;
|
|
40
|
+
}, [isFiltered, filterValue]);
|
|
41
|
+
const canSort = header.column.getCanSort();
|
|
42
|
+
const canFilter = header.column.getCanFilter();
|
|
23
43
|
const offset = useMemo(() => {
|
|
24
44
|
if (!pinned) {
|
|
25
45
|
return null;
|
|
26
46
|
}
|
|
27
47
|
return pinned === 'left' ? header.getStart() : table.getTotalSize() - header.getStart() - header.getSize();
|
|
28
48
|
}, [pinned, header, table]);
|
|
49
|
+
const tableCellPadding = useMemo(() => {
|
|
50
|
+
if (canSort && canFilter) {
|
|
51
|
+
return '0 var(--eds_table__cell__padding_x, 16px) 0 0';
|
|
52
|
+
}
|
|
53
|
+
if (canSort) {
|
|
54
|
+
return '0';
|
|
55
|
+
}
|
|
56
|
+
return '0 var(--eds_table__cell__padding_x, 16px) 0 var(--eds_table__cell__padding_x, 16px)';
|
|
57
|
+
}, [canSort, canFilter]);
|
|
29
58
|
return header.isPlaceholder ? /*#__PURE__*/jsx(TableCell, {
|
|
30
59
|
$sticky: ctx.stickyHeader,
|
|
31
60
|
$offset: offset,
|
|
@@ -39,39 +68,39 @@ function TableHeaderCell({
|
|
|
39
68
|
$sticky: ctx.stickyHeader,
|
|
40
69
|
$offset: offset,
|
|
41
70
|
$pinned: pinned,
|
|
71
|
+
$activeFilter: hasActiveFilters,
|
|
42
72
|
className: ctx.headerClass ? ctx.headerClass(header.column) : '',
|
|
43
73
|
"aria-sort": getSortLabel(header.column.getIsSorted()),
|
|
44
|
-
onClick: header.column.getToggleSortingHandler(),
|
|
45
74
|
colSpan: header.colSpan,
|
|
46
75
|
style: {
|
|
47
76
|
width: header.getSize(),
|
|
48
77
|
verticalAlign: ctx.enableColumnFiltering ? 'top' : 'middle',
|
|
49
|
-
...(ctx.headerStyle ? ctx.headerStyle(header.column) : {})
|
|
78
|
+
...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
|
|
79
|
+
padding: tableCellPadding
|
|
50
80
|
},
|
|
51
|
-
children: [/*#__PURE__*/jsxs(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
children:
|
|
58
|
-
className: "table-header-cell-label",
|
|
59
|
-
children: flexRender(header.column.columnDef.header, header.getContext())
|
|
60
|
-
})
|
|
81
|
+
children: [canSort ? /*#__PURE__*/jsxs(SortButton, {
|
|
82
|
+
tabIndex: -1,
|
|
83
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
84
|
+
"data-testid": `sort-button-${header.id}`,
|
|
85
|
+
children: [/*#__PURE__*/jsx(TableHeaderCellLabel, {
|
|
86
|
+
className: "table-header-cell-label",
|
|
87
|
+
children: flexRender(header.column.columnDef.header, header.getContext())
|
|
61
88
|
}), !header.column.columnDef.meta?.customFilterInput && /*#__PURE__*/jsx(SortIndicator, {
|
|
62
89
|
column: header.column
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}) : null]
|
|
73
|
-
}), columnResizeMode && /*#__PURE__*/jsx(Resizer, {
|
|
90
|
+
})]
|
|
91
|
+
}) : /*#__PURE__*/jsx(TableHeaderCellLabel, {
|
|
92
|
+
className: "table-header-cell-label",
|
|
93
|
+
children: flexRender(header.column.columnDef.header, header.getContext())
|
|
94
|
+
}), canFilter && !header.column.columnDef.meta?.customFilterInput ?
|
|
95
|
+
/*#__PURE__*/
|
|
96
|
+
// Supressing this warning - div is not interactive, but prevents propagation of events to avoid unintended sorting
|
|
97
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
|
98
|
+
jsx(FilterVisibility, {
|
|
74
99
|
onClick: e => e.stopPropagation(),
|
|
100
|
+
children: /*#__PURE__*/jsx(FilterWrapper, {
|
|
101
|
+
column: header.column
|
|
102
|
+
})
|
|
103
|
+
}) : null, columnResizeMode && /*#__PURE__*/jsx(Resizer, {
|
|
75
104
|
onMouseDown: header.getResizeHandler(),
|
|
76
105
|
onTouchStart: header.getResizeHandler(),
|
|
77
106
|
$isResizing: header.column.getIsResizing(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HTMLAttributes, ForwardedRef } from 'react';
|
|
2
2
|
import { EdsDataGridProps } from './EdsDataGridProps';
|
|
3
|
-
declare function EdsDataGridInner<T>({ rows, columns, columnResizeMode, pageSize, rowSelection, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, selectedRows, rowSelectionState, enableColumnFiltering, debug, enablePagination, enableSorting, stickyHeader, stickyFooter, onSelectRow, onRowSelectionChange, caption, enableVirtual, virtualHeight, columnVisibility, columnVisibilityChange, emptyMessage, columnOrder, cellClass, cellStyle, rowClass, rowStyle, headerClass, headerStyle, footerClass, footerStyle, externalPaginator, onSortingChange, manualSorting, sortingState, columnPinState, scrollbarHorizontal, width, minWidth, height, getRowId, rowVirtualizerInstanceRef, tableInstanceRef, columnSizing, onColumnResize, expansionState, setExpansionState, getSubRows, defaultColumn, onRowContextMenu, onRowClick, onRowDoubleClick, onCellClick, enableFooter, enableSortingRemoval, ...rest }: EdsDataGridProps<T> & HTMLAttributes<HTMLDivElement>, ref: ForwardedRef<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
declare function EdsDataGridInner<T>({ rows, columns, columnResizeMode, pageSize, rowSelection, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, selectedRows, rowSelectionState, enableColumnFiltering, columnFiltersState, onColumnFiltersChange, debug, enablePagination, enableSorting, stickyHeader, stickyFooter, onSelectRow, onRowSelectionChange, caption, enableVirtual, virtualHeight, columnVisibility, columnVisibilityChange, emptyMessage, columnOrder, cellClass, cellStyle, rowClass, rowStyle, headerClass, headerStyle, footerClass, footerStyle, externalPaginator, onSortingChange, manualSorting, sortingState, columnPinState, scrollbarHorizontal, width, minWidth, height, getRowId, rowVirtualizerInstanceRef, tableInstanceRef, columnSizing, onColumnResize, expansionState, setExpansionState, getSubRows, defaultColumn, onRowContextMenu, onRowClick, onRowDoubleClick, onCellClick, enableFooter, enableSortingRemoval, ...rest }: EdsDataGridProps<T> & HTMLAttributes<HTMLDivElement>, ref: ForwardedRef<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
export declare const EdsDataGrid: <T>(props: EdsDataGridProps<T> & HTMLAttributes<HTMLDivElement> & {
|
|
5
5
|
ref?: ForwardedRef<HTMLDivElement>;
|
|
6
6
|
}) => ReturnType<typeof EdsDataGridInner>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Cell, Column, ColumnDef, ColumnPinningState, ColumnResizeMode, ColumnSizingState, ExpandedState, OnChangeFn, Row, RowSelectionState, SortingState, Table, TableOptions } from '@tanstack/react-table';
|
|
1
|
+
import { Cell, Column, ColumnDef, ColumnFilter, ColumnPinningState, ColumnResizeMode, ColumnSizingState, ExpandedState, OnChangeFn, Row, RowSelectionState, SortingState, Table, TableOptions } from '@tanstack/react-table';
|
|
2
2
|
import { Virtualizer } from '@tanstack/react-virtual';
|
|
3
3
|
import { CSSProperties, MouseEvent, MutableRefObject, ReactElement } from 'react';
|
|
4
4
|
type BaseProps<T> = {
|
|
@@ -184,6 +184,16 @@ type FilterProps = {
|
|
|
184
184
|
* @default false
|
|
185
185
|
*/
|
|
186
186
|
enableColumnFiltering?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Initial filter state
|
|
189
|
+
* @default undefined
|
|
190
|
+
*/
|
|
191
|
+
columnFiltersState?: Array<ColumnFilter>;
|
|
192
|
+
/**
|
|
193
|
+
* Callback for when the filter state changes
|
|
194
|
+
* @default undefined
|
|
195
|
+
*/
|
|
196
|
+
onColumnFiltersChange?: OnChangeFn<Array<ColumnFilter>>;
|
|
187
197
|
};
|
|
188
198
|
type HandlersProps<T> = {
|
|
189
199
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ColumnPinningPosition } from '@tanstack/react-table';
|
|
2
|
+
export declare const FilterVisibility: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
2
3
|
export declare const TableCell: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<(Omit<{
|
|
3
4
|
variant?: import("@equinor/eds-core-react/dist/types/components/Table/Table.types").Variants;
|
|
4
5
|
color?: import("@equinor/eds-core-react/dist/types/components/Table/Table.types").Colors;
|
|
@@ -15,4 +16,5 @@ export declare const TableCell: import("styled-components/dist/types").IStyledCo
|
|
|
15
16
|
$sticky: boolean;
|
|
16
17
|
$pinned: ColumnPinningPosition;
|
|
17
18
|
$offset: number;
|
|
19
|
+
$activeFilter?: boolean;
|
|
18
20
|
}>> & string & Omit<import("react").ForwardRefExoticComponent<import("@equinor/eds-core-react").CellProps & import("react").RefAttributes<HTMLTableCellElement>>, keyof import("react").Component<any, {}, any>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/eds-data-grid-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "A feature-rich data-grid written in React, implementing the Equinor Design System",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -20,53 +20,53 @@
|
|
|
20
20
|
"styled-components": ">=5.1"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@tanstack/react-table": "^8.
|
|
24
|
-
"@tanstack/react-virtual": "^3.13.
|
|
23
|
+
"@tanstack/react-table": "^8.21.3",
|
|
24
|
+
"@tanstack/react-virtual": "^3.13.6",
|
|
25
25
|
"@equinor/eds-icons": "^0.22.0",
|
|
26
|
-
"@equinor/eds-
|
|
27
|
-
"@equinor/eds-
|
|
26
|
+
"@equinor/eds-tokens": "0.9.2",
|
|
27
|
+
"@equinor/eds-utils": "^0.8.7"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@rollup/plugin-babel": "^6.0.4",
|
|
31
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
32
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
33
|
-
"@storybook/addon-a11y": "^8.
|
|
34
|
-
"@storybook/addon-actions": "^8.
|
|
35
|
-
"@storybook/addon-docs": "^8.
|
|
36
|
-
"@storybook/addon-essentials": "^8.
|
|
37
|
-
"@storybook/addon-links": "^8.
|
|
38
|
-
"@storybook/blocks": "^8.
|
|
39
|
-
"@storybook/preview-api": "^8.
|
|
40
|
-
"@storybook/react": "^8.
|
|
41
|
-
"@storybook/react-vite": "^8.
|
|
31
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
32
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
33
|
+
"@storybook/addon-a11y": "^8.6.12",
|
|
34
|
+
"@storybook/addon-actions": "^8.6.12",
|
|
35
|
+
"@storybook/addon-docs": "^8.6.12",
|
|
36
|
+
"@storybook/addon-essentials": "^8.6.12",
|
|
37
|
+
"@storybook/addon-links": "^8.6.12",
|
|
38
|
+
"@storybook/blocks": "^8.6.12",
|
|
39
|
+
"@storybook/preview-api": "^8.6.12",
|
|
40
|
+
"@storybook/react": "^8.6.12",
|
|
41
|
+
"@storybook/react-vite": "^8.6.12",
|
|
42
42
|
"@testing-library/dom": "^10.4.0",
|
|
43
43
|
"@testing-library/jest-dom": "^6.6.3",
|
|
44
44
|
"@testing-library/react": "16.3.0",
|
|
45
|
-
"@testing-library/user-event": "^14.
|
|
45
|
+
"@testing-library/user-event": "^14.6.1",
|
|
46
46
|
"@types/jest": "^29.5.14",
|
|
47
|
-
"@types/node": "^22.
|
|
47
|
+
"@types/node": "^22.15.3",
|
|
48
48
|
"@types/ramda": "^0.30.2",
|
|
49
|
-
"@types/react": "^18.3.
|
|
50
|
-
"@types/react-dom": "^18.3.
|
|
49
|
+
"@types/react": "^18.3.20",
|
|
50
|
+
"@types/react-dom": "^18.3.6",
|
|
51
51
|
"babel-plugin-styled-components": "^2.1.4",
|
|
52
52
|
"jest": "29.7.0",
|
|
53
53
|
"jest-environment-jsdom": "29.7.0",
|
|
54
54
|
"jest-styled-components": "^7.2.0",
|
|
55
55
|
"js-file-download": "^0.4.12",
|
|
56
|
-
"postcss": "^8.
|
|
56
|
+
"postcss": "^8.5.3",
|
|
57
57
|
"ramda": "^0.30.1",
|
|
58
58
|
"react": "^18.3.1",
|
|
59
59
|
"react-dom": "^18.3.1",
|
|
60
|
-
"react-hook-form": "^7.
|
|
61
|
-
"rollup": "^4.
|
|
62
|
-
"rollup-plugin-delete": "^2.
|
|
60
|
+
"react-hook-form": "^7.56.1",
|
|
61
|
+
"rollup": "^4.40.1",
|
|
62
|
+
"rollup-plugin-delete": "^2.2.0",
|
|
63
63
|
"rollup-plugin-postcss": "^4.0.2",
|
|
64
|
-
"storybook": "^8.
|
|
64
|
+
"storybook": "^8.6.12",
|
|
65
65
|
"styled-components": "6.1.17",
|
|
66
|
-
"ts-jest": "29.2
|
|
66
|
+
"ts-jest": "29.3.2",
|
|
67
67
|
"ts-node": "10.9.2",
|
|
68
68
|
"tsc-watch": "^6.2.1",
|
|
69
|
-
"typescript": "~5.8.
|
|
69
|
+
"typescript": "~5.8.3"
|
|
70
70
|
},
|
|
71
71
|
"homepage": "https://eds.equinor.com",
|
|
72
72
|
"repository": {
|