@patternfly/react-table 4.44.10 → 4.44.14
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/esm/components/Table/Table.d.ts +2 -1
- package/dist/esm/components/Table/Table.d.ts.map +1 -1
- package/dist/esm/components/Table/Table.js.map +1 -1
- package/dist/esm/components/Table/TableTypes.d.ts +2 -1
- package/dist/esm/components/Table/TableTypes.d.ts.map +1 -1
- package/dist/esm/components/Table/TableTypes.js.map +1 -1
- package/dist/esm/components/Table/base/provider.d.ts +2 -2
- package/dist/esm/components/Table/base/types.d.ts +2 -2
- package/dist/esm/components/TableComposable/TableComposable.d.ts +1 -1
- package/dist/esm/components/TableComposable/Td.d.ts +1 -1
- package/dist/js/components/Table/Table.d.ts +2 -1
- package/dist/js/components/Table/Table.d.ts.map +1 -1
- package/dist/js/components/Table/Table.js.map +1 -1
- package/dist/js/components/Table/TableTypes.d.ts +2 -1
- package/dist/js/components/Table/TableTypes.d.ts.map +1 -1
- package/dist/js/components/Table/TableTypes.js.map +1 -1
- package/dist/js/components/Table/base/provider.d.ts +2 -2
- package/dist/js/components/Table/base/types.d.ts +2 -2
- package/dist/js/components/TableComposable/TableComposable.d.ts +1 -1
- package/dist/js/components/TableComposable/Td.d.ts +1 -1
- package/dist/umd/react-table.css +5 -3
- package/dist/umd/react-table.min.css +17 -15
- package/package.json +6 -6
- package/src/components/Table/Table.tsx +2 -1
- package/src/components/Table/TableTypes.tsx +2 -1
- package/src/components/Table/examples/LegacyTableActions.tsx +218 -0
- package/src/components/Table/examples/LegacyTableBasic.tsx +90 -0
- package/src/components/Table/examples/LegacyTableCellWidth.tsx +66 -0
- package/src/components/Table/examples/LegacyTableCompoundExpandable.tsx +175 -0
- package/src/components/Table/examples/LegacyTableControllingText.tsx +51 -0
- package/src/components/Table/examples/LegacyTableEmptyState.tsx +48 -0
- package/src/components/Table/examples/LegacyTableExpandable.tsx +172 -0
- package/src/components/Table/examples/LegacyTableFavoritable.tsx +157 -0
- package/src/components/Table/examples/LegacyTableHoverable.tsx +125 -0
- package/src/components/Table/examples/LegacyTableMisc.tsx +56 -0
- package/src/components/Table/examples/LegacyTableSelectable.tsx +124 -0
- package/src/components/Table/examples/LegacyTableSelectableRadio.tsx +54 -0
- package/src/components/Table/examples/LegacyTableSortable.tsx +120 -0
- package/src/components/Table/examples/LegacyTableSortableCustom.tsx +189 -0
- package/src/components/Table/examples/LegacyTableTextModifiers.tsx +31 -0
- package/src/components/Table/examples/LegacyTableTree.tsx +213 -0
- package/src/components/Table/examples/Table.md +83 -1848
- package/src/components/TableComposable/examples/ComposableTable.md +31 -2805
- package/src/components/TableComposable/examples/ComposableTableActions.tsx +163 -0
- package/src/components/TableComposable/examples/ComposableTableBasic.tsx +89 -0
- package/src/components/TableComposable/examples/ComposableTableCellWidth.tsx +56 -0
- package/src/components/TableComposable/examples/ComposableTableCompoundExpandable.tsx +103 -0
- package/src/components/TableComposable/examples/ComposableTableControllingText.tsx +51 -0
- package/src/components/TableComposable/examples/ComposableTableDraggable.tsx +170 -0
- package/src/components/TableComposable/examples/ComposableTableEmptyState.tsx +45 -0
- package/src/components/TableComposable/examples/ComposableTableExpandable.tsx +195 -0
- package/src/components/TableComposable/examples/ComposableTableFavoritable.tsx +118 -0
- package/src/components/TableComposable/examples/ComposableTableHoverable.tsx +67 -0
- package/src/components/TableComposable/examples/ComposableTableMisc.tsx +92 -0
- package/src/components/TableComposable/examples/ComposableTableMultipleStickyColumns.tsx +153 -0
- package/src/components/TableComposable/examples/ComposableTableNestedExpandable.tsx +127 -0
- package/src/components/TableComposable/examples/ComposableTableNestedHeaders.tsx +202 -0
- package/src/components/TableComposable/examples/ComposableTableSelectable.tsx +125 -0
- package/src/components/TableComposable/examples/ComposableTableSelectableRadio.tsx +68 -0
- package/src/components/TableComposable/examples/ComposableTableSortable.tsx +107 -0
- package/src/components/TableComposable/examples/ComposableTableSortableCustom.tsx +175 -0
- package/src/components/TableComposable/examples/ComposableTableStickyColumn.tsx +144 -0
- package/src/components/TableComposable/examples/ComposableTableStickyColumnsAndHeader.tsx +167 -0
- package/src/components/TableComposable/examples/ComposableTableTextModifiers.tsx +33 -0
- package/src/components/TableComposable/examples/ComposableTableTree.tsx +201 -0
- package/src/demos/Table.md +7 -6
- package/src/components/Table/examples/DemoSortableTable.js +0 -65
- package/src/components/TableComposable/examples/DemoSortableTable.js +0 -65
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TableComposable, Thead, Tr, Th, Tbody, Td, ThProps } 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 ComposableTableSortableCustom: 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 getSortParams = (columnIndex: number): ThProps['sort'] => ({
|
|
82
|
+
sortBy: {
|
|
83
|
+
index: activeSortIndex,
|
|
84
|
+
direction: activeSortDirection
|
|
85
|
+
},
|
|
86
|
+
onSort: (_event, index, direction) => {
|
|
87
|
+
setActiveSortIndex(index);
|
|
88
|
+
setActiveSortDirection(direction);
|
|
89
|
+
},
|
|
90
|
+
columnIndex
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<React.Fragment>
|
|
95
|
+
<Toolbar id="toolbar">
|
|
96
|
+
<ToolbarContent>
|
|
97
|
+
<ToolbarItem>
|
|
98
|
+
<OptionsMenu
|
|
99
|
+
id="options-menu-multiple-options-example"
|
|
100
|
+
menuItems={[
|
|
101
|
+
<OptionsMenuItemGroup key="first group" aria-label="Sort column">
|
|
102
|
+
{Object.values(columnNames).map((columnName, columnIndex) => (
|
|
103
|
+
<OptionsMenuItem
|
|
104
|
+
key={columnName}
|
|
105
|
+
isSelected={activeSortIndex === columnIndex}
|
|
106
|
+
onSelect={() => {
|
|
107
|
+
setActiveSortIndex(columnIndex);
|
|
108
|
+
setActiveSortDirection(activeSortDirection !== null ? activeSortDirection : 'asc');
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
{columnName}
|
|
112
|
+
</OptionsMenuItem>
|
|
113
|
+
))}
|
|
114
|
+
</OptionsMenuItemGroup>,
|
|
115
|
+
<OptionsMenuSeparator key="separator" />,
|
|
116
|
+
<OptionsMenuItemGroup key="second group" aria-label="Sort direction">
|
|
117
|
+
<OptionsMenuItem
|
|
118
|
+
onSelect={() => setActiveSortDirection('asc')}
|
|
119
|
+
isSelected={activeSortDirection === 'asc'}
|
|
120
|
+
id="ascending"
|
|
121
|
+
key="ascending"
|
|
122
|
+
>
|
|
123
|
+
Ascending
|
|
124
|
+
</OptionsMenuItem>
|
|
125
|
+
<OptionsMenuItem
|
|
126
|
+
onSelect={() => setActiveSortDirection('desc')}
|
|
127
|
+
isSelected={activeSortDirection === 'desc'}
|
|
128
|
+
id="descending"
|
|
129
|
+
key="descending"
|
|
130
|
+
>
|
|
131
|
+
Descending
|
|
132
|
+
</OptionsMenuItem>
|
|
133
|
+
</OptionsMenuItemGroup>
|
|
134
|
+
]}
|
|
135
|
+
isOpen={isSortDropdownOpen}
|
|
136
|
+
toggle={
|
|
137
|
+
<OptionsMenuToggle
|
|
138
|
+
hideCaret
|
|
139
|
+
onToggle={() => setIsSortDropdownOpen(!isSortDropdownOpen)}
|
|
140
|
+
toggleTemplate={<SortAmountDownIcon />}
|
|
141
|
+
/>
|
|
142
|
+
}
|
|
143
|
+
isPlain
|
|
144
|
+
isGrouped
|
|
145
|
+
/>
|
|
146
|
+
</ToolbarItem>
|
|
147
|
+
</ToolbarContent>
|
|
148
|
+
</Toolbar>
|
|
149
|
+
<TableComposable aria-label="Sortable table custom toolbar">
|
|
150
|
+
<Thead>
|
|
151
|
+
<Tr>
|
|
152
|
+
<Th sort={getSortParams(0)}>{columnNames.name}</Th>
|
|
153
|
+
<Th sort={getSortParams(1)}>{columnNames.branches}</Th>
|
|
154
|
+
<Th sort={getSortParams(2)} info={{ tooltip: 'More information ' }}>
|
|
155
|
+
{columnNames.prs}
|
|
156
|
+
</Th>
|
|
157
|
+
<Th sort={getSortParams(3)}>{columnNames.workspaces}</Th>
|
|
158
|
+
<Th sort={getSortParams(4)}>{columnNames.lastCommit}</Th>
|
|
159
|
+
</Tr>
|
|
160
|
+
</Thead>
|
|
161
|
+
<Tbody>
|
|
162
|
+
{sortedRepositories.map((repo, rowIndex) => (
|
|
163
|
+
<Tr key={rowIndex}>
|
|
164
|
+
<Td dataLabel={columnNames.name}>{repo.name}</Td>
|
|
165
|
+
<Td dataLabel={columnNames.branches}>{repo.branches}</Td>
|
|
166
|
+
<Td dataLabel={columnNames.prs}>{repo.prs}</Td>
|
|
167
|
+
<Td dataLabel={columnNames.workspaces}>{repo.workspaces}</Td>
|
|
168
|
+
<Td dataLabel={columnNames.lastCommit}>{repo.lastCommit}</Td>
|
|
169
|
+
</Tr>
|
|
170
|
+
))}
|
|
171
|
+
</Tbody>
|
|
172
|
+
</TableComposable>
|
|
173
|
+
</React.Fragment>
|
|
174
|
+
);
|
|
175
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TableComposable, Thead, Tr, Th, Tbody, Td, InnerScrollContainer, ThProps } from '@patternfly/react-table';
|
|
3
|
+
|
|
4
|
+
interface Fact {
|
|
5
|
+
name: string;
|
|
6
|
+
state: string;
|
|
7
|
+
detail1: string;
|
|
8
|
+
detail2: string;
|
|
9
|
+
detail3: string;
|
|
10
|
+
detail4: string;
|
|
11
|
+
detail5: string;
|
|
12
|
+
detail6: string;
|
|
13
|
+
detail7: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const ComposableTableStickyColumn: React.FunctionComponent = () => {
|
|
17
|
+
// In real usage, this data would come from some external source like an API via props.
|
|
18
|
+
const facts: Fact[] = Array.from({ length: 9 }, (_, index) => ({
|
|
19
|
+
name: `Fact ${index + 1}`,
|
|
20
|
+
state: `State ${index + 1}`,
|
|
21
|
+
detail1: `Test cell ${index + 1}-3`,
|
|
22
|
+
detail2: `Test cell ${index + 1}-4`,
|
|
23
|
+
detail3: `Test cell ${index + 1}-5`,
|
|
24
|
+
detail4: `Test cell ${index + 1}-6`,
|
|
25
|
+
detail5: `Test cell ${index + 1}-7`,
|
|
26
|
+
detail6: `Test cell ${index + 1}-8`,
|
|
27
|
+
detail7: `Test cell ${index + 1}-9`
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
const columnNames = {
|
|
31
|
+
name: 'Fact',
|
|
32
|
+
state: 'State',
|
|
33
|
+
header3: 'Header 3',
|
|
34
|
+
header4: 'Header 4',
|
|
35
|
+
header5: 'Header 5',
|
|
36
|
+
header6: 'Header 6',
|
|
37
|
+
header7: 'Header 7',
|
|
38
|
+
header8: 'Header 8',
|
|
39
|
+
header9: 'Header 9'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Index of the currently sorted column
|
|
43
|
+
// Note: if you intend to make columns reorderable, you may instead want to use a non-numeric key
|
|
44
|
+
// as the identifier of the sorted column. See the "Compound expandable" example.
|
|
45
|
+
const [activeSortIndex, setActiveSortIndex] = React.useState<number | null>(null);
|
|
46
|
+
|
|
47
|
+
// Sort direction of the currently sorted column
|
|
48
|
+
const [activeSortDirection, setActiveSortDirection] = React.useState<'asc' | 'desc' | null>(null);
|
|
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 = (fact: Fact): (string | number)[] => {
|
|
54
|
+
const { name, state, detail1, detail2, detail3, detail4, detail5, detail6, detail7 } = fact;
|
|
55
|
+
return [name, state, detail1, detail2, detail3, detail4, detail5, detail6, detail7];
|
|
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 sortedFacts = facts;
|
|
61
|
+
if (activeSortIndex !== null) {
|
|
62
|
+
sortedFacts = facts.sort((a, b) => {
|
|
63
|
+
const aValue = getSortableRowValues(a)[activeSortIndex];
|
|
64
|
+
const bValue = getSortableRowValues(b)[activeSortIndex];
|
|
65
|
+
if (aValue === bValue) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
if (activeSortDirection === 'asc') {
|
|
69
|
+
return aValue > bValue ? 1 : -1;
|
|
70
|
+
} else {
|
|
71
|
+
return bValue > aValue ? 1 : -1;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const getSortParams = (columnIndex: number): ThProps['sort'] => ({
|
|
77
|
+
sortBy: {
|
|
78
|
+
index: activeSortIndex,
|
|
79
|
+
direction: activeSortDirection
|
|
80
|
+
},
|
|
81
|
+
onSort: (_event, index, direction) => {
|
|
82
|
+
setActiveSortIndex(index);
|
|
83
|
+
setActiveSortDirection(direction);
|
|
84
|
+
},
|
|
85
|
+
columnIndex
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<InnerScrollContainer>
|
|
90
|
+
<TableComposable aria-label="Sticky column table" gridBreakPoint="">
|
|
91
|
+
<Thead>
|
|
92
|
+
<Tr>
|
|
93
|
+
<Th isStickyColumn hasRightBorder modifier="truncate" sort={getSortParams(0)}>
|
|
94
|
+
{columnNames.name}
|
|
95
|
+
</Th>
|
|
96
|
+
<Th modifier="truncate" sort={getSortParams(1)}>
|
|
97
|
+
{columnNames.state}
|
|
98
|
+
</Th>
|
|
99
|
+
<Th modifier="truncate">{columnNames.header3}</Th>
|
|
100
|
+
<Th modifier="truncate">{columnNames.header4}</Th>
|
|
101
|
+
<Th modifier="truncate">{columnNames.header5}</Th>
|
|
102
|
+
<Th modifier="truncate">{columnNames.header6}</Th>
|
|
103
|
+
<Th modifier="truncate">{columnNames.header7}</Th>
|
|
104
|
+
<Th modifier="truncate">{columnNames.header8}</Th>
|
|
105
|
+
<Th modifier="truncate">{columnNames.header9}</Th>
|
|
106
|
+
</Tr>
|
|
107
|
+
</Thead>
|
|
108
|
+
<Tbody>
|
|
109
|
+
{sortedFacts.map(fact => (
|
|
110
|
+
<Tr key={fact.name}>
|
|
111
|
+
<Th isStickyColumn hasRightBorder modifier="truncate">
|
|
112
|
+
{fact.name}
|
|
113
|
+
</Th>
|
|
114
|
+
<Td modifier="nowrap" dataLabel={columnNames.state}>
|
|
115
|
+
{fact.state}
|
|
116
|
+
</Td>
|
|
117
|
+
<Td modifier="nowrap" dataLabel={columnNames.header3}>
|
|
118
|
+
{fact.detail1}
|
|
119
|
+
</Td>
|
|
120
|
+
<Td modifier="nowrap" dataLabel={columnNames.header4}>
|
|
121
|
+
{fact.detail2}
|
|
122
|
+
</Td>
|
|
123
|
+
<Td modifier="nowrap" dataLabel={columnNames.header5}>
|
|
124
|
+
{fact.detail3}
|
|
125
|
+
</Td>
|
|
126
|
+
<Td modifier="nowrap" dataLabel={columnNames.header6}>
|
|
127
|
+
{fact.detail4}
|
|
128
|
+
</Td>
|
|
129
|
+
<Td modifier="nowrap" dataLabel={columnNames.header7}>
|
|
130
|
+
{fact.detail5}
|
|
131
|
+
</Td>
|
|
132
|
+
<Td modifier="nowrap" dataLabel={columnNames.header8}>
|
|
133
|
+
{fact.detail6}
|
|
134
|
+
</Td>
|
|
135
|
+
<Td modifier="nowrap" dataLabel={columnNames.header9}>
|
|
136
|
+
{fact.detail7}
|
|
137
|
+
</Td>
|
|
138
|
+
</Tr>
|
|
139
|
+
))}
|
|
140
|
+
</Tbody>
|
|
141
|
+
</TableComposable>
|
|
142
|
+
</InnerScrollContainer>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
TableComposable,
|
|
4
|
+
Thead,
|
|
5
|
+
Tr,
|
|
6
|
+
Th,
|
|
7
|
+
Tbody,
|
|
8
|
+
Td,
|
|
9
|
+
InnerScrollContainer,
|
|
10
|
+
OuterScrollContainer,
|
|
11
|
+
ThProps
|
|
12
|
+
} from '@patternfly/react-table';
|
|
13
|
+
import BlueprintIcon from '@patternfly/react-icons/dist/esm/icons/blueprint-icon';
|
|
14
|
+
|
|
15
|
+
interface Fact {
|
|
16
|
+
name: string;
|
|
17
|
+
state: string;
|
|
18
|
+
detail1: string;
|
|
19
|
+
detail2: string;
|
|
20
|
+
detail3: string;
|
|
21
|
+
detail4: string;
|
|
22
|
+
detail5: string;
|
|
23
|
+
detail6: string;
|
|
24
|
+
detail7: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const ComposableTableStickyColumnsAndHeader: React.FunctionComponent = () => {
|
|
28
|
+
// In real usage, this data would come from some external source like an API via props.
|
|
29
|
+
const facts: Fact[] = Array.from({ length: 9 }, (_, index) => ({
|
|
30
|
+
name: `Fact ${index + 1}`,
|
|
31
|
+
state: `State ${index + 1}`,
|
|
32
|
+
detail1: `Test cell ${index + 1}-3`,
|
|
33
|
+
detail2: `Test cell ${index + 1}-4`,
|
|
34
|
+
detail3: `Test cell ${index + 1}-5`,
|
|
35
|
+
detail4: `Test cell ${index + 1}-6`,
|
|
36
|
+
detail5: `Test cell ${index + 1}-7`,
|
|
37
|
+
detail6: `Test cell ${index + 1}-8`,
|
|
38
|
+
detail7: `Test cell ${index + 1}-9`
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
const columnNames = {
|
|
42
|
+
name: 'Fact',
|
|
43
|
+
state: 'State',
|
|
44
|
+
header3: 'Header 3',
|
|
45
|
+
header4: 'Header 4',
|
|
46
|
+
header5: 'Header 5',
|
|
47
|
+
header6: 'Header 6',
|
|
48
|
+
header7: 'Header 7',
|
|
49
|
+
header8: 'Header 8',
|
|
50
|
+
header9: 'Header 9'
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Index of the currently sorted column
|
|
54
|
+
// Note: if you intend to make columns reorderable, you may instead want to use a non-numeric key
|
|
55
|
+
// as the identifier of the sorted column. See the "Compound expandable" example.
|
|
56
|
+
const [activeSortIndex, setActiveSortIndex] = React.useState<number | null>(null);
|
|
57
|
+
|
|
58
|
+
// Sort direction of the currently sorted column
|
|
59
|
+
const [activeSortDirection, setActiveSortDirection] = React.useState<'asc' | 'desc' | null>(null);
|
|
60
|
+
|
|
61
|
+
// Since OnSort specifies sorted columns by index, we need sortable values for our object by column index.
|
|
62
|
+
// This example is trivial since our data objects just contain strings, but if the data was more complex
|
|
63
|
+
// this would be a place to return simplified string or number versions of each column to sort by.
|
|
64
|
+
const getSortableRowValues = (fact: Fact): (string | number)[] => {
|
|
65
|
+
const { name, state, detail1, detail2, detail3, detail4, detail5, detail6, detail7 } = fact;
|
|
66
|
+
return [name, state, detail1, detail2, detail3, detail4, detail5, detail6, detail7];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Note that we perform the sort as part of the component's render logic and not in onSort.
|
|
70
|
+
// We shouldn't store the list of data in state because we don't want to have to sync that with props.
|
|
71
|
+
let sortedFacts = facts;
|
|
72
|
+
if (activeSortIndex !== null) {
|
|
73
|
+
sortedFacts = facts.sort((a, b) => {
|
|
74
|
+
const aValue = getSortableRowValues(a)[activeSortIndex];
|
|
75
|
+
const bValue = getSortableRowValues(b)[activeSortIndex];
|
|
76
|
+
if (aValue === bValue) {
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
if (activeSortDirection === 'asc') {
|
|
80
|
+
return aValue > bValue ? 1 : -1;
|
|
81
|
+
} else {
|
|
82
|
+
return bValue > aValue ? 1 : -1;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const getSortParams = (columnIndex: number): ThProps['sort'] => ({
|
|
88
|
+
sortBy: {
|
|
89
|
+
index: activeSortIndex,
|
|
90
|
+
direction: activeSortDirection
|
|
91
|
+
},
|
|
92
|
+
onSort: (_event, index, direction) => {
|
|
93
|
+
setActiveSortIndex(index);
|
|
94
|
+
setActiveSortDirection(direction);
|
|
95
|
+
},
|
|
96
|
+
columnIndex
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div style={{ height: '600px' }}>
|
|
101
|
+
<OuterScrollContainer>
|
|
102
|
+
<InnerScrollContainer>
|
|
103
|
+
<TableComposable aria-label="Sticky columns and header table" gridBreakPoint="" isStickyHeader>
|
|
104
|
+
<Thead>
|
|
105
|
+
<Tr>
|
|
106
|
+
<Th isStickyColumn modifier="truncate" sort={getSortParams(0)}>
|
|
107
|
+
{columnNames.name}
|
|
108
|
+
</Th>
|
|
109
|
+
<Th
|
|
110
|
+
isStickyColumn
|
|
111
|
+
stickyMinWidth="120px"
|
|
112
|
+
stickyLeftOffset="120px"
|
|
113
|
+
hasRightBorder
|
|
114
|
+
modifier="truncate"
|
|
115
|
+
sort={getSortParams(1)}
|
|
116
|
+
>
|
|
117
|
+
{columnNames.state}
|
|
118
|
+
</Th>
|
|
119
|
+
<Th modifier="truncate">{columnNames.header3}</Th>
|
|
120
|
+
<Th modifier="truncate">{columnNames.header4}</Th>
|
|
121
|
+
<Th modifier="truncate">{columnNames.header5}</Th>
|
|
122
|
+
<Th modifier="truncate">{columnNames.header6}</Th>
|
|
123
|
+
<Th modifier="truncate">{columnNames.header7}</Th>
|
|
124
|
+
<Th modifier="truncate">{columnNames.header8}</Th>
|
|
125
|
+
<Th modifier="truncate">{columnNames.header9}</Th>
|
|
126
|
+
</Tr>
|
|
127
|
+
</Thead>
|
|
128
|
+
<Tbody>
|
|
129
|
+
{sortedFacts.map(fact => (
|
|
130
|
+
<Tr key={fact.name}>
|
|
131
|
+
<Th isStickyColumn modifier="truncate">
|
|
132
|
+
{fact.name}
|
|
133
|
+
</Th>
|
|
134
|
+
<Th isStickyColumn stickyMinWidth="120px" stickyLeftOffset="120px" modifier="truncate" hasRightBorder>
|
|
135
|
+
<BlueprintIcon />
|
|
136
|
+
{` ${fact.state}`}
|
|
137
|
+
</Th>
|
|
138
|
+
<Td modifier="nowrap" dataLabel={columnNames.header3}>
|
|
139
|
+
{fact.detail1}
|
|
140
|
+
</Td>
|
|
141
|
+
<Td modifier="nowrap" dataLabel={columnNames.header4}>
|
|
142
|
+
{fact.detail2}
|
|
143
|
+
</Td>
|
|
144
|
+
<Td modifier="nowrap" dataLabel={columnNames.header5}>
|
|
145
|
+
{fact.detail3}
|
|
146
|
+
</Td>
|
|
147
|
+
<Td modifier="nowrap" dataLabel={columnNames.header6}>
|
|
148
|
+
{fact.detail4}
|
|
149
|
+
</Td>
|
|
150
|
+
<Td modifier="nowrap" dataLabel={columnNames.header7}>
|
|
151
|
+
{fact.detail5}
|
|
152
|
+
</Td>
|
|
153
|
+
<Td modifier="nowrap" dataLabel={columnNames.header8}>
|
|
154
|
+
{fact.detail6}
|
|
155
|
+
</Td>
|
|
156
|
+
<Td modifier="nowrap" dataLabel={columnNames.header9}>
|
|
157
|
+
{fact.detail7}
|
|
158
|
+
</Td>
|
|
159
|
+
</Tr>
|
|
160
|
+
))}
|
|
161
|
+
</Tbody>
|
|
162
|
+
</TableComposable>
|
|
163
|
+
</InnerScrollContainer>
|
|
164
|
+
</OuterScrollContainer>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TableComposable, Thead, Tr, Th, Tbody, Td, TableText } 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
|
+
const columnNames = {
|
|
8
|
+
truncate: 'Truncating text',
|
|
9
|
+
wrap: 'Wrapping table header text. This th text will wrap instead of truncate.'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const ComposableTableText: React.FunctionComponent = () => (
|
|
13
|
+
<TableComposable aria-label="Table text">
|
|
14
|
+
<Thead>
|
|
15
|
+
<Tr>
|
|
16
|
+
<Th width={30}>{columnNames.truncate}</Th>
|
|
17
|
+
<Th>{columnNames.wrap}</Th>
|
|
18
|
+
</Tr>
|
|
19
|
+
</Thead>
|
|
20
|
+
<Tbody>
|
|
21
|
+
<Tr>
|
|
22
|
+
<Td dataLabel={columnNames.truncate}>
|
|
23
|
+
<TableText wrapModifier="truncate">This text will truncate instead of wrap.</TableText>
|
|
24
|
+
</Td>
|
|
25
|
+
<Td dataLabel={columnNames.wrap}>
|
|
26
|
+
<TableText wrapModifier="nowrap">
|
|
27
|
+
<a href="#">This is a link that needs to be on one line and fully readable.</a>
|
|
28
|
+
</TableText>
|
|
29
|
+
</Td>
|
|
30
|
+
</Tr>
|
|
31
|
+
</Tbody>
|
|
32
|
+
</TableComposable>
|
|
33
|
+
);
|