@patternfly/react-table 5.4.0-prerelease.3 → 5.4.0-prerelease.30
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 +118 -0
- package/README.md +2 -17
- package/components/package.json +1 -1
- package/deprecated/package.json +1 -1
- package/dist/dynamic/components/Table/package.json +1 -1
- package/dist/dynamic/components/Table/utils/decorators/package.json +1 -1
- package/dist/dynamic/components/Table/utils/package.json +1 -1
- package/dist/dynamic/deprecated/components/Table/base/package.json +1 -1
- package/dist/dynamic/deprecated/components/Table/package.json +1 -1
- package/dist/dynamic/deprecated/components/package.json +1 -1
- package/dist/esm/components/Table/ActionsColumn.js.map +1 -1
- package/dist/esm/components/Table/RowWrapper.js.map +1 -1
- package/dist/esm/components/Table/SortColumn.js.map +1 -1
- package/dist/esm/components/Table/Table.js.map +1 -1
- package/dist/esm/components/Table/TableText.js.map +1 -1
- package/dist/esm/components/Table/TableTypes.d.ts +22 -22
- package/dist/esm/components/Table/TableTypes.d.ts.map +1 -1
- package/dist/esm/components/Table/Td.js.map +1 -1
- package/dist/esm/components/Table/Th.js.map +1 -1
- package/dist/esm/components/Table/Tr.d.ts +2 -0
- package/dist/esm/components/Table/Tr.d.ts.map +1 -1
- package/dist/esm/components/Table/Tr.js +2 -2
- package/dist/esm/components/Table/Tr.js.map +1 -1
- package/dist/esm/components/Table/base/columns-are-equal.js.map +1 -1
- package/dist/esm/components/Table/base/evaluate-transforms.js.map +1 -1
- package/dist/esm/components/Table/base/merge-props.js.map +1 -1
- package/dist/esm/components/Table/base/provider.js.map +1 -1
- package/dist/esm/components/Table/base/types.d.ts +10 -10
- package/dist/esm/components/Table/base/types.d.ts.map +1 -1
- package/dist/esm/components/Table/utils/decorators/compoundExpand.js.map +1 -1
- package/dist/esm/components/Table/utils/decorators/editable.js.map +1 -1
- package/dist/esm/components/Table/utils/decorators/favoritable.js.map +1 -1
- package/dist/esm/components/Table/utils/decorators/selectable.js.map +1 -1
- package/dist/esm/components/Table/utils/decorators/sortable.js.map +1 -1
- package/dist/esm/components/Table/utils/headerUtils.js.map +1 -1
- package/dist/esm/components/Table/utils/utils.js.map +1 -1
- package/dist/esm/demos/DashboardWrapper.js.map +1 -1
- package/dist/esm/deprecated/components/Table/Body.d.ts +1 -1
- package/dist/esm/deprecated/components/Table/Body.d.ts.map +1 -1
- package/dist/esm/deprecated/components/Table/Body.js.map +1 -1
- package/dist/esm/deprecated/components/Table/BodyCell.js.map +1 -1
- package/dist/esm/deprecated/components/Table/BodyWrapper.js.map +1 -1
- package/dist/esm/deprecated/components/Table/Table.js.map +1 -1
- package/dist/esm/deprecated/components/Table/base/body-row.js.map +1 -1
- package/dist/esm/deprecated/components/Table/base/body.js.map +1 -1
- package/dist/esm/deprecated/components/Table/base/header-row.js.map +1 -1
- package/dist/esm/deprecated/components/Table/base/resolve-row-key.js.map +1 -1
- package/dist/esm/test-helpers/data-helpers.js.map +1 -1
- package/dist/js/components/Table/ActionsColumn.js.map +1 -1
- package/dist/js/components/Table/CollapseColumn.js.map +1 -1
- package/dist/js/components/Table/DraggableCell.js.map +1 -1
- package/dist/js/components/Table/EditColumn.js.map +1 -1
- package/dist/js/components/Table/EditableSelectInputCell.js.map +1 -1
- package/dist/js/components/Table/EditableTextCell.js.map +1 -1
- package/dist/js/components/Table/FavoritesCell.js.map +1 -1
- package/dist/js/components/Table/HeaderCellInfoWrapper.js.map +1 -1
- package/dist/js/components/Table/RowWrapper.js +0 -1
- package/dist/js/components/Table/RowWrapper.js.map +1 -1
- package/dist/js/components/Table/SelectColumn.js +1 -1
- package/dist/js/components/Table/SelectColumn.js.map +1 -1
- package/dist/js/components/Table/SortColumn.js +1 -2
- package/dist/js/components/Table/SortColumn.js.map +1 -1
- package/dist/js/components/Table/Table.js.map +1 -1
- package/dist/js/components/Table/TableText.js +2 -2
- package/dist/js/components/Table/TableText.js.map +1 -1
- package/dist/js/components/Table/TableTypes.d.ts +22 -22
- package/dist/js/components/Table/TableTypes.d.ts.map +1 -1
- package/dist/js/components/Table/TableTypes.js +2 -6
- package/dist/js/components/Table/TableTypes.js.map +1 -1
- package/dist/js/components/Table/Td.js.map +1 -1
- package/dist/js/components/Table/Th.js.map +1 -1
- package/dist/js/components/Table/Tr.d.ts +2 -0
- package/dist/js/components/Table/Tr.d.ts.map +1 -1
- package/dist/js/components/Table/Tr.js +2 -2
- package/dist/js/components/Table/Tr.js.map +1 -1
- package/dist/js/components/Table/base/columns-are-equal.js.map +1 -1
- package/dist/js/components/Table/base/evaluate-transforms.js.map +1 -1
- package/dist/js/components/Table/base/merge-props.js.map +1 -1
- package/dist/js/components/Table/base/provider.js.map +1 -1
- package/dist/js/components/Table/base/types.d.ts +10 -10
- package/dist/js/components/Table/base/types.d.ts.map +1 -1
- package/dist/js/components/Table/base/types.js +0 -4
- package/dist/js/components/Table/base/types.js.map +1 -1
- package/dist/js/components/Table/utils/decorators/compoundExpand.js.map +1 -1
- package/dist/js/components/Table/utils/decorators/editable.js.map +1 -1
- package/dist/js/components/Table/utils/decorators/favoritable.js.map +1 -1
- package/dist/js/components/Table/utils/decorators/selectable.js.map +1 -1
- package/dist/js/components/Table/utils/decorators/sortable.js.map +1 -1
- package/dist/js/components/Table/utils/decorators/treeRow.js.map +1 -1
- package/dist/js/components/Table/utils/headerUtils.js.map +1 -1
- package/dist/js/components/Table/utils/utils.js.map +1 -1
- package/dist/js/demos/DashboardHeader.js.map +1 -1
- package/dist/js/demos/DashboardWrapper.js.map +1 -1
- package/dist/js/deprecated/components/Table/Body.d.ts +1 -1
- package/dist/js/deprecated/components/Table/Body.d.ts.map +1 -1
- package/dist/js/deprecated/components/Table/Body.js.map +1 -1
- package/dist/js/deprecated/components/Table/BodyCell.js +0 -1
- package/dist/js/deprecated/components/Table/BodyCell.js.map +1 -1
- package/dist/js/deprecated/components/Table/BodyWrapper.js.map +1 -1
- package/dist/js/deprecated/components/Table/Table.js.map +1 -1
- package/dist/js/deprecated/components/Table/base/body-row.js.map +1 -1
- package/dist/js/deprecated/components/Table/base/body.js.map +1 -1
- package/dist/js/deprecated/components/Table/base/header-row.js.map +1 -1
- package/dist/js/deprecated/components/Table/base/resolve-row-key.js.map +1 -1
- package/dist/js/test-helpers/data-helpers.js.map +1 -1
- package/dist/umd/assets/output-C9SGt1J5.css +30664 -0
- package/dist/umd/react-table.min.js +4 -5
- package/package.json +8 -11
- package/rollup.config.mjs +8 -0
- package/src/components/Table/TableTypes.tsx +5 -5
- package/src/components/Table/Tr.tsx +4 -0
- package/src/components/Table/examples/Table.md +11 -0
- package/src/components/Table/examples/TableCompoundExpandable.tsx +1 -1
- package/src/components/Table/examples/TableEditable.tsx +313 -0
- package/src/components/Table/utils/__snapshots__/transformers.test.tsx.snap +2 -2
- package/src/demos/examples/TableColumnManagement.tsx +1 -1
- package/src/demos/examples/TableColumnManagementWithDraggable.tsx +1 -1
- package/src/deprecated/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +57 -0
- package/src/deprecated/components/Table/examples/Table.md +36 -18
- package/rollup.config.js +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-table",
|
|
3
|
-
"version": "5.4.0-prerelease.
|
|
3
|
+
"version": "5.4.0-prerelease.30",
|
|
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",
|
|
@@ -39,19 +39,16 @@
|
|
|
39
39
|
"subpaths": "node ../../scripts/exportSubpaths.js --config subpaths.config.json"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@patternfly/react-core": "^5.4.0-prerelease.
|
|
43
|
-
"@patternfly/react-icons": "^5.4.0-prerelease.
|
|
44
|
-
"@patternfly/react-styles": "^5.4.0-prerelease.
|
|
45
|
-
"@patternfly/react-tokens": "^5.4.0-prerelease.
|
|
46
|
-
"lodash": "^4.17.
|
|
47
|
-
"tslib": "^2.
|
|
48
|
-
},
|
|
49
|
-
"devDependencies": {
|
|
50
|
-
"typescript": "^4.7.4"
|
|
42
|
+
"@patternfly/react-core": "^5.4.0-prerelease.27",
|
|
43
|
+
"@patternfly/react-icons": "^5.4.0-prerelease.10",
|
|
44
|
+
"@patternfly/react-styles": "^5.4.0-prerelease.11",
|
|
45
|
+
"@patternfly/react-tokens": "^5.4.0-prerelease.10",
|
|
46
|
+
"lodash": "^4.17.21",
|
|
47
|
+
"tslib": "^2.6.3"
|
|
51
48
|
},
|
|
52
49
|
"peerDependencies": {
|
|
53
50
|
"react": "^17 || ^18",
|
|
54
51
|
"react-dom": "^17 || ^18"
|
|
55
52
|
},
|
|
56
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "0781d69df6e3426e8973572c587e1f51b5ce693e"
|
|
57
54
|
}
|
|
@@ -138,7 +138,7 @@ export interface IExtra extends IExtraData {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
export type IFormatterValueType = formatterValueType & {
|
|
141
|
-
title?:
|
|
141
|
+
title?: React.ReactNode;
|
|
142
142
|
props?: any;
|
|
143
143
|
};
|
|
144
144
|
|
|
@@ -157,7 +157,7 @@ export interface IAction extends Omit<DropdownItemProps, 'title' | 'onClick'>, P
|
|
|
157
157
|
/** Key of actions menu item */
|
|
158
158
|
itemKey?: string;
|
|
159
159
|
/** Content to display in the actions menu item */
|
|
160
|
-
title?:
|
|
160
|
+
title?: React.ReactNode;
|
|
161
161
|
/** Render item as aria-disabled option */
|
|
162
162
|
isAriaDisabled?: boolean;
|
|
163
163
|
/** Props for adding a tooltip to a menu item. This is used to display tooltip when hovered over the item */
|
|
@@ -191,7 +191,7 @@ export interface decoratorReturnType {
|
|
|
191
191
|
textCenter?: boolean;
|
|
192
192
|
component?: string;
|
|
193
193
|
isVisible?: boolean;
|
|
194
|
-
title?:
|
|
194
|
+
title?: React.ReactNode;
|
|
195
195
|
props?: any;
|
|
196
196
|
scope?: string;
|
|
197
197
|
parentId?: number;
|
|
@@ -205,7 +205,7 @@ export type IFormatter = (data?: IFormatterValueType, extra?: IExtra) => formatt
|
|
|
205
205
|
|
|
206
206
|
export interface ICell {
|
|
207
207
|
/* cell contents */
|
|
208
|
-
title?:
|
|
208
|
+
title?: React.ReactNode;
|
|
209
209
|
/** transformations applied to the header cell */
|
|
210
210
|
transforms?: ITransform[];
|
|
211
211
|
/** transformations applied to the cells within the column's body */
|
|
@@ -229,7 +229,7 @@ export interface ICell {
|
|
|
229
229
|
export type RowCellContent<T = any> = (value?: string, rowIndex?: number, cellIndex?: number, props?: T) => void;
|
|
230
230
|
|
|
231
231
|
export interface IRowCell<T = any> {
|
|
232
|
-
title?:
|
|
232
|
+
title?: React.ReactNode | RowCellContent<T>;
|
|
233
233
|
props?: T;
|
|
234
234
|
formatters?: IFormatter[];
|
|
235
235
|
}
|
|
@@ -28,6 +28,8 @@ export interface TrProps extends Omit<React.HTMLProps<HTMLTableRowElement>, 'onR
|
|
|
28
28
|
isStriped?: boolean;
|
|
29
29
|
/** Flag indicating the row will act as a border. This is typically used for a table with a nested and sticky header. */
|
|
30
30
|
isBorderRow?: boolean;
|
|
31
|
+
/** Flag indicating the row is controlling the expansion of another row. */
|
|
32
|
+
isControlRow?: boolean;
|
|
31
33
|
/** An event handler for the row */
|
|
32
34
|
onRowClick?: (event?: React.KeyboardEvent | React.MouseEvent) => void;
|
|
33
35
|
/** Flag indicating that the row is selectable */
|
|
@@ -50,6 +52,7 @@ const TrBase: React.FunctionComponent<TrProps> = ({
|
|
|
50
52
|
isRowSelected = false,
|
|
51
53
|
isStriped = false,
|
|
52
54
|
isBorderRow = false,
|
|
55
|
+
isControlRow = false,
|
|
53
56
|
innerRef,
|
|
54
57
|
ouiaId,
|
|
55
58
|
ouiaSafe = true,
|
|
@@ -100,6 +103,7 @@ const TrBase: React.FunctionComponent<TrProps> = ({
|
|
|
100
103
|
isRowSelected && styles.modifiers.selected,
|
|
101
104
|
isStriped && styles.modifiers.striped,
|
|
102
105
|
isBorderRow && styles.modifiers.borderRow,
|
|
106
|
+
isControlRow && styles.tableControlRow,
|
|
103
107
|
resetOffset && styles.modifiers.firstCellOffsetReset
|
|
104
108
|
)}
|
|
105
109
|
hidden={rowIsHidden}
|
|
@@ -51,11 +51,15 @@ import FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-i
|
|
|
51
51
|
import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
|
|
52
52
|
import BlueprintIcon from '@patternfly/react-icons/dist/esm/icons/blueprint-icon';
|
|
53
53
|
import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
|
|
54
|
+
import PencilAltIcon from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';
|
|
55
|
+
import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
|
|
56
|
+
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
54
57
|
|
|
55
58
|
import { css } from '@patternfly/react-styles';
|
|
56
59
|
import styles from '@patternfly/react-styles/css/components/Table/table';
|
|
57
60
|
import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing';
|
|
58
61
|
import textStyles from '@patternfly/react-styles/css/utilities/Text/text';
|
|
62
|
+
import inlineEditStyles from '@patternfly/react-styles/css/components/InlineEdit/inline-edit';
|
|
59
63
|
import global_BackgroundColor_150 from '@patternfly/react-tokens/dist/esm/global_BackgroundColor_150';
|
|
60
64
|
|
|
61
65
|
## Table examples
|
|
@@ -156,6 +160,13 @@ This selectable rows feature is intended for use when a table is used to present
|
|
|
156
160
|
```ts file="TableClickable.tsx"
|
|
157
161
|
```
|
|
158
162
|
|
|
163
|
+
### Editable rows
|
|
164
|
+
|
|
165
|
+
This example shows a table with editable rows. Cells in a row can be edited after clicking on the edit icon.
|
|
166
|
+
|
|
167
|
+
```ts file="TableEditable.tsx"
|
|
168
|
+
```
|
|
169
|
+
|
|
159
170
|
### Actions
|
|
160
171
|
|
|
161
172
|
This example demonstrates adding actions as the last column. The header's last cell is an empty cell, and each body row's last cell is an action cell.
|
|
@@ -75,7 +75,7 @@ export const TableCompoundExpandable: React.FunctionComponent = () => {
|
|
|
75
75
|
const isRowExpanded = !!expandedCellKey;
|
|
76
76
|
return (
|
|
77
77
|
<Tbody key={repo.name} isExpanded={isRowExpanded}>
|
|
78
|
-
<Tr>
|
|
78
|
+
<Tr isControlRow>
|
|
79
79
|
<Td width={25} dataLabel={columnNames.name} component="th">
|
|
80
80
|
<a href="#">{repo.name}</a>
|
|
81
81
|
</Td>
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
|
|
3
|
+
import { Button, Checkbox, Radio, TextInput, KeyTypes, getUniqueId } from '@patternfly/react-core';
|
|
4
|
+
import PencilAltIcon from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';
|
|
5
|
+
import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
|
|
6
|
+
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
7
|
+
import inlineEditStyles from '@patternfly/react-styles/css/components/InlineEdit/inline-edit';
|
|
8
|
+
import { css } from '@patternfly/react-styles';
|
|
9
|
+
|
|
10
|
+
interface EditButtonsCellProps {
|
|
11
|
+
onClick: (type: 'save' | 'cancel' | 'edit') => void;
|
|
12
|
+
elementToFocusOnEditRef?: React.MutableRefObject<HTMLElement>;
|
|
13
|
+
rowAriaLabel: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const EditButtonsCell: React.FunctionComponent<EditButtonsCellProps> = ({
|
|
17
|
+
onClick,
|
|
18
|
+
elementToFocusOnEditRef,
|
|
19
|
+
rowAriaLabel = 'row'
|
|
20
|
+
}) => {
|
|
21
|
+
const editButtonRef = React.useRef<HTMLButtonElement>();
|
|
22
|
+
|
|
23
|
+
const onKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, button: 'edit' | 'stopEditing') => {
|
|
24
|
+
const focusRef = button === 'edit' ? elementToFocusOnEditRef : editButtonRef;
|
|
25
|
+
|
|
26
|
+
if (event.key === KeyTypes.Enter || event.key === KeyTypes.Space) {
|
|
27
|
+
// because space key triggers click event before keyDown, we have to prevent default behaviour and trigger click manually
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
(event.target as HTMLButtonElement).click();
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
focusRef?.current?.focus();
|
|
32
|
+
}, 0);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
<Td
|
|
39
|
+
dataLabel="Save and cancel buttons"
|
|
40
|
+
className={css(
|
|
41
|
+
inlineEditStyles.inlineEditGroup,
|
|
42
|
+
inlineEditStyles.modifiers.iconGroup,
|
|
43
|
+
inlineEditStyles.modifiers.actionGroup
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
<div className={css(inlineEditStyles.inlineEditAction, inlineEditStyles.modifiers.valid)}>
|
|
47
|
+
<Button
|
|
48
|
+
aria-label={`Save edits of ${rowAriaLabel}`}
|
|
49
|
+
onClick={() => onClick('save')}
|
|
50
|
+
onKeyDown={(event) => onKeyDown(event, 'stopEditing')}
|
|
51
|
+
variant="plain"
|
|
52
|
+
>
|
|
53
|
+
<CheckIcon />
|
|
54
|
+
</Button>
|
|
55
|
+
</div>
|
|
56
|
+
<div className={css(inlineEditStyles.inlineEditAction)}>
|
|
57
|
+
<Button
|
|
58
|
+
aria-label={`Discard edits of ${rowAriaLabel}`}
|
|
59
|
+
onClick={() => onClick('cancel')}
|
|
60
|
+
onKeyDown={(event) => onKeyDown(event, 'stopEditing')}
|
|
61
|
+
variant="plain"
|
|
62
|
+
>
|
|
63
|
+
<TimesIcon />
|
|
64
|
+
</Button>
|
|
65
|
+
</div>
|
|
66
|
+
</Td>
|
|
67
|
+
<Td
|
|
68
|
+
dataLabel="Edit button"
|
|
69
|
+
className={css(inlineEditStyles.inlineEditAction, inlineEditStyles.modifiers.enableEditable)}
|
|
70
|
+
>
|
|
71
|
+
<Button
|
|
72
|
+
ref={editButtonRef}
|
|
73
|
+
aria-label={`Edit ${rowAriaLabel}`}
|
|
74
|
+
onClick={() => onClick('edit')}
|
|
75
|
+
onKeyDown={(event) => onKeyDown(event, 'edit')}
|
|
76
|
+
variant="plain"
|
|
77
|
+
>
|
|
78
|
+
<PencilAltIcon />
|
|
79
|
+
</Button>
|
|
80
|
+
</Td>
|
|
81
|
+
</>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
interface EditableCellProps {
|
|
86
|
+
dataLabel: string;
|
|
87
|
+
staticValue: React.ReactNode;
|
|
88
|
+
editingValue: React.ReactNode;
|
|
89
|
+
role?: string;
|
|
90
|
+
ariaLabel?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const EditableCell: React.FunctionComponent<EditableCellProps> = ({
|
|
94
|
+
dataLabel,
|
|
95
|
+
staticValue,
|
|
96
|
+
editingValue,
|
|
97
|
+
role,
|
|
98
|
+
ariaLabel
|
|
99
|
+
}) => {
|
|
100
|
+
const hasMultipleInputs = Array.isArray(editingValue) && editingValue.every((elem) => React.isValidElement(elem));
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Td dataLabel={dataLabel}>
|
|
104
|
+
<div className={css(inlineEditStyles.inlineEditValue)}>{staticValue}</div>
|
|
105
|
+
{hasMultipleInputs ? (
|
|
106
|
+
<div className={css(inlineEditStyles.inlineEditGroup, 'pf-m-column')} role={role} aria-label={ariaLabel}>
|
|
107
|
+
{(editingValue as React.ReactElement[]).map((elem, index) => (
|
|
108
|
+
<div key={index} className={css(inlineEditStyles.inlineEditInput)}>
|
|
109
|
+
{elem}
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
) : (
|
|
114
|
+
<div className={css(inlineEditStyles.inlineEditInput)}>{editingValue}</div>
|
|
115
|
+
)}
|
|
116
|
+
</Td>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
interface EditableRow {
|
|
121
|
+
data: CustomData;
|
|
122
|
+
columnNames: ColumnNames<CustomData>;
|
|
123
|
+
dataOptions?: CustomDataOptions;
|
|
124
|
+
saveChanges: (editedData: CustomData) => void;
|
|
125
|
+
ariaLabel: string;
|
|
126
|
+
rowIndex?: number;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const EditableRow: React.FunctionComponent<EditableRow> = ({
|
|
130
|
+
data,
|
|
131
|
+
columnNames,
|
|
132
|
+
dataOptions,
|
|
133
|
+
saveChanges,
|
|
134
|
+
ariaLabel,
|
|
135
|
+
rowIndex
|
|
136
|
+
}) => {
|
|
137
|
+
const [editable, setEditable] = React.useState(false);
|
|
138
|
+
const [editedData, setEditedData] = React.useState(data);
|
|
139
|
+
|
|
140
|
+
const inputRef = React.useRef();
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<Tr className={css(inlineEditStyles.inlineEdit, editable ? inlineEditStyles.modifiers.inlineEditable : '')}>
|
|
144
|
+
<EditableCell
|
|
145
|
+
dataLabel={columnNames.textInput}
|
|
146
|
+
staticValue={data.textInput}
|
|
147
|
+
editingValue={
|
|
148
|
+
<TextInput
|
|
149
|
+
aria-label={`${columnNames.textInput} ${ariaLabel}`}
|
|
150
|
+
ref={inputRef}
|
|
151
|
+
value={editedData.textInput}
|
|
152
|
+
onChange={(e) => setEditedData((data) => ({ ...data, textInput: (e.target as HTMLInputElement).value }))}
|
|
153
|
+
/>
|
|
154
|
+
}
|
|
155
|
+
/>
|
|
156
|
+
<EditableCell
|
|
157
|
+
dataLabel={columnNames.textInputDisabled}
|
|
158
|
+
staticValue={data.textInputDisabled}
|
|
159
|
+
editingValue={
|
|
160
|
+
<TextInput
|
|
161
|
+
aria-label={`${columnNames.textInputDisabled} ${ariaLabel}`}
|
|
162
|
+
isDisabled={true}
|
|
163
|
+
value={editedData.textInputDisabled ?? ''}
|
|
164
|
+
/>
|
|
165
|
+
}
|
|
166
|
+
/>
|
|
167
|
+
<EditableCell
|
|
168
|
+
dataLabel={columnNames.checkboxes}
|
|
169
|
+
staticValue={data.checkboxes.join(', ')}
|
|
170
|
+
role="group"
|
|
171
|
+
ariaLabel={`Checkbox group row ${rowIndex}`}
|
|
172
|
+
editingValue={dataOptions?.checkboxes.map((option) => {
|
|
173
|
+
const id = getUniqueId('checkbox');
|
|
174
|
+
return (
|
|
175
|
+
<Checkbox
|
|
176
|
+
key={id}
|
|
177
|
+
name={id}
|
|
178
|
+
id={id}
|
|
179
|
+
label={option}
|
|
180
|
+
isChecked={editedData.checkboxes.includes(option)}
|
|
181
|
+
onChange={(_e, checked) =>
|
|
182
|
+
setEditedData((data) => ({
|
|
183
|
+
...data,
|
|
184
|
+
checkboxes: checked ? [...data.checkboxes, option] : data.checkboxes.filter((item) => item !== option)
|
|
185
|
+
}))
|
|
186
|
+
}
|
|
187
|
+
/>
|
|
188
|
+
);
|
|
189
|
+
})}
|
|
190
|
+
/>
|
|
191
|
+
<EditableCell
|
|
192
|
+
dataLabel={columnNames.radios}
|
|
193
|
+
staticValue={data.radios}
|
|
194
|
+
ariaLabel={`Radio button group row ${rowIndex}`}
|
|
195
|
+
role="radiogroup"
|
|
196
|
+
editingValue={dataOptions?.radios.map((option) => {
|
|
197
|
+
const id = getUniqueId('radio');
|
|
198
|
+
return (
|
|
199
|
+
<Radio
|
|
200
|
+
key={id}
|
|
201
|
+
name={id}
|
|
202
|
+
id={id}
|
|
203
|
+
label={option}
|
|
204
|
+
isChecked={editedData.radios === option}
|
|
205
|
+
onChange={() => setEditedData((data) => ({ ...data, radios: option }))}
|
|
206
|
+
/>
|
|
207
|
+
);
|
|
208
|
+
})}
|
|
209
|
+
/>
|
|
210
|
+
<EditButtonsCell
|
|
211
|
+
onClick={(type) => {
|
|
212
|
+
type === 'edit' ? setEditable(true) : setEditable(false);
|
|
213
|
+
type === 'save' && saveChanges(editedData);
|
|
214
|
+
type === 'cancel' && setEditedData(data);
|
|
215
|
+
}}
|
|
216
|
+
rowAriaLabel={ariaLabel}
|
|
217
|
+
elementToFocusOnEditRef={inputRef}
|
|
218
|
+
/>
|
|
219
|
+
</Tr>
|
|
220
|
+
);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
interface CustomData {
|
|
224
|
+
textInput: string;
|
|
225
|
+
textInputDisabled: string | null;
|
|
226
|
+
checkboxes: string[];
|
|
227
|
+
radios: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface CustomDataOptions {
|
|
231
|
+
checkboxes: string[];
|
|
232
|
+
radios: string[];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
type ColumnNames<T> = { [K in keyof T]: string };
|
|
236
|
+
|
|
237
|
+
export const TableEditable: React.FunctionComponent = () => {
|
|
238
|
+
// In real usage, this data would come from some external source like an API via props.
|
|
239
|
+
const initialRows: CustomData[] = [
|
|
240
|
+
{
|
|
241
|
+
textInput: 'Editable text 1',
|
|
242
|
+
textInputDisabled: 'Non-editable text 1',
|
|
243
|
+
checkboxes: ['Option A'],
|
|
244
|
+
radios: 'Option A'
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
textInput: 'Editable text 2',
|
|
248
|
+
textInputDisabled: null,
|
|
249
|
+
checkboxes: [],
|
|
250
|
+
radios: 'Option B'
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
textInput: 'Editable text 3',
|
|
254
|
+
textInputDisabled: 'Non-editable text 3',
|
|
255
|
+
checkboxes: ['Option A', 'Option B'],
|
|
256
|
+
radios: 'Option A'
|
|
257
|
+
}
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
// List of all selectable options for some cells of initialRows
|
|
261
|
+
const initialRowsOptions: CustomDataOptions[] = [
|
|
262
|
+
{
|
|
263
|
+
checkboxes: ['Option A', 'Option B', 'Option C'],
|
|
264
|
+
radios: ['Option A', 'Option B']
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
checkboxes: ['Option A', 'Option B'],
|
|
268
|
+
radios: ['Option A', 'Option B', 'Option C']
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
checkboxes: ['Option A', 'Option B'],
|
|
272
|
+
radios: ['Option A', 'Option B']
|
|
273
|
+
}
|
|
274
|
+
];
|
|
275
|
+
|
|
276
|
+
const [rows, setRows] = React.useState(initialRows);
|
|
277
|
+
|
|
278
|
+
const columnNames: ColumnNames<CustomData> = {
|
|
279
|
+
textInput: 'Text input',
|
|
280
|
+
textInputDisabled: 'Disabled text input',
|
|
281
|
+
checkboxes: 'Checkboxes',
|
|
282
|
+
radios: 'Radios'
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return (
|
|
286
|
+
<Table aria-label="Editable table">
|
|
287
|
+
<Thead>
|
|
288
|
+
<Tr>
|
|
289
|
+
<Th>{columnNames.textInput}</Th>
|
|
290
|
+
<Th>{columnNames.textInputDisabled}</Th>
|
|
291
|
+
<Th>{columnNames.checkboxes}</Th>
|
|
292
|
+
<Th>{columnNames.radios}</Th>
|
|
293
|
+
<Th screenReaderText="Row edit actions" />
|
|
294
|
+
</Tr>
|
|
295
|
+
</Thead>
|
|
296
|
+
<Tbody>
|
|
297
|
+
{rows.map((data, index) => (
|
|
298
|
+
<EditableRow
|
|
299
|
+
key={index}
|
|
300
|
+
data={data}
|
|
301
|
+
rowIndex={index}
|
|
302
|
+
dataOptions={initialRowsOptions[index]}
|
|
303
|
+
columnNames={columnNames}
|
|
304
|
+
saveChanges={(editedRow) => {
|
|
305
|
+
setRows((rows) => rows.map((row, i) => (i === index ? editedRow : row)));
|
|
306
|
+
}}
|
|
307
|
+
ariaLabel={`row ${index + 1}`}
|
|
308
|
+
></EditableRow>
|
|
309
|
+
))}
|
|
310
|
+
</Tbody>
|
|
311
|
+
</Table>
|
|
312
|
+
);
|
|
313
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`Transformer functions selectable unselected 1`] = `
|
|
4
|
-
|
|
4
|
+
{
|
|
5
5
|
"children": <SelectColumn
|
|
6
6
|
aria-label="Select row 0"
|
|
7
7
|
checked={false}
|
|
@@ -17,7 +17,7 @@ Object {
|
|
|
17
17
|
`;
|
|
18
18
|
|
|
19
19
|
exports[`Transformer functions sortable asc 1`] = `
|
|
20
|
-
|
|
20
|
+
{
|
|
21
21
|
"aria-sort": "ascending",
|
|
22
22
|
"children": <SortColumn
|
|
23
23
|
isSortedBy={true}
|
|
@@ -225,7 +225,7 @@ export const TableColumnManagement: React.FunctionComponent = () => {
|
|
|
225
225
|
<Button key="save" variant="primary" onClick={onSave}>
|
|
226
226
|
Save
|
|
227
227
|
</Button>,
|
|
228
|
-
<Button key="cancel" variant="
|
|
228
|
+
<Button key="cancel" variant="link" onClick={handleModalToggle}>
|
|
229
229
|
Cancel
|
|
230
230
|
</Button>
|
|
231
231
|
]}
|
|
@@ -439,7 +439,7 @@ export const TableColumnManagementWithDraggable: React.FunctionComponent = () =>
|
|
|
439
439
|
<Button key="save" variant="primary" onClick={onSave}>
|
|
440
440
|
Save
|
|
441
441
|
</Button>,
|
|
442
|
-
<Button key="cancel" variant="
|
|
442
|
+
<Button key="cancel" variant="link" onClick={handleModalToggle}>
|
|
443
443
|
Cancel
|
|
444
444
|
</Button>
|
|
445
445
|
]}
|