@patternfly/react-data-view 5.1.2 → 5.1.4

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 (29) hide show
  1. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.d.ts +2 -0
  2. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.js +30 -8
  3. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.test.js +4 -0
  4. package/dist/cjs/DataViewTableTree/DataViewTableTree.d.ts +2 -0
  5. package/dist/cjs/DataViewTableTree/DataViewTableTree.js +4 -4
  6. package/dist/cjs/DataViewTableTree/DataViewTableTree.test.js +4 -0
  7. package/dist/cjs/DataViewToolbar/DataViewToolbar.d.ts +2 -0
  8. package/dist/cjs/DataViewToolbar/DataViewToolbar.js +2 -1
  9. package/dist/esm/DataViewTableBasic/DataViewTableBasic.d.ts +2 -0
  10. package/dist/esm/DataViewTableBasic/DataViewTableBasic.js +7 -5
  11. package/dist/esm/DataViewTableBasic/DataViewTableBasic.test.js +4 -0
  12. package/dist/esm/DataViewTableTree/DataViewTableTree.d.ts +2 -0
  13. package/dist/esm/DataViewTableTree/DataViewTableTree.js +5 -5
  14. package/dist/esm/DataViewTableTree/DataViewTableTree.test.js +4 -0
  15. package/dist/esm/DataViewToolbar/DataViewToolbar.d.ts +2 -0
  16. package/dist/esm/DataViewToolbar/DataViewToolbar.js +2 -1
  17. package/package.json +1 -1
  18. package/patternfly-docs/content/extensions/data-view/examples/Components/Components.md +9 -1
  19. package/patternfly-docs/content/extensions/data-view/examples/Components/DataViewTableEmptyExample.tsx +48 -0
  20. package/patternfly-docs/content/extensions/data-view/examples/Components/DataViewTableExample.tsx +22 -2
  21. package/patternfly-docs/content/extensions/data-view/examples/Components/DataViewTableTreeExample.tsx +11 -9
  22. package/src/DataViewTable/__snapshots__/DataViewTable.test.tsx.snap +6 -6
  23. package/src/DataViewTableBasic/DataViewTableBasic.test.tsx +7 -0
  24. package/src/DataViewTableBasic/DataViewTableBasic.tsx +14 -4
  25. package/src/DataViewTableBasic/__snapshots__/DataViewTableBasic.test.tsx.snap +85 -0
  26. package/src/DataViewTableTree/DataViewTableTree.test.tsx +7 -0
  27. package/src/DataViewTableTree/DataViewTableTree.tsx +14 -3
  28. package/src/DataViewTableTree/__snapshots__/DataViewTableTree.test.tsx.snap +91 -6
  29. package/src/DataViewToolbar/DataViewToolbar.tsx +4 -1
@@ -6,6 +6,8 @@ export interface DataViewTableBasicProps extends Omit<TableProps, 'onSelect' | '
6
6
  columns: DataViewTh[];
7
7
  /** Current page rows */
8
8
  rows: DataViewTr[];
9
+ /** Empty state to be displayed */
10
+ emptyState?: React.ReactNode;
9
11
  /** Custom OUIA ID */
10
12
  ouiaId?: string;
11
13
  }
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __rest = (this && this.__rest) || function (s, e) {
3
26
  var t = {};
4
27
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -10,27 +33,25 @@ var __rest = (this && this.__rest) || function (s, e) {
10
33
  }
11
34
  return t;
12
35
  };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
36
  Object.defineProperty(exports, "__esModule", { value: true });
17
37
  exports.DataViewTableBasic = void 0;
18
- const react_1 = __importDefault(require("react"));
38
+ const react_1 = __importStar(require("react"));
19
39
  const react_table_1 = require("@patternfly/react-table");
20
40
  const InternalContext_1 = require("../InternalContext");
21
41
  const DataViewTableHeader_1 = require("../DataViewTableHeader");
22
42
  const DataViewTable_1 = require("../DataViewTable");
23
43
  const DataViewTableBasic = (_a) => {
24
- var { columns, rows, ouiaId = 'DataViewTableBasic' } = _a, props = __rest(_a, ["columns", "rows", "ouiaId"]);
44
+ var { columns, rows, ouiaId = 'DataViewTableBasic', emptyState = null } = _a, props = __rest(_a, ["columns", "rows", "ouiaId", "emptyState"]);
25
45
  const { selection } = (0, InternalContext_1.useInternalContext)();
26
46
  const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
47
+ const isSelectable = (0, react_1.useMemo)(() => Boolean(onSelect && isSelected), [onSelect, isSelected]);
27
48
  return (react_1.default.createElement(react_table_1.Table, Object.assign({ "aria-label": "Data table", ouiaId: ouiaId }, props),
28
49
  react_1.default.createElement(DataViewTableHeader_1.DataViewTableHeader, { columns: columns, ouiaId: ouiaId }),
29
- react_1.default.createElement(react_table_1.Tbody, null, rows.map((row, rowIndex) => {
50
+ react_1.default.createElement(react_table_1.Tbody, null, (rows === null || rows === void 0 ? void 0 : rows.length) > 0 ? rows.map((row, rowIndex) => {
30
51
  var _a;
31
52
  const rowIsObject = (0, DataViewTable_1.isDataViewTrObject)(row);
32
53
  return (react_1.default.createElement(react_table_1.Tr, Object.assign({ key: rowIndex, ouiaId: `${ouiaId}-tr-${rowIndex}` }, (rowIsObject && ((_a = row === null || row === void 0 ? void 0 : row.props) !== null && _a !== void 0 ? _a : {}))),
33
- onSelect && isSelected && (react_1.default.createElement(react_table_1.Td, { key: `select-${rowIndex}`, select: {
54
+ isSelectable && (react_1.default.createElement(react_table_1.Td, { key: `select-${rowIndex}`, select: {
34
55
  rowIndex,
35
56
  onSelect: (_event, isSelecting) => {
36
57
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(isSelecting, rowIsObject ? row : [row]);
@@ -43,7 +64,8 @@ const DataViewTableBasic = (_a) => {
43
64
  const cellIsObject = (0, DataViewTable_1.isDataViewTdObject)(cell);
44
65
  return (react_1.default.createElement(react_table_1.Td, Object.assign({ key: colIndex }, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}` }), cellIsObject ? cell.cell : cell));
45
66
  })));
46
- }))));
67
+ }) : (react_1.default.createElement(react_table_1.Tr, { key: "empty", ouiaId: `${ouiaId}-tr-empty` },
68
+ react_1.default.createElement(react_table_1.Td, { colSpan: columns.length + Number(isSelectable) }, emptyState))))));
47
69
  };
48
70
  exports.DataViewTableBasic = DataViewTableBasic;
49
71
  exports.default = exports.DataViewTableBasic;
@@ -24,4 +24,8 @@ describe('DataViewTable component', () => {
24
24
  const { container } = (0, react_2.render)(react_1.default.createElement(DataViewTableBasic_1.DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, rows: rows }));
25
25
  expect(container).toMatchSnapshot();
26
26
  });
27
+ test('should render with an empty state', () => {
28
+ const { container } = (0, react_2.render)(react_1.default.createElement(DataViewTableBasic_1.DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, emptyState: "No data found", rows: [] }));
29
+ expect(container).toMatchSnapshot();
30
+ });
27
31
  });
@@ -6,6 +6,8 @@ export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'r
6
6
  columns: DataViewTh[];
7
7
  /** Current page rows */
8
8
  rows: DataViewTrTree[];
9
+ /** Empty state to be displayed */
10
+ emptyState?: React.ReactNode;
9
11
  /** Optional icon for the leaf rows */
10
12
  leafIcon?: React.ReactNode;
11
13
  /** Optional icon for the expanded parent rows */
@@ -55,7 +55,7 @@ const isNodeChecked = (node, isSelected) => {
55
55
  return allSelected;
56
56
  };
57
57
  const DataViewTableTree = (_a) => {
58
- var { columns, rows, leafIcon = null, expandedIcon = null, collapsedIcon = null, ouiaId = 'DataViewTableTree' } = _a, props = __rest(_a, ["columns", "rows", "leafIcon", "expandedIcon", "collapsedIcon", "ouiaId"]);
58
+ var { columns, rows, emptyState = null, leafIcon = null, expandedIcon = null, collapsedIcon = null, ouiaId = 'DataViewTableTree' } = _a, props = __rest(_a, ["columns", "rows", "emptyState", "leafIcon", "expandedIcon", "collapsedIcon", "ouiaId"]);
59
59
  const { selection } = (0, InternalContext_1.useInternalContext)();
60
60
  const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
61
61
  const [expandedNodeIds, setExpandedNodeIds] = react_1.default.useState([]);
@@ -92,7 +92,6 @@ const DataViewTableTree = (_a) => {
92
92
  'aria-posinset': posinset,
93
93
  'aria-setsize': (_b = (_a = node.children) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
94
94
  isChecked,
95
- ouiaId: `${ouiaId}-tree-toggle-${node.id}`,
96
95
  checkboxId: `checkbox_id_${(_c = node.id) === null || _c === void 0 ? void 0 : _c.toLowerCase().replace(/\s+/g, '_')}`,
97
96
  icon,
98
97
  },
@@ -101,7 +100,7 @@ const DataViewTableTree = (_a) => {
101
100
  ? renderRows(node.children, level + 1, 1, rowIndex + 1, !isExpanded || isHidden)
102
101
  : [];
103
102
  return [
104
- react_1.default.createElement(react_table_1.TreeRowWrapper, { key: node.id, row: { props: treeRow.props } }, node.row.map((cell, colIndex) => {
103
+ react_1.default.createElement(react_table_1.TreeRowWrapper, { key: node.id, row: { props: treeRow.props }, ouiaId: `${ouiaId}-tr-${rowIndex}` }, node.row.map((cell, colIndex) => {
105
104
  var _a;
106
105
  const cellIsObject = (0, DataViewTable_1.isDataViewTdObject)(cell);
107
106
  return (react_1.default.createElement(react_table_1.Td, Object.assign({ key: colIndex, treeRow: colIndex === 0 ? treeRow : undefined }, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}` }), cellIsObject ? cell.cell : cell));
@@ -114,7 +113,8 @@ const DataViewTableTree = (_a) => {
114
113
  }, [rows, expandedNodeIds, expandedDetailsNodeNames, leafIcon, expandedIcon, collapsedIcon, isSelected, onSelect, isSelectDisabled, ouiaId]);
115
114
  return (react_1.default.createElement(react_table_1.Table, Object.assign({ isTreeTable: true, "aria-label": "Data table", ouiaId: ouiaId }, props),
116
115
  react_1.default.createElement(DataViewTableHeader_1.DataViewTableHeader, { isTreeTable: true, columns: columns, ouiaId: ouiaId }),
117
- react_1.default.createElement(react_table_1.Tbody, null, nodes)));
116
+ react_1.default.createElement(react_table_1.Tbody, null, nodes.length > 0 ? nodes : (react_1.default.createElement(react_table_1.Tr, { key: "empty", ouiaId: `${ouiaId}-tr-empty` },
117
+ react_1.default.createElement(react_table_1.Td, { colSpan: columns.length }, emptyState))))));
118
118
  };
119
119
  exports.DataViewTableTree = DataViewTableTree;
120
120
  exports.default = exports.DataViewTableTree;
@@ -72,4 +72,8 @@ describe('DataViewTableTree component', () => {
72
72
  react_1.default.createElement(DataViewTable_1.DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, rows: rows, leafIcon: react_1.default.createElement(react_icons_1.LeafIcon, null), expandedIcon: react_1.default.createElement(react_icons_1.FolderOpenIcon, { "aria-hidden": true }), collapsedIcon: react_1.default.createElement(react_icons_1.FolderIcon, { "aria-hidden": true }) })));
73
73
  expect(container).toMatchSnapshot();
74
74
  });
75
+ test('should render tree table with an empty state', () => {
76
+ const { container } = (0, react_2.render)(react_1.default.createElement(DataViewTable_1.DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, emptyState: "No data found", rows: [] }));
77
+ expect(container).toMatchSnapshot();
78
+ });
75
79
  });
@@ -8,6 +8,8 @@ export interface DataViewToolbarProps extends PropsWithChildren {
8
8
  bulkSelect?: React.ReactNode;
9
9
  /** React component to display pagination */
10
10
  pagination?: React.ReactNode;
11
+ /** React component to display actions */
12
+ actions?: React.ReactNode;
11
13
  }
12
14
  export declare const DataViewToolbar: React.FC<DataViewToolbarProps>;
13
15
  export default DataViewToolbar;
@@ -18,10 +18,11 @@ exports.DataViewToolbar = void 0;
18
18
  const react_1 = __importDefault(require("react"));
19
19
  const react_core_1 = require("@patternfly/react-core");
20
20
  const DataViewToolbar = (_a) => {
21
- var { className, ouiaId = 'DataViewToolbar', bulkSelect, pagination, children } = _a, props = __rest(_a, ["className", "ouiaId", "bulkSelect", "pagination", "children"]);
21
+ var { className, ouiaId = 'DataViewToolbar', bulkSelect, actions = null, pagination, children } = _a, props = __rest(_a, ["className", "ouiaId", "bulkSelect", "actions", "pagination", "children"]);
22
22
  return (react_1.default.createElement(react_core_1.Toolbar, Object.assign({ ouiaId: ouiaId, className: className }, props),
23
23
  react_1.default.createElement(react_core_1.ToolbarContent, null,
24
24
  bulkSelect && (react_1.default.createElement(react_core_1.ToolbarItem, { "data-ouia-component-id": `${ouiaId}-bulk-select` }, bulkSelect)),
25
+ actions,
25
26
  pagination && (react_1.default.createElement(react_core_1.ToolbarItem, { variant: react_core_1.ToolbarItemVariant.pagination, "data-ouia-component-id": `${ouiaId}-pagination` }, pagination)),
26
27
  children)));
27
28
  };
@@ -6,6 +6,8 @@ export interface DataViewTableBasicProps extends Omit<TableProps, 'onSelect' | '
6
6
  columns: DataViewTh[];
7
7
  /** Current page rows */
8
8
  rows: DataViewTr[];
9
+ /** Empty state to be displayed */
10
+ emptyState?: React.ReactNode;
9
11
  /** Custom OUIA ID */
10
12
  ouiaId?: string;
11
13
  }
@@ -9,22 +9,23 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import React from 'react';
12
+ import React, { useMemo } from 'react';
13
13
  import { Table, Tbody, Td, Tr, } from '@patternfly/react-table';
14
14
  import { useInternalContext } from '../InternalContext';
15
15
  import { DataViewTableHeader } from '../DataViewTableHeader';
16
16
  import { isDataViewTdObject, isDataViewTrObject } from '../DataViewTable';
17
17
  export const DataViewTableBasic = (_a) => {
18
- var { columns, rows, ouiaId = 'DataViewTableBasic' } = _a, props = __rest(_a, ["columns", "rows", "ouiaId"]);
18
+ var { columns, rows, ouiaId = 'DataViewTableBasic', emptyState = null } = _a, props = __rest(_a, ["columns", "rows", "ouiaId", "emptyState"]);
19
19
  const { selection } = useInternalContext();
20
20
  const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
21
+ const isSelectable = useMemo(() => Boolean(onSelect && isSelected), [onSelect, isSelected]);
21
22
  return (React.createElement(Table, Object.assign({ "aria-label": "Data table", ouiaId: ouiaId }, props),
22
23
  React.createElement(DataViewTableHeader, { columns: columns, ouiaId: ouiaId }),
23
- React.createElement(Tbody, null, rows.map((row, rowIndex) => {
24
+ React.createElement(Tbody, null, (rows === null || rows === void 0 ? void 0 : rows.length) > 0 ? rows.map((row, rowIndex) => {
24
25
  var _a;
25
26
  const rowIsObject = isDataViewTrObject(row);
26
27
  return (React.createElement(Tr, Object.assign({ key: rowIndex, ouiaId: `${ouiaId}-tr-${rowIndex}` }, (rowIsObject && ((_a = row === null || row === void 0 ? void 0 : row.props) !== null && _a !== void 0 ? _a : {}))),
27
- onSelect && isSelected && (React.createElement(Td, { key: `select-${rowIndex}`, select: {
28
+ isSelectable && (React.createElement(Td, { key: `select-${rowIndex}`, select: {
28
29
  rowIndex,
29
30
  onSelect: (_event, isSelecting) => {
30
31
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(isSelecting, rowIsObject ? row : [row]);
@@ -37,6 +38,7 @@ export const DataViewTableBasic = (_a) => {
37
38
  const cellIsObject = isDataViewTdObject(cell);
38
39
  return (React.createElement(Td, Object.assign({ key: colIndex }, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}` }), cellIsObject ? cell.cell : cell));
39
40
  })));
40
- }))));
41
+ }) : (React.createElement(Tr, { key: "empty", ouiaId: `${ouiaId}-tr-empty` },
42
+ React.createElement(Td, { colSpan: columns.length + Number(isSelectable) }, emptyState))))));
41
43
  };
42
44
  export default DataViewTableBasic;
@@ -19,4 +19,8 @@ describe('DataViewTable component', () => {
19
19
  const { container } = render(React.createElement(DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, rows: rows }));
20
20
  expect(container).toMatchSnapshot();
21
21
  });
22
+ test('should render with an empty state', () => {
23
+ const { container } = render(React.createElement(DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, emptyState: "No data found", rows: [] }));
24
+ expect(container).toMatchSnapshot();
25
+ });
22
26
  });
@@ -6,6 +6,8 @@ export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'r
6
6
  columns: DataViewTh[];
7
7
  /** Current page rows */
8
8
  rows: DataViewTrTree[];
9
+ /** Empty state to be displayed */
10
+ emptyState?: React.ReactNode;
9
11
  /** Optional icon for the leaf rows */
10
12
  leafIcon?: React.ReactNode;
11
13
  /** Optional icon for the expanded parent rows */
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import React, { useMemo } from 'react';
13
- import { Table, Tbody, Td, TreeRowWrapper, } from '@patternfly/react-table';
13
+ import { Table, Tbody, Td, Tr, TreeRowWrapper, } from '@patternfly/react-table';
14
14
  import { useInternalContext } from '../InternalContext';
15
15
  import { DataViewTableHeader } from '../DataViewTableHeader';
16
16
  import { isDataViewTdObject } from '../DataViewTable';
@@ -29,7 +29,7 @@ const isNodeChecked = (node, isSelected) => {
29
29
  return allSelected;
30
30
  };
31
31
  export const DataViewTableTree = (_a) => {
32
- var { columns, rows, leafIcon = null, expandedIcon = null, collapsedIcon = null, ouiaId = 'DataViewTableTree' } = _a, props = __rest(_a, ["columns", "rows", "leafIcon", "expandedIcon", "collapsedIcon", "ouiaId"]);
32
+ var { columns, rows, emptyState = null, leafIcon = null, expandedIcon = null, collapsedIcon = null, ouiaId = 'DataViewTableTree' } = _a, props = __rest(_a, ["columns", "rows", "emptyState", "leafIcon", "expandedIcon", "collapsedIcon", "ouiaId"]);
33
33
  const { selection } = useInternalContext();
34
34
  const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
35
35
  const [expandedNodeIds, setExpandedNodeIds] = React.useState([]);
@@ -66,7 +66,6 @@ export const DataViewTableTree = (_a) => {
66
66
  'aria-posinset': posinset,
67
67
  'aria-setsize': (_b = (_a = node.children) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
68
68
  isChecked,
69
- ouiaId: `${ouiaId}-tree-toggle-${node.id}`,
70
69
  checkboxId: `checkbox_id_${(_c = node.id) === null || _c === void 0 ? void 0 : _c.toLowerCase().replace(/\s+/g, '_')}`,
71
70
  icon,
72
71
  },
@@ -75,7 +74,7 @@ export const DataViewTableTree = (_a) => {
75
74
  ? renderRows(node.children, level + 1, 1, rowIndex + 1, !isExpanded || isHidden)
76
75
  : [];
77
76
  return [
78
- React.createElement(TreeRowWrapper, { key: node.id, row: { props: treeRow.props } }, node.row.map((cell, colIndex) => {
77
+ React.createElement(TreeRowWrapper, { key: node.id, row: { props: treeRow.props }, ouiaId: `${ouiaId}-tr-${rowIndex}` }, node.row.map((cell, colIndex) => {
79
78
  var _a;
80
79
  const cellIsObject = isDataViewTdObject(cell);
81
80
  return (React.createElement(Td, Object.assign({ key: colIndex, treeRow: colIndex === 0 ? treeRow : undefined }, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}` }), cellIsObject ? cell.cell : cell));
@@ -88,6 +87,7 @@ export const DataViewTableTree = (_a) => {
88
87
  }, [rows, expandedNodeIds, expandedDetailsNodeNames, leafIcon, expandedIcon, collapsedIcon, isSelected, onSelect, isSelectDisabled, ouiaId]);
89
88
  return (React.createElement(Table, Object.assign({ isTreeTable: true, "aria-label": "Data table", ouiaId: ouiaId }, props),
90
89
  React.createElement(DataViewTableHeader, { isTreeTable: true, columns: columns, ouiaId: ouiaId }),
91
- React.createElement(Tbody, null, nodes)));
90
+ React.createElement(Tbody, null, nodes.length > 0 ? nodes : (React.createElement(Tr, { key: "empty", ouiaId: `${ouiaId}-tr-empty` },
91
+ React.createElement(Td, { colSpan: columns.length }, emptyState))))));
92
92
  };
93
93
  export default DataViewTableTree;
@@ -67,4 +67,8 @@ describe('DataViewTableTree component', () => {
67
67
  React.createElement(DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, rows: rows, leafIcon: React.createElement(LeafIcon, null), expandedIcon: React.createElement(FolderOpenIcon, { "aria-hidden": true }), collapsedIcon: React.createElement(FolderIcon, { "aria-hidden": true }) })));
68
68
  expect(container).toMatchSnapshot();
69
69
  });
70
+ test('should render tree table with an empty state', () => {
71
+ const { container } = render(React.createElement(DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, emptyState: "No data found", rows: [] }));
72
+ expect(container).toMatchSnapshot();
73
+ });
70
74
  });
@@ -8,6 +8,8 @@ export interface DataViewToolbarProps extends PropsWithChildren {
8
8
  bulkSelect?: React.ReactNode;
9
9
  /** React component to display pagination */
10
10
  pagination?: React.ReactNode;
11
+ /** React component to display actions */
12
+ actions?: React.ReactNode;
11
13
  }
12
14
  export declare const DataViewToolbar: React.FC<DataViewToolbarProps>;
13
15
  export default DataViewToolbar;
@@ -12,10 +12,11 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import React from 'react';
13
13
  import { Toolbar, ToolbarContent, ToolbarItem, ToolbarItemVariant } from '@patternfly/react-core';
14
14
  export const DataViewToolbar = (_a) => {
15
- var { className, ouiaId = 'DataViewToolbar', bulkSelect, pagination, children } = _a, props = __rest(_a, ["className", "ouiaId", "bulkSelect", "pagination", "children"]);
15
+ var { className, ouiaId = 'DataViewToolbar', bulkSelect, actions = null, pagination, children } = _a, props = __rest(_a, ["className", "ouiaId", "bulkSelect", "actions", "pagination", "children"]);
16
16
  return (React.createElement(Toolbar, Object.assign({ ouiaId: ouiaId, className: className }, props),
17
17
  React.createElement(ToolbarContent, null,
18
18
  bulkSelect && (React.createElement(ToolbarItem, { "data-ouia-component-id": `${ouiaId}-bulk-select` }, bulkSelect)),
19
+ actions,
19
20
  pagination && (React.createElement(ToolbarItem, { variant: ToolbarItemVariant.pagination, "data-ouia-component-id": `${ouiaId}-pagination` }, pagination)),
20
21
  children)));
21
22
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-data-view",
3
- "version": "5.1.2",
3
+ "version": "5.1.4",
4
4
  "description": "Data view used for Red Hat projects.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -14,7 +14,8 @@ sortValue: 4
14
14
  propComponents: ['DataViewToolbar', 'DataViewTableBasic', 'DataViewTableTree']
15
15
  sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
16
16
  ---
17
- import { FolderIcon, FolderOpenIcon, LeafIcon, ExclamationCircleIcon } from '@patternfly/react-icons';
17
+ import { Button, EmptyState, EmptyStateActions, EmptyStateBody, EmptyStateFooter, EmptyStateHeader, EmptyStateIcon } from '@patternfly/react-core';
18
+ import { CubesIcon, FolderIcon, FolderOpenIcon, LeafIcon, ExclamationCircleIcon } from '@patternfly/react-icons';
18
19
  import { BulkSelect } from '@patternfly/react-component-groups';
19
20
  import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
20
21
  import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
@@ -71,3 +72,10 @@ It is also possible to disable row selection using the `isSelectDisabled` functi
71
72
  ```js file="./DataViewTableTreeExample.tsx"
72
73
 
73
74
  ```
75
+
76
+ ### Empty state example
77
+ The data view table also supports displaying a custom empty state. You can pass it using the `emptyState` property and it will be displayed in case there are no rows to be rendered.
78
+
79
+ ```js file="./DataViewTableEmptyExample.tsx"
80
+
81
+ ```
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { DataViewTable, DataViewTr, DataViewTh } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
3
+ import { CubesIcon } from '@patternfly/react-icons';
4
+ import { Button, EmptyState, EmptyStateActions, EmptyStateBody, EmptyStateFooter, EmptyStateHeader, EmptyStateIcon } from '@patternfly/react-core';
5
+
6
+ interface Repository {
7
+ id: number;
8
+ name: string;
9
+ branches: string | null;
10
+ prs: string | null;
11
+ workspaces: string;
12
+ lastCommit: string;
13
+ }
14
+
15
+ const repositories: Repository[] = [];
16
+
17
+ // you can also pass props to Tr by returning { row: DataViewTd[], props: TrProps } }
18
+ const rows: DataViewTr[] = repositories.map((repository) => Object.values(repository));
19
+
20
+ const columns: DataViewTh[] = [ 'Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit' ];
21
+
22
+ const ouiaId = 'TableExample';
23
+
24
+ const emptyState = (
25
+ <EmptyState>
26
+ <EmptyStateHeader titleText="No data found" headingLevel="h4" icon={<EmptyStateIcon icon={CubesIcon} />} />
27
+ <EmptyStateBody>There are no matching data to be displayed.</EmptyStateBody>
28
+ <EmptyStateFooter>
29
+ <EmptyStateActions>
30
+ <Button variant="primary">Primary action</Button>
31
+ </EmptyStateActions>
32
+ <EmptyStateActions>
33
+ <Button variant="link">Multiple</Button>
34
+ <Button variant="link">Action Buttons</Button>
35
+ </EmptyStateActions>
36
+ </EmptyStateFooter>
37
+ </EmptyState>
38
+ );
39
+
40
+ export const BasicExample: React.FunctionComponent = () => (
41
+ <DataViewTable
42
+ aria-label='Repositories table'
43
+ ouiaId={ouiaId}
44
+ columns={columns}
45
+ rows={rows}
46
+ emptyState={emptyState}
47
+ />
48
+ );
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { DataViewTable, DataViewTr, DataViewTh } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
3
3
  import { ExclamationCircleIcon } from '@patternfly/react-icons';
4
4
  import { Button } from '@patternfly/react-core';
5
+ import { ActionsColumn } from '@patternfly/react-table';
5
6
 
6
7
  interface Repository {
7
8
  id: number;
@@ -21,6 +22,24 @@ const repositories: Repository[] = [
21
22
  { id: 6, name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
22
23
  ];
23
24
 
25
+ const rowActions = [
26
+ {
27
+ title: 'Some action',
28
+ onClick: () => console.log('clicked on Some action') // eslint-disable-line no-console
29
+ },
30
+ {
31
+ title: <div>Another action</div>,
32
+ onClick: () => console.log('clicked on Another action') // eslint-disable-line no-console
33
+ },
34
+ {
35
+ isSeparator: true
36
+ },
37
+ {
38
+ title: 'Third action',
39
+ onClick: () => console.log('clicked on Third action') // eslint-disable-line no-console
40
+ }
41
+ ];
42
+
24
43
  // you can also pass props to Tr by returning { row: DataViewTd[], props: TrProps } }
25
44
  const rows: DataViewTr[] = repositories.map(({ id, name, branches, prs, workspaces, lastCommit }) => [
26
45
  { id, cell: workspaces, props: { favorites: { isFavorited: true } } },
@@ -28,7 +47,8 @@ const rows: DataViewTr[] = repositories.map(({ id, name, branches, prs, workspac
28
47
  branches,
29
48
  prs,
30
49
  workspaces,
31
- lastCommit
50
+ lastCommit,
51
+ { cell: <ActionsColumn items={rowActions}/>, props: { isActionCell: true } },
32
52
  ]);
33
53
 
34
54
  const columns: DataViewTh[] = [
@@ -37,7 +57,7 @@ const columns: DataViewTh[] = [
37
57
  { cell: <>Branches<ExclamationCircleIcon className='pf-v5-u-ml-sm' color='var(--pf-v5-global--danger-color--100)'/></> },
38
58
  'Pull requests',
39
59
  { cell: 'Workspaces', props: { info: { tooltip: 'More information' } } },
40
- { cell: 'Last commit', props: { sort: { sortBy: {}, columnIndex: 4 } } }
60
+ { cell: 'Last commit', props: { sort: { sortBy: {}, columnIndex: 4 } } },
41
61
  ];
42
62
 
43
63
  const ouiaId = 'TableExample';
@@ -42,19 +42,13 @@ const buildRows = (repositories: Repository[]): DataViewTrTree[] => repositories
42
42
  ...(repo.children
43
43
  ? {
44
44
  children: buildRows(repo.children) // build rows for children
45
- }
45
+ }
46
46
  : {})
47
47
  }));
48
48
 
49
49
  const rows: DataViewTrTree[] = buildRows(repositories);
50
50
 
51
- const columns: DataViewTh[] = [
52
- 'Repositories',
53
- 'Branches',
54
- 'Pull requests',
55
- 'Workspaces',
56
- 'Last commit'
57
- ];
51
+ const columns: DataViewTh[] = [ 'Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit' ];
58
52
 
59
53
  const ouiaId = 'TreeTableExample';
60
54
 
@@ -63,7 +57,15 @@ export const BasicExample: React.FunctionComponent = () => {
63
57
 
64
58
  return (
65
59
  <DataView selection={selection}>
66
- <DataViewTable isTreeTable aria-label='Repositories table' ouiaId={ouiaId} columns={columns} rows={rows} leafIcon={<LeafIcon/>} expandedIcon={<FolderOpenIcon aria-hidden />} collapsedIcon={<FolderIcon aria-hidden />} />
60
+ <DataViewTable
61
+ isTreeTable
62
+ ouiaId={ouiaId}
63
+ columns={columns}
64
+ rows={rows}
65
+ leafIcon={<LeafIcon/>}
66
+ expandedIcon={<FolderOpenIcon aria-hidden />}
67
+ collapsedIcon={<FolderIcon aria-hidden />}
68
+ />
67
69
  </DataView>
68
70
  );
69
71
  }
@@ -395,7 +395,7 @@ exports[`DataViewTable component should render a tree table correctly 1`] = `
395
395
  aria-posinset="1"
396
396
  aria-setsize="2"
397
397
  class="pf-v5-c-table__tr"
398
- data-ouia-component-id="OUIA-Generated-TableRow-9"
398
+ data-ouia-component-id="TableExample-tr-0"
399
399
  data-ouia-component-type="PF5/TableRow"
400
400
  data-ouia-safe="true"
401
401
  >
@@ -519,7 +519,7 @@ exports[`DataViewTable component should render a tree table correctly 1`] = `
519
519
  aria-posinset="1"
520
520
  aria-setsize="0"
521
521
  class="pf-v5-c-table__tr"
522
- data-ouia-component-id="OUIA-Generated-TableRow-10"
522
+ data-ouia-component-id="TableExample-tr-1"
523
523
  data-ouia-component-type="PF5/TableRow"
524
524
  data-ouia-safe="true"
525
525
  hidden=""
@@ -611,7 +611,7 @@ exports[`DataViewTable component should render a tree table correctly 1`] = `
611
611
  aria-posinset="2"
612
612
  aria-setsize="0"
613
613
  class="pf-v5-c-table__tr"
614
- data-ouia-component-id="OUIA-Generated-TableRow-11"
614
+ data-ouia-component-id="TableExample-tr-2"
615
615
  data-ouia-component-type="PF5/TableRow"
616
616
  data-ouia-safe="true"
617
617
  hidden=""
@@ -703,7 +703,7 @@ exports[`DataViewTable component should render a tree table correctly 1`] = `
703
703
  aria-posinset="2"
704
704
  aria-setsize="1"
705
705
  class="pf-v5-c-table__tr"
706
- data-ouia-component-id="OUIA-Generated-TableRow-12"
706
+ data-ouia-component-id="TableExample-tr-3"
707
707
  data-ouia-component-type="PF5/TableRow"
708
708
  data-ouia-safe="true"
709
709
  >
@@ -827,7 +827,7 @@ exports[`DataViewTable component should render a tree table correctly 1`] = `
827
827
  aria-posinset="1"
828
828
  aria-setsize="0"
829
829
  class="pf-v5-c-table__tr"
830
- data-ouia-component-id="OUIA-Generated-TableRow-13"
830
+ data-ouia-component-id="TableExample-tr-4"
831
831
  data-ouia-component-type="PF5/TableRow"
832
832
  data-ouia-safe="true"
833
833
  hidden=""
@@ -919,7 +919,7 @@ exports[`DataViewTable component should render a tree table correctly 1`] = `
919
919
  aria-posinset="3"
920
920
  aria-setsize="0"
921
921
  class="pf-v5-c-table__tr"
922
- data-ouia-component-id="OUIA-Generated-TableRow-14"
922
+ data-ouia-component-id="TableExample-tr-5"
923
923
  data-ouia-component-type="PF5/TableRow"
924
924
  data-ouia-safe="true"
925
925
  >
@@ -34,4 +34,11 @@ describe('DataViewTable component', () => {
34
34
  );
35
35
  expect(container).toMatchSnapshot();
36
36
  });
37
+
38
+ test('should render with an empty state', () => {
39
+ const { container } = render(
40
+ <DataViewTableBasic aria-label='Repositories table' ouiaId={ouiaId} columns={columns} emptyState="No data found" rows={[]} />
41
+ );
42
+ expect(container).toMatchSnapshot();
43
+ });
37
44
  });
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import {
3
3
  Table,
4
4
  TableProps,
@@ -15,6 +15,8 @@ export interface DataViewTableBasicProps extends Omit<TableProps, 'onSelect' | '
15
15
  columns: DataViewTh[];
16
16
  /** Current page rows */
17
17
  rows: DataViewTr[];
18
+ /** Empty state to be displayed */
19
+ emptyState?: React.ReactNode;
18
20
  /** Custom OUIA ID */
19
21
  ouiaId?: string;
20
22
  }
@@ -23,20 +25,22 @@ export const DataViewTableBasic: React.FC<DataViewTableBasicProps> = ({
23
25
  columns,
24
26
  rows,
25
27
  ouiaId = 'DataViewTableBasic',
28
+ emptyState = null,
26
29
  ...props
27
30
  }: DataViewTableBasicProps) => {
28
31
  const { selection } = useInternalContext();
29
32
  const { onSelect, isSelected, isSelectDisabled } = selection ?? {};
33
+ const isSelectable = useMemo(() => Boolean(onSelect && isSelected), [ onSelect, isSelected ])
30
34
 
31
35
  return (
32
36
  <Table aria-label="Data table" ouiaId={ouiaId} {...props}>
33
37
  <DataViewTableHeader columns={columns} ouiaId={ouiaId} />
34
38
  <Tbody>
35
- {rows.map((row, rowIndex) => {
39
+ {rows?.length > 0 ? rows.map((row, rowIndex) => {
36
40
  const rowIsObject = isDataViewTrObject(row);
37
41
  return (
38
42
  <Tr key={rowIndex} ouiaId={`${ouiaId}-tr-${rowIndex}`} {...(rowIsObject && (row?.props ?? {}))}>
39
- {onSelect && isSelected && (
43
+ {isSelectable && (
40
44
  <Td
41
45
  key={`select-${rowIndex}`}
42
46
  select={{
@@ -62,7 +66,13 @@ export const DataViewTableBasic: React.FC<DataViewTableBasicProps> = ({
62
66
  )
63
67
  })}
64
68
  </Tr>
65
- )})}
69
+ )}) : (
70
+ <Tr key="empty" ouiaId={`${ouiaId}-tr-empty`}>
71
+ <Td colSpan={columns.length + Number(isSelectable)}>
72
+ {emptyState}
73
+ </Td>
74
+ </Tr>
75
+ )}
66
76
  </Tbody>
67
77
  </Table>
68
78
  );
@@ -322,3 +322,88 @@ exports[`DataViewTable component should render correctly 1`] = `
322
322
  </table>
323
323
  </div>
324
324
  `;
325
+
326
+ exports[`DataViewTable component should render with an empty state 1`] = `
327
+ <div>
328
+ <table
329
+ aria-label="Repositories table"
330
+ class="pf-v5-c-table pf-m-grid-md"
331
+ data-ouia-component-id="TableExample"
332
+ data-ouia-component-type="PF5/Table"
333
+ data-ouia-safe="true"
334
+ role="grid"
335
+ >
336
+ <thead
337
+ class="pf-v5-c-table__thead"
338
+ data-ouia-component-id="TableExample-thead"
339
+ >
340
+ <tr
341
+ class="pf-v5-c-table__tr"
342
+ data-ouia-component-id="TableExample-tr-head"
343
+ data-ouia-component-type="PF5/TableRow"
344
+ data-ouia-safe="true"
345
+ >
346
+ <th
347
+ class="pf-v5-c-table__th"
348
+ data-ouia-component-id="TableExample-th-0"
349
+ scope="col"
350
+ tabindex="-1"
351
+ >
352
+ Repositories
353
+ </th>
354
+ <th
355
+ class="pf-v5-c-table__th"
356
+ data-ouia-component-id="TableExample-th-1"
357
+ scope="col"
358
+ tabindex="-1"
359
+ >
360
+ Branches
361
+ </th>
362
+ <th
363
+ class="pf-v5-c-table__th"
364
+ data-ouia-component-id="TableExample-th-2"
365
+ scope="col"
366
+ tabindex="-1"
367
+ >
368
+ Pull requests
369
+ </th>
370
+ <th
371
+ class="pf-v5-c-table__th"
372
+ data-ouia-component-id="TableExample-th-3"
373
+ scope="col"
374
+ tabindex="-1"
375
+ >
376
+ Workspaces
377
+ </th>
378
+ <th
379
+ class="pf-v5-c-table__th"
380
+ data-ouia-component-id="TableExample-th-4"
381
+ scope="col"
382
+ tabindex="-1"
383
+ >
384
+ Last commit
385
+ </th>
386
+ </tr>
387
+ </thead>
388
+ <tbody
389
+ class="pf-v5-c-table__tbody"
390
+ role="rowgroup"
391
+ >
392
+ <tr
393
+ class="pf-v5-c-table__tr"
394
+ data-ouia-component-id="TableExample-tr-empty"
395
+ data-ouia-component-type="PF5/TableRow"
396
+ data-ouia-safe="true"
397
+ >
398
+ <td
399
+ class="pf-v5-c-table__td"
400
+ colspan="5"
401
+ tabindex="-1"
402
+ >
403
+ No data found
404
+ </td>
405
+ </tr>
406
+ </tbody>
407
+ </table>
408
+ </div>
409
+ `;
@@ -82,4 +82,11 @@ describe('DataViewTableTree component', () => {
82
82
  );
83
83
  expect(container).toMatchSnapshot();
84
84
  });
85
+
86
+ test('should render tree table with an empty state', () => {
87
+ const { container } = render(
88
+ <DataViewTable isTreeTable aria-label='Repositories table' ouiaId={ouiaId} columns={columns} emptyState="No data found" rows={[]} />
89
+ );
90
+ expect(container).toMatchSnapshot();
91
+ });
85
92
  });
@@ -5,6 +5,7 @@ import {
5
5
  Tbody,
6
6
  Td,
7
7
  TdProps,
8
+ Tr,
8
9
  TreeRowWrapper,
9
10
  } from '@patternfly/react-table';
10
11
  import { useInternalContext } from '../InternalContext';
@@ -34,6 +35,8 @@ export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'r
34
35
  columns: DataViewTh[];
35
36
  /** Current page rows */
36
37
  rows: DataViewTrTree[];
38
+ /** Empty state to be displayed */
39
+ emptyState?: React.ReactNode;
37
40
  /** Optional icon for the leaf rows */
38
41
  leafIcon?: React.ReactNode;
39
42
  /** Optional icon for the expanded parent rows */
@@ -47,6 +50,7 @@ export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'r
47
50
  export const DataViewTableTree: React.FC<DataViewTableTreeProps> = ({
48
51
  columns,
49
52
  rows,
53
+ emptyState = null,
50
54
  leafIcon = null,
51
55
  expandedIcon = null,
52
56
  collapsedIcon = null,
@@ -99,7 +103,6 @@ export const DataViewTableTree: React.FC<DataViewTableTreeProps> = ({
99
103
  'aria-posinset': posinset,
100
104
  'aria-setsize': node.children?.length ?? 0,
101
105
  isChecked,
102
- ouiaId: `${ouiaId}-tree-toggle-${node.id}`,
103
106
  checkboxId: `checkbox_id_${node.id?.toLowerCase().replace(/\s+/g, '_')}`,
104
107
  icon,
105
108
  },
@@ -110,7 +113,7 @@ export const DataViewTableTree: React.FC<DataViewTableTreeProps> = ({
110
113
  : [];
111
114
 
112
115
  return [
113
- <TreeRowWrapper key={node.id} row={{ props: treeRow.props }}>
116
+ <TreeRowWrapper key={node.id} row={{ props: treeRow.props }} ouiaId={`${ouiaId}-tr-${rowIndex}`}>
114
117
  {node.row.map((cell, colIndex) => {
115
118
  const cellIsObject = isDataViewTdObject(cell);
116
119
  return (
@@ -136,7 +139,15 @@ export const DataViewTableTree: React.FC<DataViewTableTreeProps> = ({
136
139
  return (
137
140
  <Table isTreeTable aria-label="Data table" ouiaId={ouiaId} {...props}>
138
141
  <DataViewTableHeader isTreeTable columns={columns} ouiaId={ouiaId} />
139
- <Tbody>{nodes}</Tbody>
142
+ <Tbody>
143
+ {nodes.length > 0 ? nodes : (
144
+ <Tr key="empty" ouiaId={`${ouiaId}-tr-empty`}>
145
+ <Td colSpan={columns.length}>
146
+ {emptyState}
147
+ </Td>
148
+ </Tr>
149
+ )}
150
+ </Tbody>
140
151
  </Table>
141
152
  );
142
153
  };
@@ -80,7 +80,7 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
80
80
  aria-posinset="1"
81
81
  aria-setsize="2"
82
82
  class="pf-v5-c-table__tr"
83
- data-ouia-component-id="OUIA-Generated-TableRow-2"
83
+ data-ouia-component-id="TreeTableExample-tr-0"
84
84
  data-ouia-component-type="PF5/TableRow"
85
85
  data-ouia-safe="true"
86
86
  >
@@ -244,7 +244,7 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
244
244
  aria-posinset="1"
245
245
  aria-setsize="0"
246
246
  class="pf-v5-c-table__tr"
247
- data-ouia-component-id="OUIA-Generated-TableRow-3"
247
+ data-ouia-component-id="TreeTableExample-tr-1"
248
248
  data-ouia-component-type="PF5/TableRow"
249
249
  data-ouia-safe="true"
250
250
  hidden=""
@@ -376,7 +376,7 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
376
376
  aria-posinset="2"
377
377
  aria-setsize="0"
378
378
  class="pf-v5-c-table__tr"
379
- data-ouia-component-id="OUIA-Generated-TableRow-4"
379
+ data-ouia-component-id="TreeTableExample-tr-2"
380
380
  data-ouia-component-type="PF5/TableRow"
381
381
  data-ouia-safe="true"
382
382
  hidden=""
@@ -508,7 +508,7 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
508
508
  aria-posinset="2"
509
509
  aria-setsize="1"
510
510
  class="pf-v5-c-table__tr"
511
- data-ouia-component-id="OUIA-Generated-TableRow-5"
511
+ data-ouia-component-id="TreeTableExample-tr-3"
512
512
  data-ouia-component-type="PF5/TableRow"
513
513
  data-ouia-safe="true"
514
514
  >
@@ -672,7 +672,7 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
672
672
  aria-posinset="1"
673
673
  aria-setsize="0"
674
674
  class="pf-v5-c-table__tr"
675
- data-ouia-component-id="OUIA-Generated-TableRow-6"
675
+ data-ouia-component-id="TreeTableExample-tr-4"
676
676
  data-ouia-component-type="PF5/TableRow"
677
677
  data-ouia-safe="true"
678
678
  hidden=""
@@ -804,7 +804,7 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
804
804
  aria-posinset="3"
805
805
  aria-setsize="0"
806
806
  class="pf-v5-c-table__tr"
807
- data-ouia-component-id="OUIA-Generated-TableRow-7"
807
+ data-ouia-component-id="TreeTableExample-tr-5"
808
808
  data-ouia-component-type="PF5/TableRow"
809
809
  data-ouia-safe="true"
810
810
  >
@@ -935,3 +935,88 @@ exports[`DataViewTableTree component should render the tree table correctly 1`]
935
935
  </div>
936
936
  </div>
937
937
  `;
938
+
939
+ exports[`DataViewTableTree component should render tree table with an empty state 1`] = `
940
+ <div>
941
+ <table
942
+ aria-label="Repositories table"
943
+ class="pf-v5-c-table pf-m-tree-view-grid-md pf-m-tree-view"
944
+ data-ouia-component-id="TreeTableExample"
945
+ data-ouia-component-type="PF5/Table"
946
+ data-ouia-safe="true"
947
+ role="treegrid"
948
+ >
949
+ <thead
950
+ class="pf-v5-c-table__thead"
951
+ data-ouia-component-id="TreeTableExample-thead"
952
+ >
953
+ <tr
954
+ class="pf-v5-c-table__tr"
955
+ data-ouia-component-id="TreeTableExample-tr-head"
956
+ data-ouia-component-type="PF5/TableRow"
957
+ data-ouia-safe="true"
958
+ >
959
+ <th
960
+ class="pf-v5-c-table__th"
961
+ data-ouia-component-id="TreeTableExample-th-0"
962
+ scope="col"
963
+ tabindex="-1"
964
+ >
965
+ Repositories
966
+ </th>
967
+ <th
968
+ class="pf-v5-c-table__th"
969
+ data-ouia-component-id="TreeTableExample-th-1"
970
+ scope="col"
971
+ tabindex="-1"
972
+ >
973
+ Branches
974
+ </th>
975
+ <th
976
+ class="pf-v5-c-table__th"
977
+ data-ouia-component-id="TreeTableExample-th-2"
978
+ scope="col"
979
+ tabindex="-1"
980
+ >
981
+ Pull requests
982
+ </th>
983
+ <th
984
+ class="pf-v5-c-table__th"
985
+ data-ouia-component-id="TreeTableExample-th-3"
986
+ scope="col"
987
+ tabindex="-1"
988
+ >
989
+ Workspaces
990
+ </th>
991
+ <th
992
+ class="pf-v5-c-table__th"
993
+ data-ouia-component-id="TreeTableExample-th-4"
994
+ scope="col"
995
+ tabindex="-1"
996
+ >
997
+ Last commit
998
+ </th>
999
+ </tr>
1000
+ </thead>
1001
+ <tbody
1002
+ class="pf-v5-c-table__tbody"
1003
+ role="rowgroup"
1004
+ >
1005
+ <tr
1006
+ class="pf-v5-c-table__tr"
1007
+ data-ouia-component-id="TreeTableExample-tr-empty"
1008
+ data-ouia-component-type="PF5/TableRow"
1009
+ data-ouia-safe="true"
1010
+ >
1011
+ <td
1012
+ class="pf-v5-c-table__td"
1013
+ colspan="5"
1014
+ tabindex="-1"
1015
+ >
1016
+ No data found
1017
+ </td>
1018
+ </tr>
1019
+ </tbody>
1020
+ </table>
1021
+ </div>
1022
+ `;
@@ -10,9 +10,11 @@ export interface DataViewToolbarProps extends PropsWithChildren {
10
10
  bulkSelect?: React.ReactNode;
11
11
  /** React component to display pagination */
12
12
  pagination?: React.ReactNode;
13
+ /** React component to display actions */
14
+ actions?: React.ReactNode;
13
15
  }
14
16
 
15
- export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, pagination, children, ...props }: DataViewToolbarProps) => (
17
+ export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions = null, pagination, children, ...props }: DataViewToolbarProps) => (
16
18
  <Toolbar ouiaId={ouiaId} className={className} {...props}>
17
19
  <ToolbarContent>
18
20
  {bulkSelect && (
@@ -20,6 +22,7 @@ export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, oui
20
22
  {bulkSelect}
21
23
  </ToolbarItem>
22
24
  )}
25
+ {actions}
23
26
  {pagination && (
24
27
  <ToolbarItem variant={ToolbarItemVariant.pagination} data-ouia-component-id={`${ouiaId}-pagination`}>
25
28
  {pagination}