@patternfly/react-table 4.44.11 → 4.44.15

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/esm/components/Table/Table.d.ts +2 -1
  3. package/dist/esm/components/Table/Table.d.ts.map +1 -1
  4. package/dist/esm/components/Table/Table.js.map +1 -1
  5. package/dist/esm/components/Table/TableTypes.d.ts +2 -1
  6. package/dist/esm/components/Table/TableTypes.d.ts.map +1 -1
  7. package/dist/esm/components/Table/TableTypes.js.map +1 -1
  8. package/dist/esm/components/Table/base/provider.d.ts +2 -2
  9. package/dist/esm/components/Table/base/types.d.ts +2 -2
  10. package/dist/esm/components/TableComposable/TableComposable.d.ts +1 -1
  11. package/dist/esm/components/TableComposable/Td.d.ts +1 -1
  12. package/dist/js/components/Table/Table.d.ts +2 -1
  13. package/dist/js/components/Table/Table.d.ts.map +1 -1
  14. package/dist/js/components/Table/Table.js.map +1 -1
  15. package/dist/js/components/Table/TableTypes.d.ts +2 -1
  16. package/dist/js/components/Table/TableTypes.d.ts.map +1 -1
  17. package/dist/js/components/Table/TableTypes.js.map +1 -1
  18. package/dist/js/components/Table/base/provider.d.ts +2 -2
  19. package/dist/js/components/Table/base/types.d.ts +2 -2
  20. package/dist/js/components/TableComposable/TableComposable.d.ts +1 -1
  21. package/dist/js/components/TableComposable/Td.d.ts +1 -1
  22. package/package.json +6 -6
  23. package/src/components/Table/Table.tsx +2 -1
  24. package/src/components/Table/TableTypes.tsx +2 -1
  25. package/src/components/Table/examples/LegacyTableActions.tsx +218 -0
  26. package/src/components/Table/examples/LegacyTableBasic.tsx +90 -0
  27. package/src/components/Table/examples/LegacyTableCellWidth.tsx +66 -0
  28. package/src/components/Table/examples/LegacyTableCompoundExpandable.tsx +175 -0
  29. package/src/components/Table/examples/LegacyTableControllingText.tsx +51 -0
  30. package/src/components/Table/examples/LegacyTableEmptyState.tsx +48 -0
  31. package/src/components/Table/examples/LegacyTableExpandable.tsx +172 -0
  32. package/src/components/Table/examples/LegacyTableFavoritable.tsx +157 -0
  33. package/src/components/Table/examples/LegacyTableHoverable.tsx +125 -0
  34. package/src/components/Table/examples/LegacyTableMisc.tsx +56 -0
  35. package/src/components/Table/examples/LegacyTableSelectable.tsx +124 -0
  36. package/src/components/Table/examples/LegacyTableSelectableRadio.tsx +54 -0
  37. package/src/components/Table/examples/LegacyTableSortable.tsx +120 -0
  38. package/src/components/Table/examples/LegacyTableSortableCustom.tsx +189 -0
  39. package/src/components/Table/examples/LegacyTableTextModifiers.tsx +31 -0
  40. package/src/components/Table/examples/LegacyTableTree.tsx +213 -0
  41. package/src/components/Table/examples/Table.md +83 -1848
  42. package/src/components/TableComposable/examples/ComposableTable.md +31 -2805
  43. package/src/components/TableComposable/examples/ComposableTableActions.tsx +163 -0
  44. package/src/components/TableComposable/examples/ComposableTableBasic.tsx +89 -0
  45. package/src/components/TableComposable/examples/ComposableTableCellWidth.tsx +56 -0
  46. package/src/components/TableComposable/examples/ComposableTableCompoundExpandable.tsx +103 -0
  47. package/src/components/TableComposable/examples/ComposableTableControllingText.tsx +51 -0
  48. package/src/components/TableComposable/examples/ComposableTableDraggable.tsx +170 -0
  49. package/src/components/TableComposable/examples/ComposableTableEmptyState.tsx +45 -0
  50. package/src/components/TableComposable/examples/ComposableTableExpandable.tsx +195 -0
  51. package/src/components/TableComposable/examples/ComposableTableFavoritable.tsx +118 -0
  52. package/src/components/TableComposable/examples/ComposableTableHoverable.tsx +67 -0
  53. package/src/components/TableComposable/examples/ComposableTableMisc.tsx +92 -0
  54. package/src/components/TableComposable/examples/ComposableTableMultipleStickyColumns.tsx +153 -0
  55. package/src/components/TableComposable/examples/ComposableTableNestedExpandable.tsx +127 -0
  56. package/src/components/TableComposable/examples/ComposableTableNestedHeaders.tsx +202 -0
  57. package/src/components/TableComposable/examples/ComposableTableSelectable.tsx +125 -0
  58. package/src/components/TableComposable/examples/ComposableTableSelectableRadio.tsx +68 -0
  59. package/src/components/TableComposable/examples/ComposableTableSortable.tsx +107 -0
  60. package/src/components/TableComposable/examples/ComposableTableSortableCustom.tsx +175 -0
  61. package/src/components/TableComposable/examples/ComposableTableStickyColumn.tsx +144 -0
  62. package/src/components/TableComposable/examples/ComposableTableStickyColumnsAndHeader.tsx +167 -0
  63. package/src/components/TableComposable/examples/ComposableTableTextModifiers.tsx +33 -0
  64. package/src/components/TableComposable/examples/ComposableTableTree.tsx +201 -0
  65. package/src/demos/Table.md +7 -6
  66. package/src/components/Table/examples/DemoSortableTable.js +0 -65
  67. package/src/components/TableComposable/examples/DemoSortableTable.js +0 -65
@@ -0,0 +1,189 @@
1
+ import React from 'react';
2
+ import { TableProps, sortable, info, Table, TableBody, TableHeader } from '@patternfly/react-table';
3
+ import {
4
+ Toolbar,
5
+ ToolbarContent,
6
+ ToolbarItem,
7
+ OptionsMenu,
8
+ OptionsMenuItemGroup,
9
+ OptionsMenuItem,
10
+ OptionsMenuSeparator,
11
+ OptionsMenuToggle
12
+ } from '@patternfly/react-core';
13
+ import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
14
+
15
+ interface Repository {
16
+ name: string;
17
+ branches: string;
18
+ prs: string;
19
+ workspaces: string;
20
+ lastCommit: string;
21
+ }
22
+
23
+ export const LegacyTableSortableCustom: React.FunctionComponent = () => {
24
+ // In real usage, this data would come from some external source like an API via props.
25
+ const repositories: Repository[] = [
26
+ { name: 'one', branches: 'two', prs: 'a', workspaces: 'four', lastCommit: 'five' },
27
+ { name: 'a', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },
28
+ { name: 'p', branches: 'two', prs: 'b', workspaces: 'four', lastCommit: 'five' }
29
+ ];
30
+
31
+ const columnNames = {
32
+ name: 'Repositories',
33
+ branches: 'Branches',
34
+ prs: 'Pull requests',
35
+ workspaces: 'Workspaces',
36
+ lastCommit: 'Last commit'
37
+ };
38
+
39
+ // Index of the currently sorted column
40
+ // Note: if you intend to make columns reorderable, you may instead want to use a non-numeric key
41
+ // as the identifier of the sorted column. See the "Compound expandable" example.
42
+ const [activeSortIndex, setActiveSortIndex] = React.useState<number | null>(null);
43
+
44
+ // Sort direction of the currently sorted column
45
+ const [activeSortDirection, setActiveSortDirection] = React.useState<'asc' | 'desc' | null>(null);
46
+
47
+ // Sort dropdown expansion
48
+ const [isSortDropdownOpen, setIsSortDropdownOpen] = React.useState(false);
49
+
50
+ // Since OnSort specifies sorted columns by index, we need sortable values for our object by column index.
51
+ // This example is trivial since our data objects just contain strings, but if the data was more complex
52
+ // this would be a place to return simplified string or number versions of each column to sort by.
53
+ const getSortableRowValues = (repo: Repository): (string | number)[] => {
54
+ const { name, branches, prs, workspaces, lastCommit } = repo;
55
+ return [name, branches, prs, workspaces, lastCommit];
56
+ };
57
+
58
+ // Note that we perform the sort as part of the component's render logic and not in onSort.
59
+ // We shouldn't store the list of data in state because we don't want to have to sync that with props.
60
+ let sortedRepositories = repositories;
61
+ if (activeSortIndex !== null) {
62
+ sortedRepositories = repositories.sort((a, b) => {
63
+ const aValue = getSortableRowValues(a)[activeSortIndex];
64
+ const bValue = getSortableRowValues(b)[activeSortIndex];
65
+ if (typeof aValue === 'number') {
66
+ // Numeric sort
67
+ if (activeSortDirection === 'asc') {
68
+ return (aValue as number) - (bValue as number);
69
+ }
70
+ return (bValue as number) - (aValue as number);
71
+ } else {
72
+ // String sort
73
+ if (activeSortDirection === 'asc') {
74
+ return (aValue as string).localeCompare(bValue as string);
75
+ }
76
+ return (bValue as string).localeCompare(aValue as string);
77
+ }
78
+ });
79
+ }
80
+
81
+ const columns: TableProps['cells'] = [
82
+ { title: 'Repositories', transforms: [sortable] },
83
+ {
84
+ title: 'Branches',
85
+ transforms: [
86
+ info({
87
+ tooltip: 'More information about branches'
88
+ }),
89
+ sortable
90
+ ]
91
+ },
92
+ { title: 'Pull requests', transforms: [sortable] },
93
+ {
94
+ title: 'Workspaces',
95
+ transforms: [sortable]
96
+ },
97
+ {
98
+ title: 'Last commit',
99
+ transforms: [
100
+ info({
101
+ tooltip: 'More information about commits'
102
+ }),
103
+ sortable
104
+ ]
105
+ }
106
+ ];
107
+ const rows: TableProps['rows'] = sortedRepositories.map(repo => [
108
+ repo.name,
109
+ repo.branches,
110
+ repo.prs,
111
+ repo.workspaces,
112
+ repo.lastCommit
113
+ ]);
114
+
115
+ return (
116
+ <React.Fragment>
117
+ <Toolbar id="toolbar">
118
+ <ToolbarContent>
119
+ <ToolbarItem>
120
+ <OptionsMenu
121
+ id="options-menu-multiple-options-example"
122
+ menuItems={[
123
+ <OptionsMenuItemGroup key="first group" aria-label="Sort column">
124
+ {Object.values(columnNames).map((columnName, columnIndex) => (
125
+ <OptionsMenuItem
126
+ key={columnName}
127
+ isSelected={activeSortIndex === columnIndex}
128
+ onSelect={() => {
129
+ setActiveSortIndex(columnIndex);
130
+ setActiveSortDirection(activeSortDirection !== null ? activeSortDirection : 'asc');
131
+ }}
132
+ >
133
+ {columnName}
134
+ </OptionsMenuItem>
135
+ ))}
136
+ </OptionsMenuItemGroup>,
137
+ <OptionsMenuSeparator key="separator" />,
138
+ <OptionsMenuItemGroup key="second group" aria-label="Sort direction">
139
+ <OptionsMenuItem
140
+ onSelect={() => setActiveSortDirection('asc')}
141
+ isSelected={activeSortDirection === 'asc'}
142
+ id="ascending"
143
+ key="ascending"
144
+ >
145
+ Ascending
146
+ </OptionsMenuItem>
147
+ <OptionsMenuItem
148
+ onSelect={() => setActiveSortDirection('desc')}
149
+ isSelected={activeSortDirection === 'desc'}
150
+ id="descending"
151
+ key="descending"
152
+ >
153
+ Descending
154
+ </OptionsMenuItem>
155
+ </OptionsMenuItemGroup>
156
+ ]}
157
+ isOpen={isSortDropdownOpen}
158
+ toggle={
159
+ <OptionsMenuToggle
160
+ hideCaret
161
+ onToggle={() => setIsSortDropdownOpen(!isSortDropdownOpen)}
162
+ toggleTemplate={<SortAmountDownIcon />}
163
+ />
164
+ }
165
+ isPlain
166
+ isGrouped
167
+ />
168
+ </ToolbarItem>
169
+ </ToolbarContent>
170
+ </Toolbar>
171
+ <Table
172
+ aria-label="Sortable Table with Custom Toolbar"
173
+ sortBy={{
174
+ index: activeSortIndex,
175
+ direction: activeSortDirection
176
+ }}
177
+ onSort={(_event, index, direction) => {
178
+ setActiveSortIndex(index);
179
+ setActiveSortDirection(direction);
180
+ }}
181
+ cells={columns}
182
+ rows={rows}
183
+ >
184
+ <TableHeader />
185
+ <TableBody />
186
+ </Table>
187
+ </React.Fragment>
188
+ );
189
+ };
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { Table, TableHeader, TableBody, cellWidth, TableText, TableProps } from '@patternfly/react-table';
3
+
4
+ // This example has been simplified to focus on the text modifier props. In real usage,
5
+ // you may want to derive your rows from typed underlying data and minimal state. See other examples.
6
+
7
+ export const LegacyTableTextModifiers: React.FunctionComponent = () => {
8
+ const columns: TableProps['cells'] = [
9
+ { title: 'Truncating text', transforms: [cellWidth(30)] },
10
+ { title: 'Wrapping table header text. This th text will wrap instead of truncate.' }
11
+ ];
12
+ const rows: TableProps['rows'] = [
13
+ [
14
+ { title: <TableText wrapModifier="truncate">This text will truncate instead of wrap.</TableText> },
15
+ {
16
+ title: (
17
+ <TableText wrapModifier="nowrap">
18
+ <a href="#">This is a link that needs to be on one line and fully readable.</a>
19
+ </TableText>
20
+ )
21
+ }
22
+ ]
23
+ ];
24
+
25
+ return (
26
+ <Table aria-label="Table text with modifiers" cells={columns} rows={rows}>
27
+ <TableHeader />
28
+ <TableBody />
29
+ </Table>
30
+ );
31
+ };
@@ -0,0 +1,213 @@
1
+ import React from 'react';
2
+ import {
3
+ Table,
4
+ TableHeader,
5
+ TableBody,
6
+ treeRow,
7
+ IRow,
8
+ OnTreeRowCollapse,
9
+ OnCheckChange,
10
+ OnToggleRowDetails
11
+ } from '@patternfly/react-table';
12
+ import LeafIcon from '@patternfly/react-icons/dist/esm/icons/leaf-icon';
13
+ import FolderIcon from '@patternfly/react-icons/dist/esm/icons/folder-icon';
14
+ import FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-icon';
15
+
16
+ interface RepositoriesTreeNode {
17
+ name: string;
18
+ branches: string;
19
+ pullRequests: string;
20
+ workspaces: string;
21
+ children?: RepositoriesTreeNode[];
22
+ }
23
+
24
+ export const LegacyTableTree: React.FunctionComponent = () => {
25
+ // In real usage, this data would come from some external source like an API via props.
26
+ const data: RepositoriesTreeNode[] = [
27
+ {
28
+ name: 'Repositories one',
29
+ branches: 'Branch one',
30
+ pullRequests: 'Pull request one',
31
+ workspaces: 'Workplace one',
32
+ children: [
33
+ {
34
+ name: 'Repositories two',
35
+ branches: 'Branch two',
36
+ pullRequests: 'Pull request two',
37
+ workspaces: 'Workplace two',
38
+ children: [
39
+ {
40
+ name: 'Repositories three',
41
+ branches: 'Branch three',
42
+ pullRequests: 'Pull request three',
43
+ workspaces: 'Workplace three'
44
+ },
45
+ {
46
+ name: 'Repositories four',
47
+ branches: 'Branch four',
48
+ pullRequests: 'Pull request four',
49
+ workspaces: 'Workplace four'
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ name: 'Repositories five',
55
+ branches: 'Branch five',
56
+ pullRequests: 'Pull request five',
57
+ workspaces: 'Workplace five'
58
+ },
59
+ {
60
+ name: 'Repositories six',
61
+ branches: 'Branch six',
62
+ pullRequests: 'Pull request six',
63
+ workspaces: 'Workplace six'
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ name: 'Repositories seven',
69
+ branches: 'Branch seven',
70
+ pullRequests: 'Pull request seven',
71
+ workspaces: 'Workplace seven',
72
+ children: [
73
+ {
74
+ name: 'Repositories eight',
75
+ branches: 'Branch eight',
76
+ pullRequests: 'Pull request eight',
77
+ workspaces: 'Workplace eight'
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ name: 'Repositories nine',
83
+ branches: 'Branch nine',
84
+ pullRequests: 'Pull request nine',
85
+ workspaces: 'Workplace nine'
86
+ }
87
+ ];
88
+
89
+ const [expandedNodeNames, setExpandedNodeNames] = React.useState<string[]>(['Repositories one']);
90
+ const [expandedDetailsNodeNames, setExpandedDetailsNodeNames] = React.useState<string[]>([]);
91
+ const [selectedNodeNames, setSelectedNodeNames] = React.useState<string[]>([]);
92
+
93
+ const getDescendants = (node: RepositoriesTreeNode): RepositoriesTreeNode[] =>
94
+ [node].concat(...(node.children ? node.children.map(getDescendants) : []));
95
+ const areAllDescendantsSelected = (node: RepositoriesTreeNode) =>
96
+ getDescendants(node).every(n => selectedNodeNames.includes(n.name));
97
+ const areSomeDescendantsSelected = (node: RepositoriesTreeNode) =>
98
+ getDescendants(node).some(n => selectedNodeNames.includes(n.name));
99
+
100
+ const isNodeChecked = (node: RepositoriesTreeNode) => {
101
+ if (areAllDescendantsSelected(node)) {
102
+ return true;
103
+ }
104
+ if (areSomeDescendantsSelected(node)) {
105
+ return null;
106
+ }
107
+ return false;
108
+ };
109
+
110
+ // We index the tree nodes in the order of the table rows, for looking up by rowIndex
111
+ const flattenedNodes: RepositoriesTreeNode[] = [];
112
+
113
+ /**
114
+ Recursive function which flattens the data into an array of flattened IRow objects
115
+ params:
116
+ - nodes - array of a single level of tree nodes
117
+ - level - number representing how deeply nested the current row is
118
+ - posinset - position of the row relative to this row's siblings
119
+ - isHidden - defaults to false, true if this row's parent is expanded
120
+ - currentRowIndex - position of the row relative to the entire table
121
+ */
122
+ const buildRows = (
123
+ [node, ...remainingNodes]: RepositoriesTreeNode[],
124
+ level = 1,
125
+ posinset = 1,
126
+ rowIndex = 0,
127
+ isHidden = false
128
+ ): IRow[] => {
129
+ if (!node) {
130
+ return [];
131
+ }
132
+ const isExpanded = expandedNodeNames.includes(node.name);
133
+ const isDetailsExpanded = expandedDetailsNodeNames.includes(node.name);
134
+ const isChecked = isNodeChecked(node);
135
+ let icon = <LeafIcon />;
136
+ if (node.children) {
137
+ icon = isExpanded ? <FolderOpenIcon aria-hidden /> : <FolderIcon aria-hidden />;
138
+ }
139
+ flattenedNodes.push(node);
140
+ return [
141
+ {
142
+ cells: [node.name, node.branches, node.pullRequests, node.workspaces],
143
+ props: {
144
+ isExpanded,
145
+ isDetailsExpanded,
146
+ isHidden,
147
+ 'aria-level': level,
148
+ 'aria-posinset': posinset,
149
+ 'aria-setsize': node.children ? node.children.length : 0,
150
+ isChecked,
151
+ icon
152
+ }
153
+ },
154
+ ...(node.children && node.children.length
155
+ ? buildRows(node.children, level + 1, 1, rowIndex + 1, !isExpanded || isHidden)
156
+ : []),
157
+ ...buildRows(
158
+ remainingNodes,
159
+ level,
160
+ posinset + 1,
161
+ rowIndex + 1 + ((node.children && node.children.length) || 0),
162
+ isHidden
163
+ )
164
+ ];
165
+ };
166
+
167
+ const onCollapse: OnTreeRowCollapse = (_event, rowIndex) => {
168
+ const node = flattenedNodes[rowIndex];
169
+ const isExpanded = expandedNodeNames.includes(node.name);
170
+ setExpandedNodeNames(prevExpanded => {
171
+ const otherExpandedNodeNames = prevExpanded.filter(name => name !== node.name);
172
+ return isExpanded ? otherExpandedNodeNames : [...otherExpandedNodeNames, node.name];
173
+ });
174
+ };
175
+
176
+ const onCheck: OnCheckChange = (_event, isChecking, rowIndex) => {
177
+ const node = flattenedNodes[rowIndex];
178
+ const nodeNamesToCheck = getDescendants(node).map(n => n.name);
179
+ setSelectedNodeNames(prevSelected => {
180
+ const otherSelectedNodeNames = prevSelected.filter(name => !nodeNamesToCheck.includes(name));
181
+ return !isChecking ? otherSelectedNodeNames : [...otherSelectedNodeNames, ...nodeNamesToCheck];
182
+ });
183
+ };
184
+
185
+ const onToggleRowDetails: OnToggleRowDetails = (_event, rowIndex) => {
186
+ const node = flattenedNodes[rowIndex];
187
+ const isDetailsExpanded = expandedDetailsNodeNames.includes(node.name);
188
+ setExpandedDetailsNodeNames(prevDetailsExpanded => {
189
+ const otherDetailsExpandedNodeNames = prevDetailsExpanded.filter(name => name !== node.name);
190
+ return isDetailsExpanded ? otherDetailsExpandedNodeNames : [...otherDetailsExpandedNodeNames, node.name];
191
+ });
192
+ };
193
+
194
+ return (
195
+ <Table
196
+ isTreeTable
197
+ aria-label="Tree table"
198
+ cells={[
199
+ {
200
+ title: 'Repositories',
201
+ cellTransforms: [treeRow(onCollapse, onCheck, onToggleRowDetails)]
202
+ },
203
+ 'Branches',
204
+ 'Pull requests',
205
+ 'Workspaces'
206
+ ]}
207
+ rows={buildRows(data)}
208
+ >
209
+ <TableHeader />
210
+ <TableBody />
211
+ </Table>
212
+ );
213
+ };