@patternfly/react-table 4.30.18 → 4.31.2
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/CHANGELOG.md +35 -0
- package/dist/umd/react-table.css +8926 -8855
- package/dist/umd/react-table.min.css +9028 -8957
- package/package.json +6 -6
- package/src/components/Table/examples/Table.md +181 -71
- package/src/components/TableComposable/examples/ComposableTable.md +209 -52
- package/src/demos/Table.md +552 -159
|
@@ -12,26 +12,26 @@ propComponents:
|
|
|
12
12
|
'Td',
|
|
13
13
|
'Caption',
|
|
14
14
|
'TableText',
|
|
15
|
-
'TdActionsType',
|
|
16
|
-
'TdSelectType',
|
|
15
|
+
'TdActionsType',
|
|
16
|
+
'TdSelectType',
|
|
17
17
|
'ThSelectType',
|
|
18
|
-
'TdTreeRowType',
|
|
19
|
-
'IActions',
|
|
20
|
-
'TdCompoundExpandType',
|
|
21
|
-
'TdFavoritesType',
|
|
22
|
-
'TdDraggableType',
|
|
23
|
-
'ThInfoType',
|
|
18
|
+
'TdTreeRowType',
|
|
19
|
+
'IActions',
|
|
20
|
+
'TdCompoundExpandType',
|
|
21
|
+
'TdFavoritesType',
|
|
22
|
+
'TdDraggableType',
|
|
23
|
+
'ThInfoType',
|
|
24
24
|
'TdExpandType',
|
|
25
25
|
'EditableSelectInputCell',
|
|
26
26
|
'EditableTextCell',
|
|
27
|
-
'EditableSelectInputProps',
|
|
28
|
-
'EditableTextCellProps',
|
|
27
|
+
'EditableSelectInputProps',
|
|
28
|
+
'EditableTextCellProps',
|
|
29
29
|
'ThSortType',
|
|
30
30
|
]
|
|
31
31
|
ouia: true
|
|
32
32
|
---
|
|
33
|
-
# Table Composable
|
|
34
33
|
|
|
34
|
+
# Table Composable
|
|
35
35
|
|
|
36
36
|
Note: Table lives in its own package at [@patternfly/react-table](https://www.npmjs.com/package/@patternfly/react-table)!
|
|
37
37
|
|
|
@@ -50,8 +50,7 @@ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
|
50
50
|
import LeafIcon from '@patternfly/react-icons/dist/esm/icons/leaf-icon';
|
|
51
51
|
import FolderIcon from '@patternfly/react-icons/dist/esm/icons/folder-icon';
|
|
52
52
|
import FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-icon';
|
|
53
|
-
|
|
54
|
-
import { Checkbox, ToggleGroup, ToggleGroupItem } from '@patternfly/react-core';
|
|
53
|
+
import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
|
|
55
54
|
|
|
56
55
|
import { css } from '@patternfly/react-styles';
|
|
57
56
|
import styles from '@patternfly/react-styles/css/components/Table/table';
|
|
@@ -60,7 +59,6 @@ import DemoSortableTable from './DemoSortableTable';
|
|
|
60
59
|
|
|
61
60
|
## TableComposable examples
|
|
62
61
|
|
|
63
|
-
|
|
64
62
|
The `TableComposable` component differs from the regular `Table` component, in that it allows you to compose the table by nesting the relevant `Thead`, `Tbody`, `Tr`, `Th` and `Td` components within it. For a less declarative and more implicit approach, use the `Table` component instead.
|
|
65
63
|
|
|
66
64
|
Some general notes:
|
|
@@ -70,6 +68,7 @@ Some general notes:
|
|
|
70
68
|
- You can set the `TableComposable` variant to `compact`
|
|
71
69
|
|
|
72
70
|
### Composable: Basic
|
|
71
|
+
|
|
73
72
|
```js
|
|
74
73
|
import React from 'react';
|
|
75
74
|
import { TableComposable, Thead, Tbody, Tr, Th, Td, Caption } from '@patternfly/react-table';
|
|
@@ -158,7 +157,7 @@ ComposableTableMisc = () => {
|
|
|
158
157
|
[{ title: 'one - 2', colSpan: 3 }, null, null, 'four - 2', 'five - 2'],
|
|
159
158
|
['one - 3', 'two - 3', 'three - 3', 'four - 3', { title: 'five - 3 (not centered)', textCenter: false }]
|
|
160
159
|
];
|
|
161
|
-
|
|
160
|
+
|
|
162
161
|
return (
|
|
163
162
|
<TableComposable aria-label="Misc table">
|
|
164
163
|
<Thead noWrap>
|
|
@@ -256,6 +255,8 @@ type OnSort = (
|
|
|
256
255
|
|
|
257
256
|
```
|
|
258
257
|
|
|
258
|
+
The built in display for sorting is not fully responsive, as the column headers will be displayed per row when the screen size is small. To see a full page demo of a responsive sortable table, utilizing a toolbar item to control sorting for small screens, view the `Sortable - responsive` demo in the `React demos` tab.
|
|
259
|
+
|
|
259
260
|
```js
|
|
260
261
|
import React from 'react';
|
|
261
262
|
import { TableComposable, Thead, Tbody, Tr, Th, Td } from '@patternfly/react-table';
|
|
@@ -351,10 +352,166 @@ ComposableTableSortable = () => {
|
|
|
351
352
|
};
|
|
352
353
|
```
|
|
353
354
|
|
|
355
|
+
### Composable: Sortable - custom control
|
|
356
|
+
|
|
357
|
+
Sorting a table may also be controlled manually with a toolbar control. To see a full page demo of a responsive table, view the `Sortable - responsive` demo in the `React demos` tab.
|
|
358
|
+
|
|
359
|
+
```js
|
|
360
|
+
import React from 'react';
|
|
361
|
+
import { TableComposable, Thead, Tbody, Tr, Th, Td } from '@patternfly/react-table';
|
|
362
|
+
import {
|
|
363
|
+
Toolbar,
|
|
364
|
+
ToolbarItem,
|
|
365
|
+
ToolbarContent,
|
|
366
|
+
OptionsMenu,
|
|
367
|
+
OptionsMenuItemGroup,
|
|
368
|
+
OptionsMenuItem,
|
|
369
|
+
OptionsMenuSeparator,
|
|
370
|
+
OptionsMenuToggle
|
|
371
|
+
} from '@patternfly/react-core';
|
|
372
|
+
import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
|
|
373
|
+
|
|
374
|
+
ComposableTableSortable = () => {
|
|
375
|
+
const columns = ['Column 1', 'Column 2', 'Column 3', 'Column 4', 'Column 5'];
|
|
376
|
+
const [rows, setRows] = React.useState([
|
|
377
|
+
['one', 'two', 'a', 'four', 'five'],
|
|
378
|
+
['a', 'two', 'k', 'four', 'five'],
|
|
379
|
+
['p', 'two', 'b', 'four', 'five']
|
|
380
|
+
]);
|
|
381
|
+
// index of the currently active column
|
|
382
|
+
const [activeSortIndex, setActiveSortIndex] = React.useState(-1);
|
|
383
|
+
// sort direction of the currently active column
|
|
384
|
+
const [activeSortDirection, setActiveSortDirection] = React.useState('none');
|
|
385
|
+
// sort dropdown expansion
|
|
386
|
+
const [isSortDropdownOpen, setIsSortDropdownOpen] = React.useState(false);
|
|
387
|
+
const onSort = (event, index, direction) => {
|
|
388
|
+
setActiveSortIndex(index);
|
|
389
|
+
setActiveSortDirection(direction);
|
|
390
|
+
console.log('i; ', index, direction);
|
|
391
|
+
// sorts the rows
|
|
392
|
+
const updatedRows = rows.sort((a, b) => {
|
|
393
|
+
if (typeof a[index] === 'number') {
|
|
394
|
+
// numeric sort
|
|
395
|
+
if (direction === 'asc') {
|
|
396
|
+
return a[index] - b[index];
|
|
397
|
+
}
|
|
398
|
+
return b[index] - a[index];
|
|
399
|
+
} else {
|
|
400
|
+
// string sort
|
|
401
|
+
if (direction === 'asc') {
|
|
402
|
+
return a[index].localeCompare(b[index]);
|
|
403
|
+
}
|
|
404
|
+
return b[index].localeCompare(a[index]);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
setRows(updatedRows);
|
|
408
|
+
};
|
|
409
|
+
return (
|
|
410
|
+
<React.Fragment>
|
|
411
|
+
<Toolbar id="toolbar">
|
|
412
|
+
<ToolbarContent>
|
|
413
|
+
<ToolbarItem>
|
|
414
|
+
<OptionsMenu
|
|
415
|
+
id="options-menu-multiple-options-example"
|
|
416
|
+
menuItems={[
|
|
417
|
+
<OptionsMenuItemGroup key="first group" aria-label="Sort column">
|
|
418
|
+
{columns.map((column, columnIndex) => (
|
|
419
|
+
<OptionsMenuItem
|
|
420
|
+
key={column}
|
|
421
|
+
isSelected={activeSortIndex === columnIndex}
|
|
422
|
+
onSelect={evt =>
|
|
423
|
+
onSort(evt, columnIndex, activeSortDirection !== 'none' ? activeSortDirection : 'asc')
|
|
424
|
+
}
|
|
425
|
+
>
|
|
426
|
+
{column}
|
|
427
|
+
</OptionsMenuItem>
|
|
428
|
+
))}
|
|
429
|
+
</OptionsMenuItemGroup>,
|
|
430
|
+
<OptionsMenuSeparator key="separator" />,
|
|
431
|
+
<OptionsMenuItemGroup key="second group" aria-label="Sort direction">
|
|
432
|
+
<OptionsMenuItem
|
|
433
|
+
onSelect={evt => onSort(evt, activeSortIndex, 'asc')}
|
|
434
|
+
isSelected={activeSortDirection === 'asc'}
|
|
435
|
+
id="ascending"
|
|
436
|
+
key="ascending"
|
|
437
|
+
>
|
|
438
|
+
Ascending
|
|
439
|
+
</OptionsMenuItem>
|
|
440
|
+
<OptionsMenuItem
|
|
441
|
+
onSelect={evt => onSort(evt, activeSortIndex, 'desc')}
|
|
442
|
+
isSelected={activeSortDirection === 'desc'}
|
|
443
|
+
id="descending"
|
|
444
|
+
key="descending"
|
|
445
|
+
>
|
|
446
|
+
Descending
|
|
447
|
+
</OptionsMenuItem>
|
|
448
|
+
</OptionsMenuItemGroup>
|
|
449
|
+
]}
|
|
450
|
+
isOpen={isSortDropdownOpen}
|
|
451
|
+
toggle={
|
|
452
|
+
<OptionsMenuToggle
|
|
453
|
+
hideCaret
|
|
454
|
+
onToggle={() => setIsSortDropdownOpen(!isSortDropdownOpen)}
|
|
455
|
+
toggleTemplate={<SortAmountDownIcon />}
|
|
456
|
+
/>
|
|
457
|
+
}
|
|
458
|
+
isPlain
|
|
459
|
+
isGrouped
|
|
460
|
+
/>
|
|
461
|
+
</ToolbarItem>
|
|
462
|
+
</ToolbarContent>
|
|
463
|
+
</Toolbar>
|
|
464
|
+
<TableComposable aria-label="Sortable Table">
|
|
465
|
+
<Thead>
|
|
466
|
+
<Tr>
|
|
467
|
+
{columns.map((column, columnIndex) => {
|
|
468
|
+
const sortParams = {
|
|
469
|
+
sort: {
|
|
470
|
+
sortBy: {
|
|
471
|
+
index: activeSortIndex,
|
|
472
|
+
direction: activeSortDirection
|
|
473
|
+
},
|
|
474
|
+
onSort,
|
|
475
|
+
columnIndex
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
const infoParams =
|
|
479
|
+
columnIndex === 2
|
|
480
|
+
? {
|
|
481
|
+
info: {
|
|
482
|
+
tooltip: 'More information'
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
: {};
|
|
486
|
+
return (
|
|
487
|
+
<Th key={columnIndex} {...sortParams} {...infoParams}>
|
|
488
|
+
{column}
|
|
489
|
+
</Th>
|
|
490
|
+
);
|
|
491
|
+
})}
|
|
492
|
+
</Tr>
|
|
493
|
+
</Thead>
|
|
494
|
+
<Tbody>
|
|
495
|
+
{rows.map((row, rowIndex) => (
|
|
496
|
+
<Tr key={rowIndex}>
|
|
497
|
+
{row.map((cell, cellIndex) => (
|
|
498
|
+
<Td key={`${rowIndex}_${cellIndex}`} dataLabel={columns[cellIndex]}>
|
|
499
|
+
{cell}
|
|
500
|
+
</Td>
|
|
501
|
+
))}
|
|
502
|
+
</Tr>
|
|
503
|
+
))}
|
|
504
|
+
</Tbody>
|
|
505
|
+
</TableComposable>
|
|
506
|
+
</React.Fragment>
|
|
507
|
+
);
|
|
508
|
+
};
|
|
509
|
+
```
|
|
510
|
+
|
|
354
511
|
### Composable: Selectable with checkbox
|
|
355
512
|
|
|
356
513
|
To make a row selectable, the table needs a selection column.
|
|
357
|
-
The selection column is just another column, but with selection specific props added.
|
|
514
|
+
The selection column is just another column, but with selection specific props added.
|
|
358
515
|
We add it as the first header cell and also as the first body cell for each row.
|
|
359
516
|
|
|
360
517
|
To make a column sortable, pass a `ThSelectType` object via the `select` prop on a column's `Th`.
|
|
@@ -364,6 +521,7 @@ To make a row sortable, pass a `TdSelectType` object via the `select` prop on ea
|
|
|
364
521
|
Both the `TdSelectType` and the `ThSelectType` expect an `OnSelect` event handler with the following signature:
|
|
365
522
|
|
|
366
523
|
`OnSelect:`
|
|
524
|
+
|
|
367
525
|
```
|
|
368
526
|
type OnSelect = (
|
|
369
527
|
event: React.FormEvent<HTMLInputElement>,
|
|
@@ -373,7 +531,8 @@ type OnSelect = (
|
|
|
373
531
|
extraData: IExtraData
|
|
374
532
|
) => void;
|
|
375
533
|
```
|
|
376
|
-
|
|
534
|
+
|
|
535
|
+
**Note:** This example has a `shift + select` feature where holding shift while
|
|
377
536
|
checking checkboxes will check intermediate rows' checkboxes.
|
|
378
537
|
|
|
379
538
|
```js
|
|
@@ -395,22 +554,23 @@ ComposableTableSelectable = () => {
|
|
|
395
554
|
const [recentSelection, setRecentSelection] = React.useState(null);
|
|
396
555
|
const [shifting, setShifting] = React.useState(false);
|
|
397
556
|
const onSelect = (event, isSelected, rowId) => {
|
|
398
|
-
let newSelected = selected.map((sel, index) => (index === rowId ? isSelected : sel))
|
|
399
|
-
|
|
557
|
+
let newSelected = selected.map((sel, index) => (index === rowId ? isSelected : sel));
|
|
558
|
+
|
|
400
559
|
// if the user is shift + selecting the checkboxes, then all intermediate checkboxes should be selected
|
|
401
560
|
if (shifting && recentSelection !== null && isSelected) {
|
|
402
561
|
const numberSelected = rowId - recentSelection;
|
|
403
562
|
newSelected = newSelected.map((sel, index) => {
|
|
404
563
|
// select all between recentSelection and current rowId;
|
|
405
|
-
const intermediateIndexes =
|
|
406
|
-
|
|
407
|
-
|
|
564
|
+
const intermediateIndexes =
|
|
565
|
+
numberSelected > 0
|
|
566
|
+
? Array.from(new Array(numberSelected + 1), (x, i) => i + recentSelection)
|
|
567
|
+
: Array.from(new Array(Math.abs(numberSelected) + 1), (x, i) => i + rowId);
|
|
408
568
|
return intermediateIndexes.includes(index) ? true : sel;
|
|
409
|
-
})
|
|
569
|
+
});
|
|
410
570
|
}
|
|
411
571
|
setSelected(newSelected);
|
|
412
572
|
setRecentSelection(rowId);
|
|
413
|
-
|
|
573
|
+
|
|
414
574
|
if (!isSelected && allRowsSelected) {
|
|
415
575
|
setAllRowsSelected(false);
|
|
416
576
|
} else if (isSelected && !allRowsSelected) {
|
|
@@ -427,33 +587,33 @@ ComposableTableSelectable = () => {
|
|
|
427
587
|
}
|
|
428
588
|
}
|
|
429
589
|
};
|
|
430
|
-
|
|
431
|
-
onKeyDown =
|
|
590
|
+
|
|
591
|
+
onKeyDown = e => {
|
|
432
592
|
if (e.key === 'Shift') {
|
|
433
593
|
setShifting(true);
|
|
434
594
|
}
|
|
435
595
|
};
|
|
436
|
-
onKeyUp =
|
|
596
|
+
onKeyUp = e => {
|
|
437
597
|
if (e.key === 'Shift') {
|
|
438
598
|
setShifting(false);
|
|
439
599
|
}
|
|
440
600
|
};
|
|
441
|
-
|
|
601
|
+
|
|
442
602
|
React.useEffect(() => {
|
|
443
|
-
document.addEventListener(
|
|
444
|
-
document.addEventListener(
|
|
445
|
-
|
|
603
|
+
document.addEventListener('keydown', onKeyDown);
|
|
604
|
+
document.addEventListener('keyup', onKeyUp);
|
|
605
|
+
|
|
446
606
|
return () => {
|
|
447
|
-
document.removeEventListener(
|
|
448
|
-
document.removeEventListener(
|
|
449
|
-
}
|
|
607
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
608
|
+
document.removeEventListener('keyup', onKeyUp);
|
|
609
|
+
};
|
|
450
610
|
}, []);
|
|
451
|
-
|
|
611
|
+
|
|
452
612
|
const onSelectAll = (event, isSelected) => {
|
|
453
613
|
setAllRowsSelected(isSelected);
|
|
454
614
|
setSelected(selected.map(sel => isSelected));
|
|
455
615
|
};
|
|
456
|
-
|
|
616
|
+
|
|
457
617
|
return (
|
|
458
618
|
<TableComposable aria-label="Selectable Table">
|
|
459
619
|
<Thead>
|
|
@@ -570,27 +730,23 @@ import { TableComposable, Thead, Tbody, Tr, Th, Td } from '@patternfly/react-tab
|
|
|
570
730
|
ComposableTableHoverable = () => {
|
|
571
731
|
const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];
|
|
572
732
|
const [rows, setRows] = React.useState([
|
|
573
|
-
{ cells: ['one', 'two', 'a', 'four', 'five'], isRowSelected: false},
|
|
574
|
-
{ cells: ['a', 'two', 'k', 'four', 'five'], isRowSelected: false},
|
|
575
|
-
{ cells: ['p', 'two', 'b', 'four', 'five'], isRowSelected: false}
|
|
733
|
+
{ cells: ['one', 'two', 'a', 'four', 'five'], isRowSelected: false },
|
|
734
|
+
{ cells: ['a', 'two', 'k', 'four', 'five'], isRowSelected: false },
|
|
735
|
+
{ cells: ['p', 'two', 'b', 'four', 'five'], isRowSelected: false }
|
|
576
736
|
]);
|
|
577
737
|
const onRowClick = (event, rowIndex, row) => {
|
|
578
738
|
const updatedRows = [...rows];
|
|
579
739
|
updatedRows[rowIndex].isRowSelected = !rows[rowIndex].isRowSelected;
|
|
580
|
-
setRows(updatedRows);
|
|
740
|
+
setRows(updatedRows);
|
|
581
741
|
};
|
|
582
|
-
|
|
742
|
+
|
|
583
743
|
return (
|
|
584
744
|
<TableComposable aria-label="Misc table">
|
|
585
745
|
<Thead noWrap>
|
|
586
746
|
<Tr>
|
|
587
|
-
<Th>
|
|
588
|
-
{columns[0]}
|
|
589
|
-
</Th>
|
|
747
|
+
<Th>{columns[0]}</Th>
|
|
590
748
|
<Th>{columns[1]}</Th>
|
|
591
|
-
<Th>
|
|
592
|
-
{columns[2]}
|
|
593
|
-
</Th>
|
|
749
|
+
<Th>{columns[2]}</Th>
|
|
594
750
|
<Th>{columns[3]}</Th>
|
|
595
751
|
<Th>{columns[4]}</Th>
|
|
596
752
|
</Tr>
|
|
@@ -606,10 +762,7 @@ ComposableTableHoverable = () => {
|
|
|
606
762
|
>
|
|
607
763
|
{row.cells.map((cell, cellIndex) => {
|
|
608
764
|
return (
|
|
609
|
-
<Td
|
|
610
|
-
key={`${rowIndex}_${cellIndex}`}
|
|
611
|
-
dataLabel={columns[cellIndex]}
|
|
612
|
-
>
|
|
765
|
+
<Td key={`${rowIndex}_${cellIndex}`} dataLabel={columns[cellIndex]}>
|
|
613
766
|
{cell}
|
|
614
767
|
</Td>
|
|
615
768
|
);
|
|
@@ -750,6 +903,7 @@ ComposableTableActions = () => {
|
|
|
750
903
|
### Composable: Expandable
|
|
751
904
|
|
|
752
905
|
To make a parent/child row pair expandable:
|
|
906
|
+
|
|
753
907
|
1. Make the first cell in every row an expandable cell by passing `TdExpandType` object to the `expand` prop on the `Td`
|
|
754
908
|
2. Wrap the content of each child row cell in `ExpandableRowContent`.
|
|
755
909
|
3. Enclose each parent/child row pair in a `Tbody` component with an `isExpanded` prop.
|
|
@@ -930,11 +1084,13 @@ ComposableTableExpandable = () => {
|
|
|
930
1084
|
### Composable: Compound expandable
|
|
931
1085
|
|
|
932
1086
|
To make a parent/child row pair compound expandable:
|
|
1087
|
+
|
|
933
1088
|
1. Pass a `TdCompoundExpandType` object to the `compoundExpand` prop on any `Td` that has an expandable child row
|
|
934
1089
|
2. Wrap the content of each child row cell in `ExpandableRowContent`.
|
|
935
1090
|
3. Each child `Tr` has an `isExpanded` prop.
|
|
936
1091
|
|
|
937
1092
|
The `TdCompoundExpandType` expects an `OnExpand` event handler with the following signature
|
|
1093
|
+
|
|
938
1094
|
```
|
|
939
1095
|
export type OnExpand = (
|
|
940
1096
|
event: React.MouseEvent,
|
|
@@ -1647,7 +1803,8 @@ class TreeTable extends React.Component {
|
|
|
1647
1803
|
|
|
1648
1804
|
### Composable: Draggable row table
|
|
1649
1805
|
|
|
1650
|
-
To make a row draggable:
|
|
1806
|
+
To make a row draggable:
|
|
1807
|
+
|
|
1651
1808
|
1. The table needs a draggable column.
|
|
1652
1809
|
2. Each draggable `Tr` needs to be passed `draggable`, `onDrop`, `onDragEnd`, and `onDragStart` props.
|
|
1653
1810
|
3. The `Tbody` needs `onDragOver`, `onDrop`, and `onDragLeave` props.
|