@patternfly/react-data-view 6.4.0 → 6.5.0-prerelease.1

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 (79) hide show
  1. package/dist/cjs/DataViewTable/DataViewTable.d.ts +2 -1
  2. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.d.ts +11 -0
  3. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.js +46 -6
  4. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.test.js +47 -9
  5. package/dist/cjs/DataViewTextFilter/DataViewTextFilter.d.ts +2 -0
  6. package/dist/cjs/DataViewTextFilter/DataViewTextFilter.js +29 -1
  7. package/dist/cjs/DataViewTextFilter/DataViewTextFilter.test.d.ts +1 -1
  8. package/dist/cjs/DataViewTextFilter/DataViewTextFilter.test.js +83 -0
  9. package/dist/cjs/DataViewTh/DataViewTh.d.ts +4 -4
  10. package/dist/cjs/DataViewTh/DataViewTh.js +8 -1
  11. package/dist/cjs/DataViewTh/index.d.ts +2 -0
  12. package/dist/cjs/DataViewTh/index.js +23 -0
  13. package/dist/cjs/DataViewToolbar/DataViewToolbar.js +13 -1
  14. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.d.ts +26 -0
  15. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.js +229 -0
  16. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.test.d.ts +1 -0
  17. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.test.js +171 -0
  18. package/dist/cjs/DataViewTreeFilter/index.d.ts +2 -0
  19. package/dist/cjs/DataViewTreeFilter/index.js +23 -0
  20. package/dist/cjs/Hooks/selection.d.ts +8 -8
  21. package/dist/cjs/index.d.ts +6 -0
  22. package/dist/cjs/index.js +10 -1
  23. package/dist/dynamic/DataViewTh/package.json +1 -0
  24. package/dist/dynamic/DataViewTreeFilter/package.json +1 -0
  25. package/dist/dynamic-modules.json +62 -0
  26. package/dist/esm/DataViewTable/DataViewTable.d.ts +2 -1
  27. package/dist/esm/DataViewTableBasic/DataViewTableBasic.d.ts +11 -0
  28. package/dist/esm/DataViewTableBasic/DataViewTableBasic.js +48 -8
  29. package/dist/esm/DataViewTableBasic/DataViewTableBasic.test.js +45 -10
  30. package/dist/esm/DataViewTextFilter/DataViewTextFilter.d.ts +2 -0
  31. package/dist/esm/DataViewTextFilter/DataViewTextFilter.js +29 -1
  32. package/dist/esm/DataViewTextFilter/DataViewTextFilter.test.d.ts +1 -1
  33. package/dist/esm/DataViewTextFilter/DataViewTextFilter.test.js +84 -1
  34. package/dist/esm/DataViewTh/DataViewTh.d.ts +4 -4
  35. package/dist/esm/DataViewTh/DataViewTh.js +8 -1
  36. package/dist/esm/DataViewTh/index.d.ts +2 -0
  37. package/dist/esm/DataViewTh/index.js +2 -0
  38. package/dist/esm/DataViewToolbar/DataViewToolbar.js +13 -1
  39. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.d.ts +26 -0
  40. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.js +225 -0
  41. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.test.d.ts +1 -0
  42. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.test.js +166 -0
  43. package/dist/esm/DataViewTreeFilter/index.d.ts +2 -0
  44. package/dist/esm/DataViewTreeFilter/index.js +2 -0
  45. package/dist/esm/Hooks/selection.d.ts +8 -8
  46. package/dist/esm/index.d.ts +6 -0
  47. package/dist/esm/index.js +6 -0
  48. package/dist/tsconfig.tsbuildinfo +1 -1
  49. package/generate-fed-package-json.js +18 -0
  50. package/generate-index.js +2 -2
  51. package/package.json +6 -6
  52. package/patternfly-docs/content/extensions/data-view/examples/DataView/DataView.md +10 -4
  53. package/patternfly-docs/content/extensions/data-view/examples/DataView/PredefinedLayoutFullExample.tsx +2 -1
  54. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableExpandableExample.tsx +108 -0
  55. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableInteractiveExample.tsx +148 -0
  56. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableStickyExample.tsx +90 -0
  57. package/patternfly-docs/content/extensions/data-view/examples/Table/Table.md +63 -2
  58. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/FiltersExample.tsx +2 -1
  59. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/PaginationExample.tsx +1 -1
  60. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/Toolbar.md +9 -2
  61. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/TreeFilterExample.tsx +248 -0
  62. package/patternfly-docs/patternfly-docs.config.js +4 -1
  63. package/src/DataViewTable/DataViewTable.tsx +3 -1
  64. package/src/DataViewTable/__snapshots__/DataViewTable.test.tsx.snap +7 -7
  65. package/src/DataViewTableBasic/DataViewTableBasic.test.tsx +54 -12
  66. package/src/DataViewTableBasic/DataViewTableBasic.tsx +101 -10
  67. package/src/DataViewTableBasic/__snapshots__/DataViewTableBasic.test.tsx.snap +10 -10
  68. package/src/DataViewTextFilter/DataViewTextFilter.test.tsx +129 -0
  69. package/src/DataViewTextFilter/DataViewTextFilter.tsx +58 -22
  70. package/src/DataViewTh/DataViewTh.tsx +15 -7
  71. package/src/DataViewTh/index.ts +2 -0
  72. package/src/DataViewToolbar/DataViewToolbar.tsx +17 -2
  73. package/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap +288 -280
  74. package/src/DataViewTreeFilter/DataViewTreeFilter.test.tsx +222 -0
  75. package/src/DataViewTreeFilter/DataViewTreeFilter.tsx +361 -0
  76. package/src/DataViewTreeFilter/__snapshots__/DataViewTreeFilter.test.tsx.snap +199 -0
  77. package/src/DataViewTreeFilter/index.ts +2 -0
  78. package/src/Hooks/selection.ts +8 -8
  79. package/src/index.ts +9 -0
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataViewTreeFilter = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_core_1 = require("@patternfly/react-core");
6
+ const react_1 = require("react");
7
+ const react_jss_1 = require("react-jss");
8
+ /** This style is needed so the tree filter dropdown looks like the basic filter dropdow */
9
+ const useStyles = (0, react_jss_1.createUseStyles)({
10
+ dataViewTreeFilterTreeView: {
11
+ '& .pf-v6-c-tree-view__node::after': {
12
+ borderRadius: 0,
13
+ borderRightStyle: 'none',
14
+ borderLeftStyle: 'none'
15
+ },
16
+ '& .pf-v6-c-tree-view__content': {
17
+ borderRadius: 0
18
+ }
19
+ }
20
+ });
21
+ // Generic helper to collect items from tree based on predicate
22
+ const collectTreeItems = (items, predicate, leafOnly = false) => {
23
+ const collected = [];
24
+ const collect = (item) => {
25
+ var _a;
26
+ const isLeaf = !item.children || item.children.length === 0;
27
+ if (predicate(item) && (!leafOnly || isLeaf)) {
28
+ collected.push(item);
29
+ }
30
+ (_a = item.children) === null || _a === void 0 ? void 0 : _a.forEach(child => collect(child));
31
+ };
32
+ items.forEach(item => collect(item));
33
+ return collected;
34
+ };
35
+ // Helper function to get all checked items (not just leaf nodes)
36
+ const getAllCheckedItems = (items) => collectTreeItems(items, item => { var _a; return ((_a = item.checkProps) === null || _a === void 0 ? void 0 : _a.checked) === true; }, false);
37
+ // Get all checked leaf items (returns array of names)
38
+ const getAllCheckedLeafItems = (items) => collectTreeItems(items, item => { var _a; return ((_a = item.checkProps) === null || _a === void 0 ? void 0 : _a.checked) === true; }, true).map(item => String(item.name));
39
+ // Helper function to expand all nodes in the tree
40
+ const expandAllNodes = (items) => items.map(item => (Object.assign(Object.assign({}, item), { defaultExpanded: true, children: item.children ? expandAllNodes(item.children) : undefined })));
41
+ // Helper function to set pre-selected items
42
+ const setPreSelectedItems = (items, selectedIds) => items.map(item => {
43
+ var _a, _b;
44
+ const isSelected = selectedIds.includes(String(item.id));
45
+ const hasSelectedChildren = (_b = (_a = item.children) === null || _a === void 0 ? void 0 : _a.some(child => selectedIds.includes(String(child.id)))) !== null && _b !== void 0 ? _b : false;
46
+ return Object.assign(Object.assign({}, item), { checkProps: item.checkProps ? Object.assign(Object.assign({}, item.checkProps), { checked: isSelected || hasSelectedChildren }) : undefined, children: item.children ? setPreSelectedItems(item.children, selectedIds) : undefined });
47
+ });
48
+ // Helper function to uncheck all items recursively
49
+ const uncheckRecursive = (items) => items.map(item => (Object.assign(Object.assign({}, item), { checkProps: item.checkProps ? Object.assign(Object.assign({}, item.checkProps), { checked: false }) : undefined, children: item.children ? uncheckRecursive(item.children) : undefined })));
50
+ const DataViewTreeFilter = ({ filterId, title, value = [], onChange, showToolbarItem, ouiaId = 'DataViewTreeFilter', items, defaultExpanded = false, onSelect, defaultSelected = [] }) => {
51
+ const classes = useStyles();
52
+ const [isOpen, setIsOpen] = (0, react_1.useState)(false);
53
+ const [treeData, setTreeData] = (0, react_1.useState)(items || []);
54
+ const menuRef = (0, react_1.useRef)(null);
55
+ const isInitialMount = (0, react_1.useRef)(true);
56
+ const hasCalledInitialOnChange = (0, react_1.useRef)(false);
57
+ // Initialize tree data with defaultExpanded and defaultSelected (only on first mount)
58
+ (0, react_1.useEffect)(() => {
59
+ if (!items) {
60
+ return;
61
+ }
62
+ let initializedData = [...items];
63
+ // Apply default expansion
64
+ if (defaultExpanded) {
65
+ initializedData = expandAllNodes(initializedData);
66
+ }
67
+ // Apply pre-selected items only on initial mount
68
+ if (isInitialMount.current && defaultSelected.length > 0) {
69
+ initializedData = setPreSelectedItems(initializedData, defaultSelected);
70
+ }
71
+ setTreeData(initializedData);
72
+ if (isInitialMount.current) {
73
+ isInitialMount.current = false;
74
+ }
75
+ }, [items, defaultExpanded]);
76
+ // Call onChange and onSelect after tree data is initialized with default selections
77
+ (0, react_1.useEffect)(() => {
78
+ if (!hasCalledInitialOnChange.current && defaultSelected.length > 0 && treeData.length > 0) {
79
+ const selectedValues = getAllCheckedLeafItems(treeData);
80
+ // Only call if there are actually selected values
81
+ if (selectedValues.length > 0) {
82
+ // Calculate both values synchronously before calling callbacks
83
+ const selectedItems = getAllCheckedItems(treeData);
84
+ // useEffect already runs after render, so this is safe
85
+ if (onChange) {
86
+ onChange(undefined, selectedValues);
87
+ }
88
+ if (onSelect) {
89
+ onSelect(selectedItems);
90
+ }
91
+ hasCalledInitialOnChange.current = true;
92
+ }
93
+ }
94
+ }, [treeData, onChange, onSelect, defaultSelected.length]);
95
+ // Sync tree checkboxes when value prop changes (when clearAllFilters is called)
96
+ (0, react_1.useEffect)(() => {
97
+ if (value.length === 0) {
98
+ setTreeData(currentTreeData => {
99
+ if (currentTreeData.length === 0) {
100
+ return currentTreeData;
101
+ }
102
+ const currentCheckedItems = getAllCheckedLeafItems(currentTreeData);
103
+ // Only update if there are checked items that need to be unchecked
104
+ if (currentCheckedItems.length > 0) {
105
+ return uncheckRecursive(currentTreeData);
106
+ }
107
+ return currentTreeData;
108
+ });
109
+ }
110
+ }, [value]);
111
+ // Check if all children are checked (recursive)
112
+ const areAllChildrenChecked = (item) => {
113
+ var _a, _b;
114
+ if (!((_a = item.children) === null || _a === void 0 ? void 0 : _a.length)) {
115
+ return ((_b = item.checkProps) === null || _b === void 0 ? void 0 : _b.checked) === true;
116
+ }
117
+ return item.children.every(child => areAllChildrenChecked(child));
118
+ };
119
+ // Check if some children are checked (recursive)
120
+ const areSomeChildrenChecked = (item) => {
121
+ var _a, _b;
122
+ if (!((_a = item.children) === null || _a === void 0 ? void 0 : _a.length)) {
123
+ return ((_b = item.checkProps) === null || _b === void 0 ? void 0 : _b.checked) === true;
124
+ }
125
+ return item.children.some(child => areSomeChildrenChecked(child));
126
+ };
127
+ // Find tree item by name
128
+ const findItemByName = (items, name) => {
129
+ for (const item of items) {
130
+ if (item.name === name) {
131
+ return item;
132
+ }
133
+ if (item.children) {
134
+ const found = findItemByName(item.children, name);
135
+ if (found) {
136
+ return found;
137
+ }
138
+ }
139
+ }
140
+ return null;
141
+ };
142
+ // Find parent item by child ID
143
+ const findParentById = (items, childId) => {
144
+ var _a;
145
+ for (const item of items) {
146
+ if ((_a = item.children) === null || _a === void 0 ? void 0 : _a.some(child => child.id === childId)) {
147
+ return item;
148
+ }
149
+ if (item.children) {
150
+ const found = findParentById(item.children, childId);
151
+ if (found) {
152
+ return found;
153
+ }
154
+ }
155
+ }
156
+ return null;
157
+ };
158
+ // Update parent checkbox states based on children (recursive)
159
+ const onCheckParentHandle = (childId) => {
160
+ const parent = findParentById(treeData, childId);
161
+ if (!parent) {
162
+ return;
163
+ }
164
+ if (parent.checkProps) {
165
+ const allChildrenChecked = areAllChildrenChecked(parent);
166
+ const someChildrenChecked = areSomeChildrenChecked(parent);
167
+ if (allChildrenChecked) {
168
+ parent.checkProps.checked = true;
169
+ }
170
+ else if (someChildrenChecked) {
171
+ parent.checkProps.checked = null;
172
+ }
173
+ else {
174
+ parent.checkProps.checked = false;
175
+ }
176
+ }
177
+ if (parent.id) {
178
+ onCheckParentHandle(parent.id);
179
+ }
180
+ };
181
+ // Check/uncheck item and all its children (recursive)
182
+ const onCheckHandle = (treeViewItem, checked) => {
183
+ var _a;
184
+ if (treeViewItem.checkProps) {
185
+ treeViewItem.checkProps.checked = checked;
186
+ }
187
+ (_a = treeViewItem.children) === null || _a === void 0 ? void 0 : _a.forEach(child => onCheckHandle(child, checked));
188
+ };
189
+ // Handle checkbox change event
190
+ const onCheck = (event, treeViewItem) => {
191
+ const checked = event.target.checked;
192
+ onCheckHandle(treeViewItem, checked);
193
+ if (treeViewItem.id) {
194
+ onCheckParentHandle(treeViewItem.id);
195
+ }
196
+ setTreeData(prev => [...prev]);
197
+ const selectedValues = getAllCheckedLeafItems(treeData);
198
+ onChange === null || onChange === void 0 ? void 0 : onChange(event, selectedValues);
199
+ if (onSelect) {
200
+ const selectedItems = getAllCheckedItems(treeData);
201
+ onSelect(selectedItems);
202
+ }
203
+ };
204
+ // Clear a specific filter by name (when label chip is removed)
205
+ const onFilterSelectorClear = (itemName) => {
206
+ const treeViewItem = findItemByName(treeData, itemName);
207
+ if (!treeViewItem) {
208
+ return;
209
+ }
210
+ onCheckHandle(treeViewItem, false);
211
+ if (treeViewItem.id) {
212
+ onCheckParentHandle(treeViewItem.id);
213
+ }
214
+ };
215
+ // Uncheck all items in the tree
216
+ const uncheckAllItems = () => {
217
+ const updatedTreeData = uncheckRecursive(treeData);
218
+ setTreeData(updatedTreeData);
219
+ onChange === null || onChange === void 0 ? void 0 : onChange(undefined, []);
220
+ };
221
+ const dropdown = ((0, jsx_runtime_1.jsx)(react_core_1.Dropdown, { ref: menuRef, isOpen: isOpen, onOpenChange: (isOpen) => setIsOpen(isOpen), toggle: (toggleRef) => ((0, jsx_runtime_1.jsx)(react_core_1.MenuToggle, { ref: toggleRef, onClick: () => setIsOpen(!isOpen), isExpanded: isOpen, children: title })), ouiaId: ouiaId, shouldFocusToggleOnSelect: true, children: (0, jsx_runtime_1.jsx)(react_core_1.TreeView, { hasAnimations: true, data: treeData, onCheck: onCheck, hasCheckboxes: true, className: classes.dataViewTreeFilterTreeView }) }));
222
+ return ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarFilter, { "data-ouia-component-id": ouiaId, labels: value.map(item => ({ key: item, node: item })), deleteLabel: (_, label) => {
223
+ const labelKey = typeof label === 'string' ? label : label.key;
224
+ onChange === null || onChange === void 0 ? void 0 : onChange(undefined, value.filter(item => item !== labelKey));
225
+ onFilterSelectorClear(labelKey);
226
+ }, deleteLabelGroup: uncheckAllItems, categoryName: title, showToolbarItem: showToolbarItem, children: dropdown }, filterId));
227
+ };
228
+ exports.DataViewTreeFilter = DataViewTreeFilter;
229
+ exports.default = exports.DataViewTreeFilter;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const jsx_runtime_1 = require("react/jsx-runtime");
16
+ const react_1 = require("@testing-library/react");
17
+ require("@testing-library/jest-dom");
18
+ const user_event_1 = __importDefault(require("@testing-library/user-event"));
19
+ const DataViewTreeFilter_1 = __importDefault(require("./DataViewTreeFilter"));
20
+ const DataViewToolbar_1 = __importDefault(require("../DataViewToolbar"));
21
+ describe('DataViewTreeFilter component', () => {
22
+ const treeItems = [
23
+ {
24
+ name: 'Linux',
25
+ id: 'os-linux',
26
+ checkProps: { 'aria-label': 'linux-check', checked: false },
27
+ children: [
28
+ {
29
+ name: 'Ubuntu 22.04',
30
+ id: 'os-ubuntu',
31
+ checkProps: { checked: false }
32
+ },
33
+ {
34
+ name: 'RHEL 9',
35
+ id: 'os-rhel',
36
+ checkProps: { checked: false }
37
+ },
38
+ {
39
+ name: 'Debian 12',
40
+ id: 'os-debian',
41
+ checkProps: { checked: false }
42
+ },
43
+ {
44
+ name: 'CentOS 8',
45
+ id: 'os-centos',
46
+ checkProps: { checked: false }
47
+ },
48
+ {
49
+ name: 'Fedora 38',
50
+ id: 'os-fedora',
51
+ checkProps: { checked: false }
52
+ }
53
+ ],
54
+ defaultExpanded: true
55
+ },
56
+ {
57
+ name: 'Windows',
58
+ id: 'os-windows',
59
+ checkProps: { 'aria-label': 'windows-check', checked: false },
60
+ children: [
61
+ {
62
+ name: 'Windows Server 2022',
63
+ id: 'os-windows-2022',
64
+ checkProps: { checked: false }
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ name: 'macOS',
70
+ id: 'os-macos',
71
+ checkProps: { 'aria-label': 'macos-check', checked: false },
72
+ children: [
73
+ {
74
+ name: 'macOS Ventura',
75
+ id: 'os-macos-ventura',
76
+ checkProps: { checked: false }
77
+ },
78
+ {
79
+ name: 'macOS Sonoma',
80
+ id: 'os-macos-sonoma',
81
+ checkProps: { checked: false }
82
+ }
83
+ ]
84
+ }
85
+ ];
86
+ const defaultProps = {
87
+ filterId: 'test-tree-filter',
88
+ title: 'Test Tree Filter',
89
+ value: ['Linux'],
90
+ items: treeItems
91
+ };
92
+ beforeEach(() => {
93
+ jest.clearAllMocks();
94
+ });
95
+ it('should render correctly', () => {
96
+ const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTreeFilter_1.default, Object.assign({}, defaultProps)) }));
97
+ expect(container).toMatchSnapshot();
98
+ });
99
+ describe('defaultExpanded', () => {
100
+ it('should have expanded items by default', () => __awaiter(void 0, void 0, void 0, function* () {
101
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTreeFilter_1.default, { filterId: "os", title: "Operating System", items: treeItems, defaultExpanded: true }) }));
102
+ const openMenu = react_1.screen.getByRole('button', { name: /operating system/i });
103
+ yield user_event_1.default.click(openMenu);
104
+ yield (0, react_1.waitFor)(() => {
105
+ const node = react_1.screen.getByText('Ubuntu 22.04');
106
+ expect(node).toHaveClass('pf-v6-c-tree-view__node-text');
107
+ expect(node).toBeInTheDocument();
108
+ });
109
+ }));
110
+ });
111
+ describe('onChange callback', () => {
112
+ it('onChange should be called on toggle of node', () => __awaiter(void 0, void 0, void 0, function* () {
113
+ const mockOnChange = jest.fn();
114
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTreeFilter_1.default, { filterId: "os", title: "Operating System", items: treeItems, defaultExpanded: true, onChange: mockOnChange }) }));
115
+ const openMenu = react_1.screen.getByRole('button', { name: /operating system/i });
116
+ yield user_event_1.default.click(openMenu);
117
+ yield (0, react_1.waitFor)(() => {
118
+ const node = react_1.screen.getByText('Ubuntu 22.04');
119
+ expect(node).toBeInTheDocument();
120
+ });
121
+ const node = react_1.screen.getByText('Ubuntu 22.04');
122
+ yield user_event_1.default.click(node);
123
+ yield (0, react_1.waitFor)(() => {
124
+ expect(mockOnChange).toHaveBeenCalled();
125
+ });
126
+ }));
127
+ });
128
+ describe('onSelect callback', () => {
129
+ it('onSelect should return list of selected items when item is selected', () => __awaiter(void 0, void 0, void 0, function* () {
130
+ const mockOnSelect = jest.fn();
131
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTreeFilter_1.default, { filterId: "os", title: "Operating System", items: treeItems, defaultExpanded: true, onSelect: mockOnSelect }) }));
132
+ const openMenu = react_1.screen.getByRole('button', { name: /operating system/i });
133
+ yield user_event_1.default.click(openMenu);
134
+ yield (0, react_1.waitFor)(() => {
135
+ const node = react_1.screen.getByText('Ubuntu 22.04');
136
+ expect(node).toBeInTheDocument();
137
+ });
138
+ const node = react_1.screen.getByText('Ubuntu 22.04');
139
+ yield user_event_1.default.click(node);
140
+ yield (0, react_1.waitFor)(() => {
141
+ expect(mockOnSelect).toHaveBeenCalled();
142
+ expect(mockOnSelect).toHaveBeenCalledWith(expect.arrayContaining([
143
+ expect.objectContaining({
144
+ name: 'Ubuntu 22.04',
145
+ id: 'os-ubuntu'
146
+ })
147
+ ]));
148
+ });
149
+ }));
150
+ });
151
+ describe('rendering all items', () => {
152
+ it('all tree items should be rendered', () => __awaiter(void 0, void 0, void 0, function* () {
153
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTreeFilter_1.default, { filterId: "os", title: "Operating System", items: treeItems, defaultExpanded: true }) }));
154
+ const openMenu = react_1.screen.getByRole('button', { name: /operating system/i });
155
+ yield user_event_1.default.click(openMenu);
156
+ yield (0, react_1.waitFor)(() => {
157
+ expect(react_1.screen.getByText('Linux')).toBeInTheDocument();
158
+ expect(react_1.screen.getByText('Windows')).toBeInTheDocument();
159
+ expect(react_1.screen.getByText('macOS')).toBeInTheDocument();
160
+ expect(react_1.screen.getByText('Ubuntu 22.04')).toBeInTheDocument();
161
+ expect(react_1.screen.getByText('RHEL 9')).toBeInTheDocument();
162
+ expect(react_1.screen.getByText('Debian 12')).toBeInTheDocument();
163
+ expect(react_1.screen.getByText('CentOS 8')).toBeInTheDocument();
164
+ expect(react_1.screen.getByText('Fedora 38')).toBeInTheDocument();
165
+ expect(react_1.screen.getByText('Windows Server 2022')).toBeInTheDocument();
166
+ expect(react_1.screen.getByText('macOS Ventura')).toBeInTheDocument();
167
+ expect(react_1.screen.getByText('macOS Sonoma')).toBeInTheDocument();
168
+ });
169
+ }));
170
+ });
171
+ });
@@ -0,0 +1,2 @@
1
+ export { default } from './DataViewTreeFilter';
2
+ export * from './DataViewTreeFilter';
@@ -0,0 +1,23 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.default = void 0;
21
+ var DataViewTreeFilter_1 = require("./DataViewTreeFilter");
22
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(DataViewTreeFilter_1).default; } });
23
+ __exportStar(require("./DataViewTreeFilter"), exports);
@@ -1,12 +1,12 @@
1
- export interface UseDataViewSelectionProps {
1
+ export interface UseDataViewSelectionProps<T = any> {
2
2
  /** Function to compare items when checking if item is selected */
3
- matchOption: (item: any, another: any) => boolean;
3
+ matchOption: (item: T, another: T) => boolean;
4
4
  /** Array of initially selected entries */
5
- initialSelected?: (any)[];
5
+ initialSelected?: (T)[];
6
6
  }
7
- export declare const useDataViewSelection: (props?: UseDataViewSelectionProps) => {
8
- selected: any[];
9
- onSelect: (isSelecting: boolean, items?: any[] | any) => void;
10
- isSelected: (item: any) => boolean;
11
- setSelected: (items: any[]) => void;
7
+ export declare const useDataViewSelection: <T = any>(props?: UseDataViewSelectionProps<T>) => {
8
+ selected: T[];
9
+ onSelect: (isSelecting: boolean, items?: T[] | T) => void;
10
+ isSelected: (item: T) => boolean;
11
+ setSelected: (items: T[]) => void;
12
12
  };
@@ -1,8 +1,12 @@
1
1
  export { default as InternalContext } from './InternalContext';
2
2
  export * from './InternalContext';
3
3
  export * from './Hooks';
4
+ export { default as DataViewTreeFilter } from './DataViewTreeFilter';
5
+ export * from './DataViewTreeFilter';
4
6
  export { default as DataViewToolbar } from './DataViewToolbar';
5
7
  export * from './DataViewToolbar';
8
+ export { default as DataViewTh } from './DataViewTh';
9
+ export * from './DataViewTh';
6
10
  export { default as DataViewTextFilter } from './DataViewTextFilter';
7
11
  export * from './DataViewTextFilter';
8
12
  export { default as DataViewTableTree } from './DataViewTableTree';
@@ -13,6 +17,8 @@ export { default as DataViewTableBasic } from './DataViewTableBasic';
13
17
  export * from './DataViewTableBasic';
14
18
  export { default as DataViewTable } from './DataViewTable';
15
19
  export * from './DataViewTable';
20
+ export { default as DataViewFilters } from './DataViewFilters';
21
+ export * from './DataViewFilters';
16
22
  export { default as DataViewEventsContext } from './DataViewEventsContext';
17
23
  export * from './DataViewEventsContext';
18
24
  export { default as DataViewCheckboxFilter } from './DataViewCheckboxFilter';
package/dist/cjs/index.js CHANGED
@@ -18,14 +18,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.DataView = exports.DataViewCheckboxFilter = exports.DataViewEventsContext = exports.DataViewTable = exports.DataViewTableBasic = exports.DataViewTableHead = exports.DataViewTableTree = exports.DataViewTextFilter = exports.DataViewToolbar = exports.InternalContext = void 0;
21
+ exports.DataView = exports.DataViewCheckboxFilter = exports.DataViewEventsContext = exports.DataViewFilters = exports.DataViewTable = exports.DataViewTableBasic = exports.DataViewTableHead = exports.DataViewTableTree = exports.DataViewTextFilter = exports.DataViewTh = exports.DataViewToolbar = exports.DataViewTreeFilter = exports.InternalContext = void 0;
22
22
  var InternalContext_1 = require("./InternalContext");
23
23
  Object.defineProperty(exports, "InternalContext", { enumerable: true, get: function () { return __importDefault(InternalContext_1).default; } });
24
24
  __exportStar(require("./InternalContext"), exports);
25
25
  __exportStar(require("./Hooks"), exports);
26
+ var DataViewTreeFilter_1 = require("./DataViewTreeFilter");
27
+ Object.defineProperty(exports, "DataViewTreeFilter", { enumerable: true, get: function () { return __importDefault(DataViewTreeFilter_1).default; } });
28
+ __exportStar(require("./DataViewTreeFilter"), exports);
26
29
  var DataViewToolbar_1 = require("./DataViewToolbar");
27
30
  Object.defineProperty(exports, "DataViewToolbar", { enumerable: true, get: function () { return __importDefault(DataViewToolbar_1).default; } });
28
31
  __exportStar(require("./DataViewToolbar"), exports);
32
+ var DataViewTh_1 = require("./DataViewTh");
33
+ Object.defineProperty(exports, "DataViewTh", { enumerable: true, get: function () { return __importDefault(DataViewTh_1).default; } });
34
+ __exportStar(require("./DataViewTh"), exports);
29
35
  var DataViewTextFilter_1 = require("./DataViewTextFilter");
30
36
  Object.defineProperty(exports, "DataViewTextFilter", { enumerable: true, get: function () { return __importDefault(DataViewTextFilter_1).default; } });
31
37
  __exportStar(require("./DataViewTextFilter"), exports);
@@ -41,6 +47,9 @@ __exportStar(require("./DataViewTableBasic"), exports);
41
47
  var DataViewTable_1 = require("./DataViewTable");
42
48
  Object.defineProperty(exports, "DataViewTable", { enumerable: true, get: function () { return __importDefault(DataViewTable_1).default; } });
43
49
  __exportStar(require("./DataViewTable"), exports);
50
+ var DataViewFilters_1 = require("./DataViewFilters");
51
+ Object.defineProperty(exports, "DataViewFilters", { enumerable: true, get: function () { return __importDefault(DataViewFilters_1).default; } });
52
+ __exportStar(require("./DataViewFilters"), exports);
44
53
  var DataViewEventsContext_1 = require("./DataViewEventsContext");
45
54
  Object.defineProperty(exports, "DataViewEventsContext", { enumerable: true, get: function () { return __importDefault(DataViewEventsContext_1).default; } });
46
55
  __exportStar(require("./DataViewEventsContext"), exports);
@@ -0,0 +1 @@
1
+ {"main":"../../cjs/DataViewTh/index.js","module":"../../esm/DataViewTh/index.js","typings":"../../esm/DataViewTh/index.d.ts"}
@@ -0,0 +1 @@
1
+ {"main":"../../cjs/DataViewTreeFilter/index.js","module":"../../esm/DataViewTreeFilter/index.js","typings":"../../esm/DataViewTreeFilter/index.d.ts"}
@@ -0,0 +1,62 @@
1
+ {
2
+ "DataView": "dist/dynamic/DataView",
3
+ "DataViewCheckboxFilter": "dist/dynamic/DataViewCheckboxFilter",
4
+ "DataViewCheckboxFilterProps": "dist/dynamic/DataViewCheckboxFilter",
5
+ "DataViewEvent": "dist/dynamic/DataViewEventsContext",
6
+ "DataViewEventsContext": "dist/dynamic/DataViewEventsContext",
7
+ "DataViewEventsContextValue": "dist/dynamic/DataViewEventsContext",
8
+ "DataViewEventsProvider": "dist/dynamic/DataViewEventsContext",
9
+ "DataViewFilterOption": "dist/dynamic/DataViewFilters",
10
+ "DataViewFilters": "dist/dynamic/DataViewFilters",
11
+ "DataViewFiltersProps": "dist/dynamic/DataViewFilters",
12
+ "DataViewImpementationProps": "dist/dynamic/DataView",
13
+ "DataViewPaginationProps": "dist/dynamic/Hooks",
14
+ "DataViewProps": "dist/dynamic/DataView",
15
+ "DataViewSelection": "dist/dynamic/InternalContext",
16
+ "DataViewSortConfig": "dist/dynamic/Hooks",
17
+ "DataViewSortParams": "dist/dynamic/Hooks",
18
+ "DataViewState": "dist/dynamic/DataView",
19
+ "DataViewTable": "dist/dynamic/DataViewTable",
20
+ "DataViewTableBasic": "dist/dynamic/DataViewTableBasic",
21
+ "DataViewTableBasicProps": "dist/dynamic/DataViewTableBasic",
22
+ "DataViewTableHead": "dist/dynamic/DataViewTableHead",
23
+ "DataViewTableHeadProps": "dist/dynamic/DataViewTableHead",
24
+ "DataViewTableProps": "dist/dynamic/DataViewTable",
25
+ "DataViewTableTree": "dist/dynamic/DataViewTableTree",
26
+ "DataViewTableTreeProps": "dist/dynamic/DataViewTableTree",
27
+ "DataViewTd": "dist/dynamic/DataViewTable",
28
+ "DataViewTextFilter": "dist/dynamic/DataViewTextFilter",
29
+ "DataViewTextFilterProps": "dist/dynamic/DataViewTextFilter",
30
+ "DataViewTh": "dist/dynamic/DataViewTh",
31
+ "DataViewThProps": "dist/dynamic/DataViewTh",
32
+ "DataViewThResizableProps": "dist/dynamic/DataViewTh",
33
+ "DataViewToolbar": "dist/dynamic/DataViewToolbar",
34
+ "DataViewToolbarProps": "dist/dynamic/DataViewToolbar",
35
+ "DataViewTr": "dist/dynamic/DataViewTable",
36
+ "DataViewTrObject": "dist/dynamic/DataViewTable",
37
+ "DataViewTrTree": "dist/dynamic/DataViewTable",
38
+ "DataViewTreeFilter": "dist/dynamic/DataViewTreeFilter",
39
+ "DataViewTreeFilterProps": "dist/dynamic/DataViewTreeFilter",
40
+ "EventTypes": "dist/dynamic/DataViewEventsContext",
41
+ "ExpandableContent": "dist/dynamic/DataViewTableBasic",
42
+ "InternalContext": "dist/dynamic/InternalContext",
43
+ "InternalContextProps": "dist/dynamic/InternalContext",
44
+ "InternalContextProvider": "dist/dynamic/InternalContext",
45
+ "InternalContextValue": "dist/dynamic/InternalContext",
46
+ "InternalProviderProps": "dist/dynamic/InternalContext",
47
+ "PaginationParams": "dist/dynamic/Hooks",
48
+ "UseDataViewFiltersProps": "dist/dynamic/Hooks",
49
+ "UseDataViewPaginationProps": "dist/dynamic/Hooks",
50
+ "UseDataViewSelectionProps": "dist/dynamic/Hooks",
51
+ "UseDataViewSortProps": "dist/dynamic/Hooks",
52
+ "isDataViewFilterOption": "dist/dynamic/DataViewCheckboxFilter",
53
+ "isDataViewTdObject": "dist/dynamic/DataViewTable",
54
+ "isDataViewThObject": "dist/dynamic/DataViewTable",
55
+ "isDataViewTrObject": "dist/dynamic/DataViewTable",
56
+ "useDataViewEventsContext": "dist/dynamic/DataViewEventsContext",
57
+ "useDataViewFilters": "dist/dynamic/Hooks",
58
+ "useDataViewPagination": "dist/dynamic/Hooks",
59
+ "useDataViewSelection": "dist/dynamic/Hooks",
60
+ "useDataViewSort": "dist/dynamic/Hooks",
61
+ "useInternalContext": "dist/dynamic/InternalContext"
62
+ }
@@ -1,8 +1,9 @@
1
1
  import { FC, ReactNode } from 'react';
2
2
  import { TdProps, ThProps, TrProps } from '@patternfly/react-table';
3
3
  import { DataViewTableTreeProps } from '../DataViewTableTree';
4
- import { DataViewTableBasicProps } from '../DataViewTableBasic';
4
+ import { DataViewTableBasicProps, ExpandableContent } from '../DataViewTableBasic';
5
5
  import { DataViewThResizableProps } from '../DataViewTh/DataViewTh';
6
+ export type { ExpandableContent };
6
7
  export type DataViewTh = ReactNode | {
7
8
  /** Table head cell node */
8
9
  cell: ReactNode;
@@ -2,12 +2,19 @@ import { FC } from 'react';
2
2
  import { TableProps } from '@patternfly/react-table';
3
3
  import { DataViewTh, DataViewTr } from '../DataViewTable';
4
4
  import { DataViewState } from '../DataView/DataView';
5
+ export interface ExpandableContent {
6
+ rowId: number;
7
+ columnId: number;
8
+ content: React.ReactNode;
9
+ }
5
10
  /** extends TableProps */
6
11
  export interface DataViewTableBasicProps extends Omit<TableProps, 'onSelect' | 'rows'> {
7
12
  /** Columns definition */
8
13
  columns: DataViewTh[];
9
14
  /** Current page rows */
10
15
  rows: DataViewTr[];
16
+ /** Expanded rows content */
17
+ expandedRows?: ExpandableContent[];
11
18
  /** Table head states to be displayed when active */
12
19
  headStates?: Partial<Record<DataViewState | string, React.ReactNode>>;
13
20
  /** Table body states to be displayed when active */
@@ -16,6 +23,10 @@ export interface DataViewTableBasicProps extends Omit<TableProps, 'onSelect' | '
16
23
  ouiaId?: string;
17
24
  /** @hide Indicates if the table is resizable */
18
25
  hasResizableColumns?: boolean;
26
+ /** Toggles expandable */
27
+ isExpandable?: boolean;
28
+ /** Toggles sticky columns and header */
29
+ isSticky?: boolean;
19
30
  }
20
31
  export declare const DataViewTableBasic: FC<DataViewTableBasicProps>;
21
32
  export default DataViewTableBasic;