@patternfly/react-data-view 6.3.0 → 6.4.0-prerelease.11

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 (95) hide show
  1. package/dist/cjs/DataViewTable/DataViewTable.d.ts +6 -1
  2. package/dist/cjs/DataViewTable/DataViewTable.js +21 -1
  3. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.d.ts +13 -0
  4. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.js +46 -6
  5. package/dist/cjs/DataViewTableBasic/DataViewTableBasic.test.js +47 -9
  6. package/dist/cjs/DataViewTableHead/DataViewTableHead.d.ts +2 -0
  7. package/dist/cjs/DataViewTableHead/DataViewTableHead.js +5 -4
  8. package/dist/cjs/DataViewTableTree/DataViewTableTree.d.ts +2 -0
  9. package/dist/cjs/DataViewTableTree/DataViewTableTree.js +28 -1
  10. package/dist/cjs/DataViewTableTree/DataViewTableTree.test.js +4 -0
  11. package/dist/cjs/DataViewTh/DataViewTh.d.ts +32 -0
  12. package/dist/cjs/DataViewTh/DataViewTh.js +222 -0
  13. package/dist/cjs/DataViewTh/index.d.ts +2 -0
  14. package/dist/cjs/DataViewTh/index.js +23 -0
  15. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.d.ts +26 -0
  16. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.js +229 -0
  17. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.test.d.ts +1 -0
  18. package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.test.js +171 -0
  19. package/dist/cjs/DataViewTreeFilter/index.d.ts +2 -0
  20. package/dist/cjs/DataViewTreeFilter/index.js +23 -0
  21. package/dist/cjs/Hooks/selection.d.ts +8 -7
  22. package/dist/cjs/Hooks/selection.js +5 -1
  23. package/dist/cjs/Hooks/selection.test.js +48 -0
  24. package/dist/cjs/InternalContext/InternalContext.d.ts +2 -0
  25. package/dist/cjs/index.d.ts +6 -0
  26. package/dist/cjs/index.js +10 -1
  27. package/dist/dynamic/DataViewTh/package.json +1 -0
  28. package/dist/dynamic/DataViewTreeFilter/package.json +1 -0
  29. package/dist/dynamic-modules.json +62 -0
  30. package/dist/esm/DataViewTable/DataViewTable.d.ts +6 -1
  31. package/dist/esm/DataViewTable/DataViewTable.js +21 -1
  32. package/dist/esm/DataViewTableBasic/DataViewTableBasic.d.ts +13 -0
  33. package/dist/esm/DataViewTableBasic/DataViewTableBasic.js +48 -8
  34. package/dist/esm/DataViewTableBasic/DataViewTableBasic.test.js +45 -10
  35. package/dist/esm/DataViewTableHead/DataViewTableHead.d.ts +2 -0
  36. package/dist/esm/DataViewTableHead/DataViewTableHead.js +5 -4
  37. package/dist/esm/DataViewTableTree/DataViewTableTree.d.ts +2 -0
  38. package/dist/esm/DataViewTableTree/DataViewTableTree.js +29 -2
  39. package/dist/esm/DataViewTableTree/DataViewTableTree.test.js +4 -0
  40. package/dist/esm/DataViewTh/DataViewTh.d.ts +32 -0
  41. package/dist/esm/DataViewTh/DataViewTh.js +215 -0
  42. package/dist/esm/DataViewTh/index.d.ts +2 -0
  43. package/dist/esm/DataViewTh/index.js +2 -0
  44. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.d.ts +26 -0
  45. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.js +225 -0
  46. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.test.d.ts +1 -0
  47. package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.test.js +166 -0
  48. package/dist/esm/DataViewTreeFilter/index.d.ts +2 -0
  49. package/dist/esm/DataViewTreeFilter/index.js +2 -0
  50. package/dist/esm/Hooks/selection.d.ts +8 -7
  51. package/dist/esm/Hooks/selection.js +5 -1
  52. package/dist/esm/Hooks/selection.test.js +48 -0
  53. package/dist/esm/InternalContext/InternalContext.d.ts +2 -0
  54. package/dist/esm/index.d.ts +6 -0
  55. package/dist/esm/index.js +6 -0
  56. package/dist/tsconfig.tsbuildinfo +1 -1
  57. package/generate-fed-package-json.js +18 -0
  58. package/generate-index.js +2 -2
  59. package/package.json +12 -12
  60. package/patternfly-docs/content/extensions/data-view/examples/DataView/DataView.md +10 -4
  61. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableExpandableExample.tsx +108 -0
  62. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableInteractiveExample.tsx +148 -0
  63. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableResizableColumnsExample.tsx +155 -0
  64. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableStickyExample.tsx +90 -0
  65. package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableTreeExample.tsx +1 -0
  66. package/patternfly-docs/content/extensions/data-view/examples/Table/Table.md +113 -14
  67. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/SelectionExample.tsx +14 -3
  68. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/Toolbar.md +10 -2
  69. package/patternfly-docs/content/extensions/data-view/examples/Toolbar/TreeFilterExample.tsx +248 -0
  70. package/patternfly-docs/patternfly-docs.config.js +4 -1
  71. package/release.config.js +1 -1
  72. package/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap +0 -2
  73. package/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap +0 -2
  74. package/src/DataViewTable/DataViewTable.tsx +51 -28
  75. package/src/DataViewTable/__snapshots__/DataViewTable.test.tsx.snap +17 -25
  76. package/src/DataViewTableBasic/DataViewTableBasic.test.tsx +54 -12
  77. package/src/DataViewTableBasic/DataViewTableBasic.tsx +104 -10
  78. package/src/DataViewTableBasic/__snapshots__/DataViewTableBasic.test.tsx.snap +30 -30
  79. package/src/DataViewTableHead/DataViewTableHead.tsx +24 -23
  80. package/src/DataViewTableHead/__snapshots__/DataViewTableHead.test.tsx.snap +15 -15
  81. package/src/DataViewTableTree/DataViewTableTree.test.tsx +9 -0
  82. package/src/DataViewTableTree/DataViewTableTree.tsx +35 -1
  83. package/src/DataViewTableTree/__snapshots__/DataViewTableTree.test.tsx.snap +977 -28
  84. package/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap +0 -3
  85. package/src/DataViewTh/DataViewTh.tsx +342 -0
  86. package/src/DataViewTh/index.ts +2 -0
  87. package/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap +0 -10
  88. package/src/DataViewTreeFilter/DataViewTreeFilter.test.tsx +222 -0
  89. package/src/DataViewTreeFilter/DataViewTreeFilter.tsx +361 -0
  90. package/src/DataViewTreeFilter/__snapshots__/DataViewTreeFilter.test.tsx.snap +199 -0
  91. package/src/DataViewTreeFilter/index.ts +2 -0
  92. package/src/Hooks/selection.test.tsx +65 -1
  93. package/src/Hooks/selection.ts +13 -8
  94. package/src/InternalContext/InternalContext.tsx +2 -0
  95. package/src/index.ts +9 -0
@@ -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,10 +1,14 @@
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
+ import { DataViewThResizableProps } from '../DataViewTh/DataViewTh';
6
+ export type { ExpandableContent };
5
7
  export type DataViewTh = ReactNode | {
6
8
  /** Table head cell node */
7
9
  cell: ReactNode;
10
+ /** Additional props for a resizable column */
11
+ resizableProps?: DataViewThResizableProps;
8
12
  /** Props passed to Th */
9
13
  props?: ThProps;
10
14
  };
@@ -44,6 +48,7 @@ export type DataViewTableProps = ({
44
48
  isTreeTable: true;
45
49
  } & DataViewTableTreeProps) | ({
46
50
  isTreeTable?: false;
51
+ isResizable?: boolean;
47
52
  } & DataViewTableBasicProps);
48
53
  export declare const DataViewTable: FC<DataViewTableProps>;
49
54
  export default DataViewTable;
@@ -1,8 +1,28 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { InnerScrollContainer } from '@patternfly/react-table';
2
14
  import { DataViewTableTree } from '../DataViewTableTree';
3
15
  import { DataViewTableBasic } from '../DataViewTableBasic';
4
16
  export const isDataViewThObject = (value) => value != null && typeof value === 'object' && 'cell' in value;
5
17
  export const isDataViewTdObject = (value) => value != null && typeof value === 'object' && 'cell' in value;
6
18
  export const isDataViewTrObject = (value) => value != null && typeof value === 'object' && 'row' in value;
7
- export const DataViewTable = (props) => (props.isTreeTable ? _jsx(DataViewTableTree, Object.assign({}, props)) : _jsx(DataViewTableBasic, Object.assign({}, props)));
19
+ export const DataViewTable = (props) => {
20
+ if (props.isTreeTable) {
21
+ return _jsx(DataViewTableTree, Object.assign({}, props));
22
+ }
23
+ else {
24
+ const { isResizable } = props, rest = __rest(props, ["isResizable"]);
25
+ return isResizable ? (_jsx(InnerScrollContainer, { children: _jsx(DataViewTableBasic, Object.assign({ hasResizableColumns: true }, rest)) })) : (_jsx(DataViewTableBasic, Object.assign({}, rest)));
26
+ }
27
+ };
8
28
  export default DataViewTable;
@@ -2,18 +2,31 @@ 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 */
14
21
  bodyStates?: Partial<Record<DataViewState | string, React.ReactNode>>;
15
22
  /** Custom OUIA ID */
16
23
  ouiaId?: string;
24
+ /** @hide Indicates if the table is resizable */
25
+ hasResizableColumns?: boolean;
26
+ /** Toggles expandable */
27
+ isExpandable?: boolean;
28
+ /** Toggles sticky columns and header */
29
+ isSticky?: boolean;
17
30
  }
18
31
  export declare const DataViewTableBasic: FC<DataViewTableBasicProps>;
19
32
  export default DataViewTableBasic;
@@ -10,20 +10,32 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { useMemo } from 'react';
14
- import { Table, Tbody, Td, Tr, } from '@patternfly/react-table';
13
+ import { useMemo, useState, useRef } from 'react';
14
+ import { ExpandableRowContent, InnerScrollContainer, OuterScrollContainer, Table, Tbody, Td, Tr, } from '@patternfly/react-table';
15
15
  import { useInternalContext } from '../InternalContext';
16
16
  import { DataViewTableHead } from '../DataViewTableHead';
17
17
  import { isDataViewTdObject, isDataViewTrObject } from '../DataViewTable';
18
18
  export const DataViewTableBasic = (_a) => {
19
- var { columns, rows, ouiaId = 'DataViewTableBasic', headStates, bodyStates } = _a, props = __rest(_a, ["columns", "rows", "ouiaId", "headStates", "bodyStates"]);
19
+ var { columns, rows, expandedRows, ouiaId = 'DataViewTableBasic', headStates, bodyStates, hasResizableColumns, isExpandable = false, isSticky = false } = _a, props = __rest(_a, ["columns", "rows", "expandedRows", "ouiaId", "headStates", "bodyStates", "hasResizableColumns", "isExpandable", "isSticky"]);
20
20
  const { selection, activeState, isSelectable } = useInternalContext();
21
21
  const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
22
22
  const activeHeadState = useMemo(() => activeState ? headStates === null || headStates === void 0 ? void 0 : headStates[activeState] : undefined, [activeState, headStates]);
23
23
  const activeBodyState = useMemo(() => activeState ? bodyStates === null || bodyStates === void 0 ? void 0 : bodyStates[activeState] : undefined, [activeState, bodyStates]);
24
+ const [expandedRowsState, setExpandedRowsState] = useState({});
25
+ const [expandedColumnIndex, setExpandedColumnIndex] = useState({});
26
+ const tableRef = useRef(null);
27
+ const needsSeparateTbody = isExpandable;
24
28
  const renderedRows = useMemo(() => rows.map((row, rowIndex) => {
25
29
  const rowIsObject = isDataViewTrObject(row);
26
- return (_jsxs(Tr, Object.assign({ ouiaId: `${ouiaId}-tr-${rowIndex}` }, (rowIsObject && (row === null || row === void 0 ? void 0 : row.props)), { children: [isSelectable && (_jsx(Td, { select: {
30
+ const isRowExpanded = expandedRowsState[rowIndex] || false;
31
+ const expandedColIndex = expandedColumnIndex[rowIndex];
32
+ // Get the first cell to extract the row ID
33
+ const rowData = rowIsObject ? row.row : row;
34
+ const firstCell = rowData[0];
35
+ const rowId = isDataViewTdObject(firstCell) ? firstCell.id : undefined;
36
+ // Find all expandable contents for this row
37
+ const rowExpandableContents = isExpandable ? expandedRows === null || expandedRows === void 0 ? void 0 : expandedRows.filter((content) => content.rowId === rowId) : [];
38
+ const rowContent = (_jsxs(Tr, Object.assign({ ouiaId: `${ouiaId}-tr-${rowIndex}` }, (rowIsObject && (row === null || row === void 0 ? void 0 : row.props)), { isContentExpanded: isRowExpanded, isControlRow: true, children: [isSelectable && (_jsx(Td, { select: {
27
39
  rowIndex,
28
40
  onSelect: (_event, isSelecting) => {
29
41
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(isSelecting, rowIsObject ? row : [row]);
@@ -33,9 +45,37 @@ export const DataViewTableBasic = (_a) => {
33
45
  } }, `select-${rowIndex}`)), (rowIsObject ? row.row : row).map((cell, colIndex) => {
34
46
  var _a;
35
47
  const cellIsObject = isDataViewTdObject(cell);
36
- return (_jsx(Td, Object.assign({}, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}`, children: cellIsObject ? cell.cell : cell }), colIndex));
37
- })] }), rowIndex));
38
- }), [rows, isSelectable, isSelected, isSelectDisabled, onSelect, ouiaId]);
39
- return (_jsxs(Table, Object.assign({ "aria-label": "Data table", ouiaId: ouiaId }, props, { children: [activeHeadState || _jsx(DataViewTableHead, { columns: columns, ouiaId: ouiaId }), activeBodyState || _jsx(Tbody, { children: renderedRows })] })));
48
+ const cellExpandableContent = isExpandable ? expandedRows === null || expandedRows === void 0 ? void 0 : expandedRows.find((content) => content.rowId === rowId && content.columnId === colIndex) : undefined;
49
+ return (_jsx(Td, Object.assign({}, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), (cellExpandableContent != null && {
50
+ compoundExpand: {
51
+ isExpanded: isRowExpanded && expandedColIndex === colIndex,
52
+ expandId: `expandable-${rowIndex}`,
53
+ onToggle: () => {
54
+ setExpandedRowsState(prev => {
55
+ const isSameColumn = expandedColIndex === colIndex;
56
+ const wasExpanded = prev[rowIndex];
57
+ return Object.assign(Object.assign({}, prev), { [rowIndex]: isSameColumn ? !wasExpanded : true });
58
+ });
59
+ setExpandedColumnIndex(prev => (Object.assign(Object.assign({}, prev), { [rowIndex]: colIndex })));
60
+ },
61
+ rowIndex,
62
+ columnIndex: colIndex
63
+ }
64
+ }), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}`, children: cellIsObject ? cell.cell : cell }), colIndex));
65
+ })] }), needsSeparateTbody ? undefined : rowIndex));
66
+ if (needsSeparateTbody) {
67
+ return (_jsxs(Tbody, { isExpanded: isRowExpanded, children: [rowContent, rowExpandableContents === null || rowExpandableContents === void 0 ? void 0 : rowExpandableContents.map((expandableContent) => (_jsx(Tr, { isExpanded: isRowExpanded && expandedColIndex === expandableContent.columnId, children: _jsx(Td, { colSpan: rowData.length + (isSelectable ? 1 : 0), "data-expanded-column-index": expandableContent.columnId, children: _jsx(ExpandableRowContent, { children: expandableContent.content }) }) }, `expand-${rowIndex}-${expandableContent.columnId}`)))] }, rowIndex));
68
+ }
69
+ else {
70
+ return rowContent;
71
+ }
72
+ }), [rows, isSelectable, isSelected, isSelectDisabled, onSelect, ouiaId, expandedRowsState, expandedColumnIndex, expandedRows, isExpandable, needsSeparateTbody]);
73
+ const bodyContent = activeBodyState || (needsSeparateTbody ? renderedRows : _jsx(Tbody, { children: renderedRows }));
74
+ if (isSticky) {
75
+ return (_jsx(OuterScrollContainer, { children: _jsx(InnerScrollContainer, { children: _jsxs(Table, Object.assign({ ref: tableRef, "aria-label": "Data table", ouiaId: ouiaId, isExpandable: isExpandable, hasAnimations: true }, props, { isStickyHeader: true, children: [activeHeadState || _jsx(DataViewTableHead, { columns: columns, ouiaId: ouiaId, hasResizableColumns: hasResizableColumns }), bodyContent] })) }) }));
76
+ }
77
+ else {
78
+ return (_jsxs(Table, Object.assign({ ref: tableRef, "aria-label": "Data table", ouiaId: ouiaId, isExpandable: isExpandable, hasAnimations: true }, props, { children: [activeHeadState || _jsx(DataViewTableHead, { columns: columns, ouiaId: ouiaId, hasResizableColumns: hasResizableColumns }), bodyContent] })));
79
+ }
40
80
  };
41
81
  export default DataViewTableBasic;
@@ -1,19 +1,36 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { render } from '@testing-library/react';
11
+ import { render, screen } from '@testing-library/react';
12
+ import userEvent from '@testing-library/user-event';
3
13
  import { DataView } from '../DataView';
4
14
  import { DataViewTableBasic } from './DataViewTableBasic';
5
15
  const repositories = [
6
- { name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
7
- { name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
8
- { name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
9
- { name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
10
- { name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
11
- { name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
16
+ { id: 1, name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
17
+ { id: 2, name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
18
+ { id: 3, name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
19
+ { id: 4, name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
20
+ { id: 5, name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
21
+ { id: 6, name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
12
22
  ];
13
- const rows = repositories.map(repo => ({
14
- row: Object.values(repo),
15
- }));
23
+ const rows = repositories.map(({ id, name, branches, prs, workspaces, lastCommit }) => [
24
+ { id, cell: name },
25
+ branches,
26
+ prs,
27
+ workspaces,
28
+ lastCommit
29
+ ]);
16
30
  const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];
31
+ const expandableContents = [
32
+ { rowId: 1, columnId: 1, content: _jsx("div", { children: "Branch details for Repository one" }) },
33
+ ];
17
34
  const ouiaId = 'TableExample';
18
35
  describe('DataViewTable component', () => {
19
36
  test('should render correctly', () => {
@@ -32,4 +49,22 @@ describe('DataViewTable component', () => {
32
49
  const { container } = render(_jsx(DataView, { activeState: "loading", children: _jsx(DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, bodyStates: { loading: "Data is loading" }, rows: [] }) }));
33
50
  expect(container).toMatchSnapshot();
34
51
  });
52
+ test('when isExpandable cell should be clickable and expandable', () => __awaiter(void 0, void 0, void 0, function* () {
53
+ var _a, _b, _c;
54
+ const user = userEvent.setup();
55
+ render(_jsx(DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, rows: rows, isExpandable: true, expandedRows: expandableContents }));
56
+ // Initially, expandable content is rendered but should be hidden (not visible)
57
+ const initialBranchContent = screen.getByText('Branch details for Repository one');
58
+ expect((_a = initialBranchContent.closest('tr')) === null || _a === void 0 ? void 0 : _a.classList.contains('pf-m-expanded')).toBeFalsy();
59
+ // Find the first expandable button by ID
60
+ const branchExpandButton = document.getElementById('expandable-0-0-1');
61
+ expect(branchExpandButton).toBeTruthy();
62
+ // Verify the button is in the cell with "Branch one" text
63
+ expect((_b = branchExpandButton === null || branchExpandButton === void 0 ? void 0 : branchExpandButton.closest('td')) === null || _b === void 0 ? void 0 : _b.textContent).toContain('Branch one');
64
+ // Click the expand button for Branches column
65
+ yield user.click(branchExpandButton);
66
+ // After clicking, the expandable content should be visible
67
+ const branchContent = screen.getByText('Branch details for Repository one');
68
+ expect((_c = branchContent.closest('tr')) === null || _c === void 0 ? void 0 : _c.classList.contains('pf-m-expanded')).toBeTruthy();
69
+ }));
35
70
  });
@@ -9,6 +9,8 @@ export interface DataViewTableHeadProps extends TheadProps {
9
9
  columns: DataViewTh[];
10
10
  /** Custom OUIA ID */
11
11
  ouiaId?: string;
12
+ /** @hide Indicates whether table is resizable */
13
+ hasResizableColumns?: boolean;
12
14
  }
13
15
  export declare const DataViewTableHead: FC<DataViewTableHeadProps>;
14
16
  export default DataViewTableHead;
@@ -14,17 +14,18 @@ import { useMemo } from 'react';
14
14
  import { Th, Thead, Tr } from '@patternfly/react-table';
15
15
  import { useInternalContext } from '../InternalContext';
16
16
  import { isDataViewThObject } from '../DataViewTable';
17
+ import { DataViewTh as DataViewThElement } from '../DataViewTh/DataViewTh';
17
18
  export const DataViewTableHead = (_a) => {
18
- var { isTreeTable = false, columns, ouiaId = 'DataViewTableHead' } = _a, props = __rest(_a, ["isTreeTable", "columns", "ouiaId"]);
19
+ var { isTreeTable = false, columns, ouiaId = 'DataViewTableHead', hasResizableColumns } = _a, props = __rest(_a, ["isTreeTable", "columns", "ouiaId", "hasResizableColumns"]);
19
20
  const { selection } = useInternalContext();
20
21
  const { onSelect, isSelected } = selection !== null && selection !== void 0 ? selection : {};
21
22
  const cells = useMemo(() => [
22
- onSelect && isSelected && !isTreeTable ? (_jsx(Th, { screenReaderText: 'Data selection table head cell' }, "row-select")) : null,
23
+ onSelect && isSelected && !isTreeTable ? (_jsx(Th, { screenReaderText: "Data selection table head cell" }, "row-select")) : null,
23
24
  ...columns.map((column, index) => {
24
25
  var _a;
25
- return (_jsx(Th, Object.assign({}, (isDataViewThObject(column) && ((_a = column === null || column === void 0 ? void 0 : column.props) !== null && _a !== void 0 ? _a : {})), { "data-ouia-component-id": `${ouiaId}-th-${index}`, children: isDataViewThObject(column) ? column.cell : column }), index));
26
+ return (_jsx(DataViewThElement, { content: isDataViewThObject(column) ? column.cell : column, resizableProps: isDataViewThObject(column) ? column.resizableProps : undefined, "data-ouia-component-id": `${ouiaId}-th-${index}`, thProps: isDataViewThObject(column) ? ((_a = column === null || column === void 0 ? void 0 : column.props) !== null && _a !== void 0 ? _a : {}) : {}, hasResizableColumns: hasResizableColumns }, index));
26
27
  })
27
- ], [columns, ouiaId, onSelect, isSelected, isTreeTable]);
28
+ ], [columns, ouiaId, onSelect, isSelected, isTreeTable, hasResizableColumns]);
28
29
  return (_jsx(Thead, Object.assign({ "data-ouia-component-id": `${ouiaId}-thead` }, props, { children: _jsx(Tr, { ouiaId: `${ouiaId}-tr-head`, children: cells }) })));
29
30
  };
30
31
  export default DataViewTableHead;
@@ -18,6 +18,8 @@ export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'r
18
18
  expandedIcon?: React.ReactNode;
19
19
  /** Optional icon for the collapsed parent rows */
20
20
  collapsedIcon?: React.ReactNode;
21
+ /** Expand all expandable nodes on initial load */
22
+ expandAll?: boolean;
21
23
  /** Custom OUIA ID */
22
24
  ouiaId?: string;
23
25
  }
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { useState, useMemo } from 'react';
13
+ import { useState, useMemo, useEffect } from 'react';
14
14
  import { Table, Tbody, Td, TreeRowWrapper, } from '@patternfly/react-table';
15
15
  import { useInternalContext } from '../InternalContext';
16
16
  import { DataViewTableHead } from '../DataViewTableHead';
@@ -42,11 +42,38 @@ const getNodesAffectedBySelection = (allRows, node, isChecking, isSelected) => {
42
42
  return Array.from(affectedNodes);
43
43
  };
44
44
  export const DataViewTableTree = (_a) => {
45
- var { columns, rows, headStates, bodyStates, leafIcon = null, expandedIcon = null, collapsedIcon = null, ouiaId = 'DataViewTableTree' } = _a, props = __rest(_a, ["columns", "rows", "headStates", "bodyStates", "leafIcon", "expandedIcon", "collapsedIcon", "ouiaId"]);
45
+ var { columns, rows, headStates, bodyStates, leafIcon = null, expandedIcon = null, collapsedIcon = null, expandAll = false, ouiaId = 'DataViewTableTree' } = _a, props = __rest(_a, ["columns", "rows", "headStates", "bodyStates", "leafIcon", "expandedIcon", "collapsedIcon", "expandAll", "ouiaId"]);
46
46
  const { selection, activeState } = useInternalContext();
47
47
  const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
48
48
  const [expandedNodeIds, setExpandedNodeIds] = useState([]);
49
49
  const [expandedDetailsNodeNames, setExpandedDetailsNodeIds] = useState([]);
50
+ // Helper function to collect all node IDs that have children (are expandable)
51
+ const getExpandableNodeIds = (nodes) => {
52
+ const expandableIds = [];
53
+ const traverse = (nodeList) => {
54
+ nodeList.forEach(node => {
55
+ if (node.children && node.children.length > 0) {
56
+ expandableIds.push(node.id);
57
+ traverse(node.children);
58
+ }
59
+ });
60
+ };
61
+ traverse(nodes);
62
+ return expandableIds;
63
+ };
64
+ // Effect to handle expandAll behavior
65
+ // Memoize the expandable IDs to avoid recalculating when rows object reference changes but structure is the same
66
+ const expandableIds = useMemo(() => getExpandableNodeIds(rows), [rows]);
67
+ // Effect to handle expandAll behavior - only runs when IDs actually change
68
+ useEffect(() => {
69
+ if (expandAll) {
70
+ setExpandedNodeIds(expandableIds);
71
+ }
72
+ else {
73
+ setExpandedNodeIds([]);
74
+ }
75
+ // eslint-disable-next-line react-hooks/exhaustive-deps
76
+ }, [expandAll, expandableIds.join(',')]);
50
77
  const activeHeadState = useMemo(() => activeState ? headStates === null || headStates === void 0 ? void 0 : headStates[activeState] : undefined, [activeState, headStates]);
51
78
  const activeBodyState = useMemo(() => activeState ? bodyStates === null || bodyStates === void 0 ? void 0 : bodyStates[activeState] : undefined, [activeState, bodyStates]);
52
79
  const nodes = useMemo(() => {
@@ -74,6 +74,10 @@ describe('DataViewTableTree component', () => {
74
74
  const { container } = render(_jsx(DataView, { activeState: "error", children: _jsx(DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, bodyStates: { error: "Some error" }, rows: [] }) }));
75
75
  expect(container).toMatchSnapshot();
76
76
  });
77
+ test('should render tree table with all expandable nodes expanded', () => {
78
+ const { container } = render(_jsx(DataView, { selection: mockSelection, children: _jsx(DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, expandAll: true, rows: rows, leafIcon: _jsx(LeafIcon, {}), expandedIcon: _jsx(FolderOpenIcon, { "aria-hidden": true }), collapsedIcon: _jsx(FolderIcon, { "aria-hidden": true }) }) }));
79
+ expect(container).toMatchSnapshot();
80
+ });
77
81
  test('should render tree table with a loading state', () => {
78
82
  const { container } = render(_jsx(DataView, { activeState: "loading", children: _jsx(DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, bodyStates: { loading: "Data is loading" }, rows: [] }) }));
79
83
  expect(container).toMatchSnapshot();
@@ -0,0 +1,32 @@
1
+ import { FC, MouseEvent as ReactMouseEvent, KeyboardEvent as ReactKeyboardEvent, ReactNode } from 'react';
2
+ import { ThProps } from '@patternfly/react-table';
3
+ export interface DataViewThResizableProps {
4
+ /** Whether the column is resizable */
5
+ isResizable?: boolean;
6
+ /** Callback after the column is resized. Returns the triggering event, the column id passed in via cell props, and the new width of the column. */
7
+ onResize?: (event: ReactMouseEvent | MouseEvent | ReactKeyboardEvent | KeyboardEvent | TouchEvent, id: string | number | undefined, width: number) => void;
8
+ /** Width of the column */
9
+ width?: number;
10
+ /** Minimum width of the column */
11
+ minWidth?: number;
12
+ /** Increment for keyboard navigation */
13
+ increment?: number;
14
+ /** Increment for keyboard navigation while shift is held */
15
+ shiftIncrement?: number;
16
+ /** Provides an accessible name for the resizable column via a human readable string. */
17
+ resizeButtonAriaLabel?: string;
18
+ /** Screenreader text that gets announced when the column is resized. */
19
+ screenReaderText?: string;
20
+ }
21
+ export interface DataViewThProps {
22
+ /** Cell content */
23
+ content: ReactNode;
24
+ /** Resizable props */
25
+ resizableProps?: DataViewThResizableProps;
26
+ /** @hide Indicates whether the table has resizable columns */
27
+ hasResizableColumns?: boolean;
28
+ /** Props passed to Th */
29
+ thProps?: ThProps;
30
+ }
31
+ export declare const DataViewTh: FC<DataViewThProps>;
32
+ export default DataViewTh;