@patternfly/react-table 4.44.12 → 4.44.16

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 (70) hide show
  1. package/CHANGELOG.md +35 -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/dist/umd/react-table.css +250 -250
  23. package/dist/umd/react-table.js +9 -1
  24. package/dist/umd/react-table.min.js +3 -3
  25. package/package.json +6 -6
  26. package/src/components/Table/Table.tsx +2 -1
  27. package/src/components/Table/TableTypes.tsx +2 -1
  28. package/src/components/Table/examples/LegacyTableActions.tsx +218 -0
  29. package/src/components/Table/examples/LegacyTableBasic.tsx +90 -0
  30. package/src/components/Table/examples/LegacyTableCellWidth.tsx +66 -0
  31. package/src/components/Table/examples/LegacyTableCompoundExpandable.tsx +175 -0
  32. package/src/components/Table/examples/LegacyTableControllingText.tsx +51 -0
  33. package/src/components/Table/examples/LegacyTableEmptyState.tsx +48 -0
  34. package/src/components/Table/examples/LegacyTableExpandable.tsx +172 -0
  35. package/src/components/Table/examples/LegacyTableFavoritable.tsx +157 -0
  36. package/src/components/Table/examples/LegacyTableHoverable.tsx +125 -0
  37. package/src/components/Table/examples/LegacyTableMisc.tsx +56 -0
  38. package/src/components/Table/examples/LegacyTableSelectable.tsx +124 -0
  39. package/src/components/Table/examples/LegacyTableSelectableRadio.tsx +54 -0
  40. package/src/components/Table/examples/LegacyTableSortable.tsx +120 -0
  41. package/src/components/Table/examples/LegacyTableSortableCustom.tsx +189 -0
  42. package/src/components/Table/examples/LegacyTableTextModifiers.tsx +31 -0
  43. package/src/components/Table/examples/LegacyTableTree.tsx +213 -0
  44. package/src/components/Table/examples/Table.md +83 -1848
  45. package/src/components/TableComposable/examples/ComposableTable.md +31 -2805
  46. package/src/components/TableComposable/examples/ComposableTableActions.tsx +163 -0
  47. package/src/components/TableComposable/examples/ComposableTableBasic.tsx +89 -0
  48. package/src/components/TableComposable/examples/ComposableTableCellWidth.tsx +56 -0
  49. package/src/components/TableComposable/examples/ComposableTableCompoundExpandable.tsx +103 -0
  50. package/src/components/TableComposable/examples/ComposableTableControllingText.tsx +51 -0
  51. package/src/components/TableComposable/examples/ComposableTableDraggable.tsx +170 -0
  52. package/src/components/TableComposable/examples/ComposableTableEmptyState.tsx +45 -0
  53. package/src/components/TableComposable/examples/ComposableTableExpandable.tsx +195 -0
  54. package/src/components/TableComposable/examples/ComposableTableFavoritable.tsx +118 -0
  55. package/src/components/TableComposable/examples/ComposableTableHoverable.tsx +67 -0
  56. package/src/components/TableComposable/examples/ComposableTableMisc.tsx +92 -0
  57. package/src/components/TableComposable/examples/ComposableTableMultipleStickyColumns.tsx +153 -0
  58. package/src/components/TableComposable/examples/ComposableTableNestedExpandable.tsx +127 -0
  59. package/src/components/TableComposable/examples/ComposableTableNestedHeaders.tsx +202 -0
  60. package/src/components/TableComposable/examples/ComposableTableSelectable.tsx +125 -0
  61. package/src/components/TableComposable/examples/ComposableTableSelectableRadio.tsx +68 -0
  62. package/src/components/TableComposable/examples/ComposableTableSortable.tsx +107 -0
  63. package/src/components/TableComposable/examples/ComposableTableSortableCustom.tsx +175 -0
  64. package/src/components/TableComposable/examples/ComposableTableStickyColumn.tsx +144 -0
  65. package/src/components/TableComposable/examples/ComposableTableStickyColumnsAndHeader.tsx +167 -0
  66. package/src/components/TableComposable/examples/ComposableTableTextModifiers.tsx +33 -0
  67. package/src/components/TableComposable/examples/ComposableTableTree.tsx +201 -0
  68. package/src/demos/Table.md +7 -6
  69. package/src/components/Table/examples/DemoSortableTable.js +0 -65
  70. package/src/components/TableComposable/examples/DemoSortableTable.js +0 -65
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-table",
3
- "version": "4.44.12",
3
+ "version": "4.44.16",
4
4
  "description": "This library provides a set of React table components for use with the PatternFly 4",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -31,10 +31,10 @@
31
31
  "clean": "rimraf dist"
32
32
  },
33
33
  "dependencies": {
34
- "@patternfly/react-core": "^4.175.12",
35
- "@patternfly/react-icons": "^4.26.12",
36
- "@patternfly/react-styles": "^4.25.12",
37
- "@patternfly/react-tokens": "^4.27.12",
34
+ "@patternfly/react-core": "^4.175.16",
35
+ "@patternfly/react-icons": "^4.26.16",
36
+ "@patternfly/react-styles": "^4.25.16",
37
+ "@patternfly/react-tokens": "^4.27.16",
38
38
  "lodash": "^4.17.19",
39
39
  "tslib": "^2.0.0"
40
40
  },
@@ -46,5 +46,5 @@
46
46
  "react": "^16.8.0 || ^17.0.0",
47
47
  "react-dom": "^16.8.0 || ^17.0.0"
48
48
  },
49
- "gitHead": "c31cf1714bb3cbb692b22861c6c8204d59243d83"
49
+ "gitHead": "0fd305f905deef067794578e91429e8fcf85515c"
50
50
  }
@@ -32,6 +32,7 @@ import {
32
32
  OnFavorite
33
33
  } from './TableTypes';
34
34
  import { TreeRowWrapper } from './TreeRowWrapper';
35
+ import { CustomActionsToggleProps } from './ActionsColumn';
35
36
 
36
37
  export interface TableProps extends OUIAProps {
37
38
  /** Adds an accessible name for the Table */
@@ -89,7 +90,7 @@ export interface TableProps extends OUIAProps {
89
90
  /** The desired direction to show the dropdown when clicking on the actions Kebab. Can only be used together with `actions` property */
90
91
  dropdownDirection?: 'up' | 'down';
91
92
  /** The toggle of the actions menu dropdown. A KebabToggle or DropdownToggle component */
92
- actionsToggle?: React.ReactElement;
93
+ actionsToggle?: (props: CustomActionsToggleProps) => React.ReactNode;
93
94
  /** Row data */
94
95
  rows: (IRow | string[])[];
95
96
  /** Cell/column data */
@@ -7,6 +7,7 @@ import {
7
7
  } from '@patternfly/react-core/dist/esm/components/Dropdown/dropdownConstants';
8
8
  import * as React from 'react';
9
9
  import { CustomActionsToggleProps } from './ActionsColumn';
10
+ import { ButtonProps } from '@patternfly/react-core';
10
11
 
11
12
  export enum TableGridBreakpoint {
12
13
  none = '',
@@ -145,7 +146,7 @@ export interface ISortBy {
145
146
  defaultDirection?: 'asc' | 'desc';
146
147
  }
147
148
 
148
- export interface IAction extends Omit<DropdownItemProps, 'title' | 'onClick'> {
149
+ export interface IAction extends Omit<DropdownItemProps, 'title' | 'onClick'>, Pick<ButtonProps, 'variant'> {
149
150
  /** Flag indicating an item on actions menu is a separator, rather than an action */
150
151
  isSeparator?: boolean;
151
152
  /** Key of actions menu item */
@@ -0,0 +1,218 @@
1
+ /* eslint-disable no-console */
2
+ import React from 'react';
3
+ import {
4
+ ButtonVariant,
5
+ Checkbox,
6
+ DropdownToggle,
7
+ ToggleGroup,
8
+ ToggleGroupItem,
9
+ ToggleGroupItemProps,
10
+ Toolbar,
11
+ ToolbarContent,
12
+ ToolbarItem
13
+ } from '@patternfly/react-core';
14
+ import {
15
+ CustomActionsToggleProps,
16
+ headerCol,
17
+ TableProps,
18
+ IAction,
19
+ IActions,
20
+ IActionsResolver,
21
+ Table,
22
+ TableBody,
23
+ TableHeader
24
+ } from '@patternfly/react-table';
25
+
26
+ interface Repository {
27
+ name: string;
28
+ branches: string;
29
+ prs: string;
30
+ workspaces: string;
31
+ lastCommit: string;
32
+ }
33
+
34
+ type ExampleType = 'actions' | 'actionResolver';
35
+
36
+ export const LegacyTableActions: React.FunctionComponent = () => {
37
+ // In real usage, this data would come from some external source like an API via props.
38
+ const repositories: Repository[] = [
39
+ { name: 'a', branches: 'two', prs: '1', workspaces: 'four', lastCommit: 'five' },
40
+ { name: 'disable actions', branches: 'two', prs: '3', workspaces: 'four', lastCommit: 'five' },
41
+ { name: 'green actions', branches: 'two', prs: '4', workspaces: 'four', lastCommit: 'five' },
42
+ { name: 'extra action props', branches: 'two', prs: '5', workspaces: 'four', lastCommit: 'five' },
43
+ { name: 'blue actions', branches: 'two', prs: '6', workspaces: 'four', lastCommit: 'five' }
44
+ ];
45
+
46
+ // This state is just for the ToggleGroup in this example and isn't necessary for Table usage.
47
+ const [propToUse, setPropToUse] = React.useState<ExampleType>('actions');
48
+ const onPropToUseChange: ToggleGroupItemProps['onChange'] = (_isSelected, event) => {
49
+ const id = event.currentTarget.id;
50
+ setPropToUse(id as ExampleType);
51
+ };
52
+
53
+ const [useCustomToggle, setUseCustomToggle] = React.useState(false);
54
+ const [useExtraAction, setUseExtraAction] = React.useState(false);
55
+
56
+ const customActionsToggle = (props: CustomActionsToggleProps) => (
57
+ <DropdownToggle onToggle={props.onToggle} isDisabled={props.isDisabled}>
58
+ Actions
59
+ </DropdownToggle>
60
+ );
61
+
62
+ const columns: TableProps['cells'] = [
63
+ { title: 'Repositories', cellTransforms: [headerCol()] },
64
+ 'Branches',
65
+ 'Pull requests',
66
+ 'Workspaces',
67
+ 'Last commit'
68
+ ];
69
+ const rows: TableProps['rows'] = repositories.map(repo => {
70
+ const cells = [repo.name, repo.branches, repo.prs, repo.workspaces, repo.lastCommit];
71
+ // These rows have arbitrary differences for this example, but these could be based on some other conditions
72
+ if (repo.name === 'disable actions') {
73
+ return { cells, disableActions: true };
74
+ }
75
+ if (repo.name === 'green actions') {
76
+ return { cells, type: 'green' };
77
+ }
78
+ if (repo.name === 'extra action props') {
79
+ return { cells, actionProps: { 'data-specific-attr': 'some-value' } };
80
+ }
81
+ if (repo.name === 'blue actions') {
82
+ return { cells, type: 'blue' };
83
+ }
84
+ return { cells };
85
+ });
86
+
87
+ /**
88
+ * Use actions or actionResolver, not both
89
+ */
90
+ const extraAction: IAction = {
91
+ title: 'Start',
92
+ variant: ButtonVariant.secondary,
93
+ onClick: (_event, rowId, rowData, extra) => console.log('clicked on extra action on row: ', rowId, rowData, extra),
94
+ isOutsideDropdown: true
95
+ };
96
+ const actions: IActions = [
97
+ {
98
+ title: 'Some action',
99
+ onClick: (_event, rowId, rowData, extra) => console.log('clicked on Some action, on row: ', rowId, rowData, extra)
100
+ },
101
+ {
102
+ title: <a href="#">Link action</a>
103
+ },
104
+ {
105
+ isSeparator: true
106
+ },
107
+ {
108
+ title: 'Third action',
109
+ onClick: (_event, rowId, rowData, extra) =>
110
+ console.log('clicked on Third action, on row: ', rowId, rowData, extra)
111
+ },
112
+ ...(useExtraAction ? [extraAction] : [])
113
+ ];
114
+
115
+ /**
116
+ * Use actions or actionResolver, not both
117
+ */
118
+ const actionResolver: IActionsResolver = (rowData, { rowIndex }) => {
119
+ if (rowIndex === 1) {
120
+ return [];
121
+ }
122
+
123
+ const extraAction: IActions = [
124
+ {
125
+ title: 'Start',
126
+ variant: ButtonVariant.secondary,
127
+ onClick: (_event, rowId, rowData, extra) =>
128
+ console.log('clicked on extra action on row: ', rowId, rowData, extra),
129
+ isOutsideDropdown: true
130
+ }
131
+ ];
132
+
133
+ const thirdAction: IActions = [
134
+ {
135
+ isSeparator: true
136
+ },
137
+ {
138
+ title: `${rowData.type} action`,
139
+ onClick: (_event, rowId, rowData, extra) =>
140
+ console.log(`clicked on ${rowData.type} action, on row ${rowId} of type ${rowData.type}`, extra)
141
+ }
142
+ ];
143
+
144
+ return [
145
+ ...(useExtraAction ? extraAction : []),
146
+ {
147
+ title: 'actionResolver action',
148
+ onClick: (_event, rowId, rowData, extra) =>
149
+ console.log(`clicked on Some action, on row ${rowId} of type ${rowData.type}`, extra)
150
+ },
151
+ {
152
+ title: <div>Another action</div>,
153
+ onClick: (_event, rowId, rowData, extra) =>
154
+ console.log(`clicked on Another action, on row ${rowId} of type ${rowData.type}`, extra)
155
+ },
156
+ ...(rowData.type ? thirdAction : [])
157
+ ];
158
+ };
159
+
160
+ return (
161
+ <React.Fragment>
162
+ <Toolbar>
163
+ <ToolbarContent>
164
+ <ToolbarItem>
165
+ <ToggleGroup aria-label="actions or actionResolver">
166
+ <ToggleGroupItem
167
+ text="Use actions prop"
168
+ buttonId="actions"
169
+ isSelected={propToUse === 'actions'}
170
+ onChange={onPropToUseChange}
171
+ />
172
+ <ToggleGroupItem
173
+ text="Use actionResolver prop"
174
+ buttonId="actionResolver"
175
+ isSelected={propToUse === 'actionResolver'}
176
+ onChange={onPropToUseChange}
177
+ />
178
+ </ToggleGroup>
179
+ </ToolbarItem>
180
+ <ToolbarItem>
181
+ <Checkbox
182
+ label="Use custom actions toggle"
183
+ isChecked={useCustomToggle}
184
+ onChange={setUseCustomToggle}
185
+ aria-label="toggle use of custom actions toggle"
186
+ id="toggle-custom-actions-toggle"
187
+ name="toggle-custom-actions-toggle"
188
+ />
189
+ </ToolbarItem>
190
+ <ToolbarItem>
191
+ <Checkbox
192
+ label="Add extra actions"
193
+ isChecked={useExtraAction}
194
+ onChange={setUseExtraAction}
195
+ aria-label="toggle extra actions"
196
+ id="toggle-extra-action"
197
+ name="toggle-extra-action"
198
+ />
199
+ </ToolbarItem>
200
+ </ToolbarContent>
201
+ </Toolbar>
202
+ <Table
203
+ aria-label="Actions table"
204
+ cells={columns}
205
+ rows={rows}
206
+ {...(propToUse === 'actions' && { actions })}
207
+ {...(propToUse === 'actionResolver' && { actionResolver })}
208
+ areActionsDisabled={rowData => !!rowData.disableActions}
209
+ dropdownPosition="left"
210
+ dropdownDirection="down"
211
+ actionsToggle={useCustomToggle ? customActionsToggle : undefined}
212
+ >
213
+ <TableHeader />
214
+ <TableBody />
215
+ </Table>
216
+ </React.Fragment>
217
+ );
218
+ };
@@ -0,0 +1,90 @@
1
+ import React from 'react';
2
+ import { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table';
3
+ import { ToggleGroup, ToggleGroupItem, ToggleGroupItemProps } from '@patternfly/react-core';
4
+ interface Repository {
5
+ name: string;
6
+ branches: string;
7
+ prs: string;
8
+ workspaces: string;
9
+ lastCommit: string;
10
+ }
11
+
12
+ type ExampleType = 'default' | 'compact' | 'compactBorderless';
13
+
14
+ export const LegacyTableBasic: React.FunctionComponent = () => {
15
+ // In real usage, this data would come from some external source like an API via props.
16
+ const repositories: Repository[] = [
17
+ {
18
+ name: 'Repository one',
19
+ branches: 'Branch one',
20
+ prs: 'PR one',
21
+ workspaces: 'Workspace one',
22
+ lastCommit: 'Commit one'
23
+ },
24
+ {
25
+ name: 'Repository two',
26
+ branches: 'Branch two',
27
+ prs: 'PR two',
28
+ workspaces: 'Workspace two',
29
+ lastCommit: 'Commit two'
30
+ },
31
+ {
32
+ name: 'Repository three',
33
+ branches: 'Branch three',
34
+ prs: 'PR three',
35
+ workspaces: 'Workspace three',
36
+ lastCommit: 'Commit three'
37
+ }
38
+ ];
39
+
40
+ // This state is just for the ToggleGroup in this example and isn't necessary for TableComposable usage.
41
+ const [exampleChoice, setExampleChoice] = React.useState<ExampleType>('default');
42
+ const onExampleTypeChange: ToggleGroupItemProps['onChange'] = (_isSelected, event) => {
43
+ const id = event.currentTarget.id;
44
+ setExampleChoice(id as ExampleType);
45
+ };
46
+
47
+ const columns: TableProps['cells'] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];
48
+ const rows: TableProps['rows'] = repositories.map(repo => [
49
+ repo.name,
50
+ repo.branches,
51
+ repo.prs,
52
+ repo.workspaces,
53
+ repo.lastCommit
54
+ ]);
55
+
56
+ return (
57
+ <React.Fragment>
58
+ <ToggleGroup aria-label="Default with single selectable">
59
+ <ToggleGroupItem
60
+ text="Default"
61
+ buttonId="default"
62
+ isSelected={exampleChoice === 'default'}
63
+ onChange={onExampleTypeChange}
64
+ />
65
+ <ToggleGroupItem
66
+ text="Compact"
67
+ buttonId="compact"
68
+ isSelected={exampleChoice === 'compact'}
69
+ onChange={onExampleTypeChange}
70
+ />
71
+ <ToggleGroupItem
72
+ text="Compact borderless"
73
+ buttonId="compactBorderless"
74
+ isSelected={exampleChoice === 'compactBorderless'}
75
+ onChange={onExampleTypeChange}
76
+ />
77
+ </ToggleGroup>
78
+ <Table
79
+ aria-label="Simple Table"
80
+ variant={exampleChoice !== 'default' ? 'compact' : undefined}
81
+ borders={exampleChoice !== 'compactBorderless'}
82
+ cells={columns}
83
+ rows={rows}
84
+ >
85
+ <TableHeader />
86
+ <TableBody />
87
+ </Table>
88
+ </React.Fragment>
89
+ );
90
+ };
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { Table, TableHeader, TableBody, classNames, cellWidth, Visibility, TableProps } from '@patternfly/react-table';
3
+
4
+ interface Repository {
5
+ name: string;
6
+ branches: string;
7
+ prs: string;
8
+ workspaces: string;
9
+ lastCommit: string;
10
+ }
11
+
12
+ export const LegacyTableCellWidth: React.FunctionComponent = () => {
13
+ // In real usage, this data would come from some external source like an API via props.
14
+ const repositories: Repository[] = [
15
+ {
16
+ name: 'one - 1',
17
+ branches: 'two - 1 (visible only on md)',
18
+ prs: 'three - 1 (hidden only on md)',
19
+ workspaces: 'four - 1 (hidden on xs)',
20
+ lastCommit: 'five - 1'
21
+ },
22
+ {
23
+ name: 'one - 2',
24
+ branches: 'two - 2 (visible only on md)',
25
+ prs: 'three - 2 (hidden only on md)',
26
+ workspaces: 'four - 2 (hidden on xs)',
27
+ lastCommit: 'five - 2'
28
+ }
29
+ ];
30
+
31
+ const columns: TableProps['cells'] = [
32
+ { title: 'Header cell', transforms: [cellWidth(10)] },
33
+ {
34
+ title: 'Branches (visible only on md and 2Xl)',
35
+ columnTransforms: [
36
+ classNames(Visibility.hidden, Visibility.visibleOnMd, Visibility.hiddenOnLg, Visibility.visibleOn2Xl)
37
+ ]
38
+ },
39
+ {
40
+ title: 'Pull requests (hidden only on md)',
41
+ columnTransforms: [classNames(Visibility.hiddenOnMd, Visibility.visibleOnLg)]
42
+ },
43
+ {
44
+ title: 'Workspaces (hidden on xs)',
45
+ columnTransforms: [classNames(Visibility.hidden, Visibility.visibleOnSm)]
46
+ },
47
+ {
48
+ title: 'Last commit',
49
+ transforms: [cellWidth(30)]
50
+ }
51
+ ];
52
+ const rows: TableProps['rows'] = repositories.map(repo => [
53
+ repo.name,
54
+ repo.branches,
55
+ repo.prs,
56
+ repo.workspaces,
57
+ repo.lastCommit
58
+ ]);
59
+
60
+ return (
61
+ <Table aria-label="Table with width and breakpoint visibility modifiers" cells={columns} rows={rows}>
62
+ <TableHeader />
63
+ <TableBody />
64
+ </Table>
65
+ );
66
+ };
@@ -0,0 +1,175 @@
1
+ import React from 'react';
2
+ import { Table, TableHeader, TableBody, compoundExpand, TableProps } from '@patternfly/react-table';
3
+
4
+ import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
5
+ import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon';
6
+ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
7
+
8
+ interface Repository {
9
+ name: string;
10
+ branches: number;
11
+ prs: number;
12
+ workspaces: number;
13
+ lastCommit: string;
14
+ }
15
+
16
+ export const LegacyTableCompoundExpandable: React.FunctionComponent = () => {
17
+ // In real usage, this data would come from some external source like an API via props.
18
+ const repositories: Repository[] = [
19
+ { name: 'siemur/test-space', branches: 10, prs: 4, workspaces: 4, lastCommit: '20 minutes' },
20
+ { name: 'siemur/test-space-2', branches: 3, prs: 4, workspaces: 4, lastCommit: '20 minutes' }
21
+ ];
22
+
23
+ // In this example, expanded cells are tracked by the repo and property names from each row. This could be any pair of unique identifiers.
24
+ // This is to prevent state from being based on row and column order index in case we later add sorting and rearranging columns.
25
+ // Note that these columnKeys must be in the same order as the `columns` below, because columnIndex will be used to look up the matching key.
26
+ type ColumnKey = 'name' | 'branches' | 'prs' | 'workspaces' | 'lastCommit'; // For typechecking
27
+ const columnKeys: ColumnKey[] = ['name', 'branches', 'prs', 'workspaces', 'lastCommit']; // For indexed order
28
+ const [expandedCells, setExpandedCells] = React.useState<Record<string, ColumnKey>>({
29
+ 'siemur/test-space': 'branches' // Default to the first cell of the first row being expanded
30
+ });
31
+ const setCellExpanded = (repo: Repository, columnKey: ColumnKey, isExpanding = true) => {
32
+ const newExpandedCells = { ...expandedCells };
33
+ if (isExpanding) {
34
+ newExpandedCells[repo.name] = columnKey;
35
+ } else {
36
+ delete newExpandedCells[repo.name];
37
+ }
38
+ setExpandedCells(newExpandedCells);
39
+ };
40
+
41
+ // We want to be able to reference the original data object based on row index. But because parent/child rows are
42
+ // multiple elements in the rows array, repositories[rowIndex] will not be accurate like it would in a normal table.
43
+ // One solution to this is to create an array of data objects indexed by the displayed row index.
44
+ const reposByRowIndex: (Repository | null)[] = [];
45
+
46
+ const columns: TableProps['cells'] = [
47
+ 'Repositories',
48
+ {
49
+ title: 'Branches',
50
+ cellTransforms: [compoundExpand]
51
+ },
52
+ {
53
+ title: 'Pull requests',
54
+ cellTransforms: [compoundExpand]
55
+ },
56
+ {
57
+ title: 'Workspaces',
58
+ cellTransforms: [compoundExpand]
59
+ },
60
+ 'Last Commit',
61
+ {
62
+ title: '',
63
+ dataLabel: 'Action'
64
+ }
65
+ ];
66
+ const rows: TableProps['rows'] = [];
67
+ repositories.forEach(repo => {
68
+ const expandedCellKey = expandedCells[repo.name];
69
+ const isRowExpanded = !!expandedCellKey;
70
+ rows.push({
71
+ isOpen: isRowExpanded,
72
+ cells: [
73
+ { title: <a href="#">{repo.name}</a>, props: { component: 'th' } },
74
+ {
75
+ title: (
76
+ <React.Fragment>
77
+ <CodeBranchIcon key="icon" /> {repo.branches}
78
+ </React.Fragment>
79
+ ),
80
+ props: {
81
+ isOpen: expandedCellKey === 'branches',
82
+ ariaControls: `compound-expansion-table-${repo.name}-1`
83
+ }
84
+ },
85
+ {
86
+ title: (
87
+ <React.Fragment>
88
+ <CodeIcon key="icon" /> {repo.prs}
89
+ </React.Fragment>
90
+ ),
91
+ props: {
92
+ isOpen: expandedCellKey === 'prs',
93
+ ariaControls: `compound-expansion-table-${repo.name}-2`
94
+ }
95
+ },
96
+ {
97
+ title: (
98
+ <React.Fragment>
99
+ <CubeIcon key="icon" /> {repo.branches}
100
+ </React.Fragment>
101
+ ),
102
+ props: {
103
+ isOpen: expandedCellKey === 'workspaces',
104
+ ariaControls: `compound-expansion-table-${repo.name}-3`
105
+ }
106
+ },
107
+ repo.lastCommit,
108
+ { title: <a href="#">Open in Github</a> }
109
+ ]
110
+ });
111
+ reposByRowIndex.push(repo);
112
+ const parentIndex = rows.length - 1;
113
+ rows.push({
114
+ parent: parentIndex,
115
+ compoundParent: 1,
116
+ cells: [
117
+ {
118
+ title: (
119
+ <div className="pf-u-m-md" id={`compound-expansion-table-${repo.name}-1`}>
120
+ Expanded content for {repo.name}: Branches goes here!
121
+ </div>
122
+ ),
123
+ props: { colSpan: 6, className: 'pf-m-no-padding' }
124
+ }
125
+ ]
126
+ });
127
+ reposByRowIndex.push(null);
128
+ rows.push({
129
+ parent: parentIndex,
130
+ compoundParent: 2,
131
+ cells: [
132
+ {
133
+ title: (
134
+ <div className="pf-u-m-md" id={`compound-expansion-table-${repo.name}-2`}>
135
+ Expanded content for {repo.name}: Pull requests goes here!
136
+ </div>
137
+ ),
138
+ props: { colSpan: 6, className: 'pf-m-no-padding' }
139
+ }
140
+ ]
141
+ });
142
+ reposByRowIndex.push(null);
143
+ rows.push({
144
+ parent: parentIndex,
145
+ compoundParent: 3,
146
+ cells: [
147
+ {
148
+ title: (
149
+ <div className="pf-u-m-md" id={`compound-expansion-table-${repo.name}-3`}>
150
+ Expanded content for {repo.name}: Workspaces goes here!
151
+ </div>
152
+ ),
153
+ props: { colSpan: 6, className: 'pf-m-no-padding' }
154
+ }
155
+ ]
156
+ });
157
+ reposByRowIndex.push(null);
158
+ });
159
+
160
+ return (
161
+ <Table
162
+ aria-label="Compound expandable table"
163
+ onExpand={(_event, rowIndex, colIndex, isOpen) => {
164
+ if (reposByRowIndex[rowIndex]) {
165
+ setCellExpanded(reposByRowIndex[rowIndex], columnKeys[colIndex], !isOpen);
166
+ }
167
+ }}
168
+ rows={rows}
169
+ cells={columns}
170
+ >
171
+ <TableHeader />
172
+ <TableBody />
173
+ </Table>
174
+ );
175
+ };
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import {
3
+ Table,
4
+ TableHeader,
5
+ TableBody,
6
+ cellWidth,
7
+ truncate,
8
+ breakWord,
9
+ wrappable,
10
+ fitContent,
11
+ nowrap,
12
+ TableProps
13
+ } from '@patternfly/react-table';
14
+
15
+ // This example has been simplified to focus on the text modifier props. In real usage,
16
+ // you may want to derive your rows from typed underlying data and minimal state. See other examples.
17
+
18
+ export const LegacyTableControllingText: React.FunctionComponent = () => {
19
+ const columns: TableProps['cells'] = [
20
+ { title: 'Truncate (width 20%)', transforms: [cellWidth(20)], cellTransforms: [truncate] },
21
+ { title: 'Break word', cellTransforms: [breakWord] },
22
+ { title: 'Wrapping table header text. This th text will wrap instead of truncate.', transforms: [wrappable] },
23
+ { title: 'Fit content', transforms: [fitContent] },
24
+ { title: '', cellTransforms: [nowrap] }
25
+ ];
26
+ const rows: TableProps['rows'] = [
27
+ [
28
+ 'This text will truncate instead of wrap.',
29
+ { title: <a href="#">http://thisisaverylongurlthatneedstobreakusethebreakwordmodifier.org</a> },
30
+ {
31
+ title: (
32
+ <p>
33
+ By default,
34
+ <code>thead</code> cells will truncate and
35
+ <code>tbody</code> cells will wrap. Use
36
+ <code>transforms</code> and/or <code>cellTransforms</code> to change the behavior.
37
+ </p>
38
+ )
39
+ },
40
+ "This cell's content will adjust itself to the parent th width. This modifier only affects table layouts.",
41
+ { title: <a href="#">No wrap</a> }
42
+ ]
43
+ ];
44
+
45
+ return (
46
+ <Table aria-label="Controlling text" cells={columns} rows={rows}>
47
+ <TableHeader />
48
+ <TableBody />
49
+ </Table>
50
+ );
51
+ };