@patternfly/react-data-view 6.3.0 → 6.4.0-prerelease.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/DataViewTable/DataViewTable.d.ts +6 -1
- package/dist/cjs/DataViewTable/DataViewTable.js +21 -1
- package/dist/cjs/DataViewTableBasic/DataViewTableBasic.d.ts +13 -0
- package/dist/cjs/DataViewTableBasic/DataViewTableBasic.js +46 -6
- package/dist/cjs/DataViewTableBasic/DataViewTableBasic.test.js +47 -9
- package/dist/cjs/DataViewTableHead/DataViewTableHead.d.ts +2 -0
- package/dist/cjs/DataViewTableHead/DataViewTableHead.js +5 -4
- package/dist/cjs/DataViewTableTree/DataViewTableTree.d.ts +2 -0
- package/dist/cjs/DataViewTableTree/DataViewTableTree.js +28 -1
- package/dist/cjs/DataViewTableTree/DataViewTableTree.test.js +4 -0
- package/dist/cjs/DataViewTh/DataViewTh.d.ts +32 -0
- package/dist/cjs/DataViewTh/DataViewTh.js +222 -0
- package/dist/cjs/DataViewTh/index.d.ts +2 -0
- package/dist/cjs/DataViewTh/index.js +23 -0
- package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.d.ts +26 -0
- package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.js +229 -0
- package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.test.d.ts +1 -0
- package/dist/cjs/DataViewTreeFilter/DataViewTreeFilter.test.js +171 -0
- package/dist/cjs/DataViewTreeFilter/index.d.ts +2 -0
- package/dist/cjs/DataViewTreeFilter/index.js +23 -0
- package/dist/cjs/Hooks/selection.d.ts +1 -0
- package/dist/cjs/Hooks/selection.js +5 -1
- package/dist/cjs/Hooks/selection.test.js +48 -0
- package/dist/cjs/InternalContext/InternalContext.d.ts +2 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +10 -1
- package/dist/dynamic/DataViewTh/package.json +1 -0
- package/dist/dynamic/DataViewTreeFilter/package.json +1 -0
- package/dist/dynamic-modules.json +62 -0
- package/dist/esm/DataViewTable/DataViewTable.d.ts +6 -1
- package/dist/esm/DataViewTable/DataViewTable.js +21 -1
- package/dist/esm/DataViewTableBasic/DataViewTableBasic.d.ts +13 -0
- package/dist/esm/DataViewTableBasic/DataViewTableBasic.js +48 -8
- package/dist/esm/DataViewTableBasic/DataViewTableBasic.test.js +45 -10
- package/dist/esm/DataViewTableHead/DataViewTableHead.d.ts +2 -0
- package/dist/esm/DataViewTableHead/DataViewTableHead.js +5 -4
- package/dist/esm/DataViewTableTree/DataViewTableTree.d.ts +2 -0
- package/dist/esm/DataViewTableTree/DataViewTableTree.js +29 -2
- package/dist/esm/DataViewTableTree/DataViewTableTree.test.js +4 -0
- package/dist/esm/DataViewTh/DataViewTh.d.ts +32 -0
- package/dist/esm/DataViewTh/DataViewTh.js +215 -0
- package/dist/esm/DataViewTh/index.d.ts +2 -0
- package/dist/esm/DataViewTh/index.js +2 -0
- package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.d.ts +26 -0
- package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.js +225 -0
- package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.test.d.ts +1 -0
- package/dist/esm/DataViewTreeFilter/DataViewTreeFilter.test.js +166 -0
- package/dist/esm/DataViewTreeFilter/index.d.ts +2 -0
- package/dist/esm/DataViewTreeFilter/index.js +2 -0
- package/dist/esm/Hooks/selection.d.ts +1 -0
- package/dist/esm/Hooks/selection.js +5 -1
- package/dist/esm/Hooks/selection.test.js +48 -0
- package/dist/esm/InternalContext/InternalContext.d.ts +2 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +6 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/generate-fed-package-json.js +18 -0
- package/generate-index.js +2 -2
- package/package.json +12 -12
- package/patternfly-docs/content/extensions/data-view/examples/DataView/DataView.md +10 -4
- package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableExpandableExample.tsx +108 -0
- package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableInteractiveExample.tsx +148 -0
- package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableResizableColumnsExample.tsx +155 -0
- package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableStickyExample.tsx +90 -0
- package/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableTreeExample.tsx +1 -0
- package/patternfly-docs/content/extensions/data-view/examples/Table/Table.md +113 -14
- package/patternfly-docs/content/extensions/data-view/examples/Toolbar/SelectionExample.tsx +14 -3
- package/patternfly-docs/content/extensions/data-view/examples/Toolbar/Toolbar.md +10 -2
- package/patternfly-docs/content/extensions/data-view/examples/Toolbar/TreeFilterExample.tsx +248 -0
- package/patternfly-docs/patternfly-docs.config.js +4 -1
- package/release.config.js +1 -1
- package/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap +0 -2
- package/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap +0 -2
- package/src/DataViewTable/DataViewTable.tsx +51 -28
- package/src/DataViewTable/__snapshots__/DataViewTable.test.tsx.snap +17 -25
- package/src/DataViewTableBasic/DataViewTableBasic.test.tsx +54 -12
- package/src/DataViewTableBasic/DataViewTableBasic.tsx +104 -10
- package/src/DataViewTableBasic/__snapshots__/DataViewTableBasic.test.tsx.snap +30 -30
- package/src/DataViewTableHead/DataViewTableHead.tsx +24 -23
- package/src/DataViewTableHead/__snapshots__/DataViewTableHead.test.tsx.snap +15 -15
- package/src/DataViewTableTree/DataViewTableTree.test.tsx +9 -0
- package/src/DataViewTableTree/DataViewTableTree.tsx +35 -1
- package/src/DataViewTableTree/__snapshots__/DataViewTableTree.test.tsx.snap +977 -28
- package/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap +0 -3
- package/src/DataViewTh/DataViewTh.tsx +342 -0
- package/src/DataViewTh/index.ts +2 -0
- package/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap +0 -10
- package/src/DataViewTreeFilter/DataViewTreeFilter.test.tsx +222 -0
- package/src/DataViewTreeFilter/DataViewTreeFilter.tsx +361 -0
- package/src/DataViewTreeFilter/__snapshots__/DataViewTreeFilter.test.tsx.snap +199 -0
- package/src/DataViewTreeFilter/index.ts +2 -0
- package/src/Hooks/selection.test.tsx +65 -1
- package/src/Hooks/selection.ts +6 -1
- package/src/InternalContext/InternalContext.tsx +2 -0
- package/src/index.ts +9 -0
|
@@ -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,7 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
14
|
exports.DataViewTable = exports.isDataViewTrObject = exports.isDataViewTdObject = exports.isDataViewThObject = void 0;
|
|
4
15
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
16
|
+
const react_table_1 = require("@patternfly/react-table");
|
|
5
17
|
const DataViewTableTree_1 = require("../DataViewTableTree");
|
|
6
18
|
const DataViewTableBasic_1 = require("../DataViewTableBasic");
|
|
7
19
|
const isDataViewThObject = (value) => value != null && typeof value === 'object' && 'cell' in value;
|
|
@@ -10,6 +22,14 @@ const isDataViewTdObject = (value) => value != null && typeof value === 'object'
|
|
|
10
22
|
exports.isDataViewTdObject = isDataViewTdObject;
|
|
11
23
|
const isDataViewTrObject = (value) => value != null && typeof value === 'object' && 'row' in value;
|
|
12
24
|
exports.isDataViewTrObject = isDataViewTrObject;
|
|
13
|
-
const DataViewTable = (props) =>
|
|
25
|
+
const DataViewTable = (props) => {
|
|
26
|
+
if (props.isTreeTable) {
|
|
27
|
+
return (0, jsx_runtime_1.jsx)(DataViewTableTree_1.DataViewTableTree, Object.assign({}, props));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const { isResizable } = props, rest = __rest(props, ["isResizable"]);
|
|
31
|
+
return isResizable ? ((0, jsx_runtime_1.jsx)(react_table_1.InnerScrollContainer, { children: (0, jsx_runtime_1.jsx)(DataViewTableBasic_1.DataViewTableBasic, Object.assign({ hasResizableColumns: true }, rest)) })) : ((0, jsx_runtime_1.jsx)(DataViewTableBasic_1.DataViewTableBasic, Object.assign({}, rest)));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
14
34
|
exports.DataViewTable = DataViewTable;
|
|
15
35
|
exports.default = exports.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;
|
|
@@ -19,14 +19,26 @@ const InternalContext_1 = require("../InternalContext");
|
|
|
19
19
|
const DataViewTableHead_1 = require("../DataViewTableHead");
|
|
20
20
|
const DataViewTable_1 = require("../DataViewTable");
|
|
21
21
|
const DataViewTableBasic = (_a) => {
|
|
22
|
-
var { columns, rows, ouiaId = 'DataViewTableBasic', headStates, bodyStates } = _a, props = __rest(_a, ["columns", "rows", "ouiaId", "headStates", "bodyStates"]);
|
|
22
|
+
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"]);
|
|
23
23
|
const { selection, activeState, isSelectable } = (0, InternalContext_1.useInternalContext)();
|
|
24
24
|
const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
|
|
25
25
|
const activeHeadState = (0, react_1.useMemo)(() => activeState ? headStates === null || headStates === void 0 ? void 0 : headStates[activeState] : undefined, [activeState, headStates]);
|
|
26
26
|
const activeBodyState = (0, react_1.useMemo)(() => activeState ? bodyStates === null || bodyStates === void 0 ? void 0 : bodyStates[activeState] : undefined, [activeState, bodyStates]);
|
|
27
|
+
const [expandedRowsState, setExpandedRowsState] = (0, react_1.useState)({});
|
|
28
|
+
const [expandedColumnIndex, setExpandedColumnIndex] = (0, react_1.useState)({});
|
|
29
|
+
const tableRef = (0, react_1.useRef)(null);
|
|
30
|
+
const needsSeparateTbody = isExpandable;
|
|
27
31
|
const renderedRows = (0, react_1.useMemo)(() => rows.map((row, rowIndex) => {
|
|
28
32
|
const rowIsObject = (0, DataViewTable_1.isDataViewTrObject)(row);
|
|
29
|
-
|
|
33
|
+
const isRowExpanded = expandedRowsState[rowIndex] || false;
|
|
34
|
+
const expandedColIndex = expandedColumnIndex[rowIndex];
|
|
35
|
+
// Get the first cell to extract the row ID
|
|
36
|
+
const rowData = rowIsObject ? row.row : row;
|
|
37
|
+
const firstCell = rowData[0];
|
|
38
|
+
const rowId = (0, DataViewTable_1.isDataViewTdObject)(firstCell) ? firstCell.id : undefined;
|
|
39
|
+
// Find all expandable contents for this row
|
|
40
|
+
const rowExpandableContents = isExpandable ? expandedRows === null || expandedRows === void 0 ? void 0 : expandedRows.filter((content) => content.rowId === rowId) : [];
|
|
41
|
+
const rowContent = ((0, jsx_runtime_1.jsxs)(react_table_1.Tr, Object.assign({ ouiaId: `${ouiaId}-tr-${rowIndex}` }, (rowIsObject && (row === null || row === void 0 ? void 0 : row.props)), { isContentExpanded: isRowExpanded, isControlRow: true, children: [isSelectable && ((0, jsx_runtime_1.jsx)(react_table_1.Td, { select: {
|
|
30
42
|
rowIndex,
|
|
31
43
|
onSelect: (_event, isSelecting) => {
|
|
32
44
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(isSelecting, rowIsObject ? row : [row]);
|
|
@@ -36,10 +48,38 @@ const DataViewTableBasic = (_a) => {
|
|
|
36
48
|
} }, `select-${rowIndex}`)), (rowIsObject ? row.row : row).map((cell, colIndex) => {
|
|
37
49
|
var _a;
|
|
38
50
|
const cellIsObject = (0, DataViewTable_1.isDataViewTdObject)(cell);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
const cellExpandableContent = isExpandable ? expandedRows === null || expandedRows === void 0 ? void 0 : expandedRows.find((content) => content.rowId === rowId && content.columnId === colIndex) : undefined;
|
|
52
|
+
return ((0, jsx_runtime_1.jsx)(react_table_1.Td, Object.assign({}, (cellIsObject && ((_a = cell === null || cell === void 0 ? void 0 : cell.props) !== null && _a !== void 0 ? _a : {})), (cellExpandableContent != null && {
|
|
53
|
+
compoundExpand: {
|
|
54
|
+
isExpanded: isRowExpanded && expandedColIndex === colIndex,
|
|
55
|
+
expandId: `expandable-${rowIndex}`,
|
|
56
|
+
onToggle: () => {
|
|
57
|
+
setExpandedRowsState(prev => {
|
|
58
|
+
const isSameColumn = expandedColIndex === colIndex;
|
|
59
|
+
const wasExpanded = prev[rowIndex];
|
|
60
|
+
return Object.assign(Object.assign({}, prev), { [rowIndex]: isSameColumn ? !wasExpanded : true });
|
|
61
|
+
});
|
|
62
|
+
setExpandedColumnIndex(prev => (Object.assign(Object.assign({}, prev), { [rowIndex]: colIndex })));
|
|
63
|
+
},
|
|
64
|
+
rowIndex,
|
|
65
|
+
columnIndex: colIndex
|
|
66
|
+
}
|
|
67
|
+
}), { "data-ouia-component-id": `${ouiaId}-td-${rowIndex}-${colIndex}`, children: cellIsObject ? cell.cell : cell }), colIndex));
|
|
68
|
+
})] }), needsSeparateTbody ? undefined : rowIndex));
|
|
69
|
+
if (needsSeparateTbody) {
|
|
70
|
+
return ((0, jsx_runtime_1.jsxs)(react_table_1.Tbody, { isExpanded: isRowExpanded, children: [rowContent, rowExpandableContents === null || rowExpandableContents === void 0 ? void 0 : rowExpandableContents.map((expandableContent) => ((0, jsx_runtime_1.jsx)(react_table_1.Tr, { isExpanded: isRowExpanded && expandedColIndex === expandableContent.columnId, children: (0, jsx_runtime_1.jsx)(react_table_1.Td, { colSpan: rowData.length + (isSelectable ? 1 : 0), "data-expanded-column-index": expandableContent.columnId, children: (0, jsx_runtime_1.jsx)(react_table_1.ExpandableRowContent, { children: expandableContent.content }) }) }, `expand-${rowIndex}-${expandableContent.columnId}`)))] }, rowIndex));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
return rowContent;
|
|
74
|
+
}
|
|
75
|
+
}), [rows, isSelectable, isSelected, isSelectDisabled, onSelect, ouiaId, expandedRowsState, expandedColumnIndex, expandedRows, isExpandable, needsSeparateTbody]);
|
|
76
|
+
const bodyContent = activeBodyState || (needsSeparateTbody ? renderedRows : (0, jsx_runtime_1.jsx)(react_table_1.Tbody, { children: renderedRows }));
|
|
77
|
+
if (isSticky) {
|
|
78
|
+
return ((0, jsx_runtime_1.jsx)(react_table_1.OuterScrollContainer, { children: (0, jsx_runtime_1.jsx)(react_table_1.InnerScrollContainer, { children: (0, jsx_runtime_1.jsxs)(react_table_1.Table, Object.assign({ ref: tableRef, "aria-label": "Data table", ouiaId: ouiaId, isExpandable: isExpandable, hasAnimations: true }, props, { isStickyHeader: true, children: [activeHeadState || (0, jsx_runtime_1.jsx)(DataViewTableHead_1.DataViewTableHead, { columns: columns, ouiaId: ouiaId, hasResizableColumns: hasResizableColumns }), bodyContent] })) }) }));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return ((0, jsx_runtime_1.jsxs)(react_table_1.Table, Object.assign({ ref: tableRef, "aria-label": "Data table", ouiaId: ouiaId, isExpandable: isExpandable, hasAnimations: true }, props, { children: [activeHeadState || (0, jsx_runtime_1.jsx)(DataViewTableHead_1.DataViewTableHead, { columns: columns, ouiaId: ouiaId, hasResizableColumns: hasResizableColumns }), bodyContent] })));
|
|
82
|
+
}
|
|
43
83
|
};
|
|
44
84
|
exports.DataViewTableBasic = DataViewTableBasic;
|
|
45
85
|
exports.default = exports.DataViewTableBasic;
|
|
@@ -1,21 +1,41 @@
|
|
|
1
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
|
+
};
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
15
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
16
|
const react_1 = require("@testing-library/react");
|
|
17
|
+
const user_event_1 = __importDefault(require("@testing-library/user-event"));
|
|
5
18
|
const DataView_1 = require("../DataView");
|
|
6
19
|
const DataViewTableBasic_1 = require("./DataViewTableBasic");
|
|
7
20
|
const repositories = [
|
|
8
|
-
{ name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
|
|
9
|
-
{ name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
|
|
10
|
-
{ name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
|
|
11
|
-
{ name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
|
|
12
|
-
{ name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
|
|
13
|
-
{ name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
|
|
21
|
+
{ id: 1, name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
|
|
22
|
+
{ id: 2, name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
|
|
23
|
+
{ id: 3, name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
|
|
24
|
+
{ id: 4, name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
|
|
25
|
+
{ id: 5, name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
|
|
26
|
+
{ id: 6, name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
|
|
14
27
|
];
|
|
15
|
-
const rows = repositories.map(
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
const rows = repositories.map(({ id, name, branches, prs, workspaces, lastCommit }) => [
|
|
29
|
+
{ id, cell: name },
|
|
30
|
+
branches,
|
|
31
|
+
prs,
|
|
32
|
+
workspaces,
|
|
33
|
+
lastCommit
|
|
34
|
+
]);
|
|
18
35
|
const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];
|
|
36
|
+
const expandableContents = [
|
|
37
|
+
{ rowId: 1, columnId: 1, content: (0, jsx_runtime_1.jsx)("div", { children: "Branch details for Repository one" }) },
|
|
38
|
+
];
|
|
19
39
|
const ouiaId = 'TableExample';
|
|
20
40
|
describe('DataViewTable component', () => {
|
|
21
41
|
test('should render correctly', () => {
|
|
@@ -34,4 +54,22 @@ describe('DataViewTable component', () => {
|
|
|
34
54
|
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(DataView_1.DataView, { activeState: "loading", children: (0, jsx_runtime_1.jsx)(DataViewTableBasic_1.DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, bodyStates: { loading: "Data is loading" }, rows: [] }) }));
|
|
35
55
|
expect(container).toMatchSnapshot();
|
|
36
56
|
});
|
|
57
|
+
test('when isExpandable cell should be clickable and expandable', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
var _a, _b, _c;
|
|
59
|
+
const user = user_event_1.default.setup();
|
|
60
|
+
(0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewTableBasic_1.DataViewTableBasic, { "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, rows: rows, isExpandable: true, expandedRows: expandableContents }));
|
|
61
|
+
// Initially, expandable content is rendered but should be hidden (not visible)
|
|
62
|
+
const initialBranchContent = react_1.screen.getByText('Branch details for Repository one');
|
|
63
|
+
expect((_a = initialBranchContent.closest('tr')) === null || _a === void 0 ? void 0 : _a.classList.contains('pf-m-expanded')).toBeFalsy();
|
|
64
|
+
// Find the first expandable button by ID
|
|
65
|
+
const branchExpandButton = document.getElementById('expandable-0-0-1');
|
|
66
|
+
expect(branchExpandButton).toBeTruthy();
|
|
67
|
+
// Verify the button is in the cell with "Branch one" text
|
|
68
|
+
expect((_b = branchExpandButton === null || branchExpandButton === void 0 ? void 0 : branchExpandButton.closest('td')) === null || _b === void 0 ? void 0 : _b.textContent).toContain('Branch one');
|
|
69
|
+
// Click the expand button for Branches column
|
|
70
|
+
yield user.click(branchExpandButton);
|
|
71
|
+
// After clicking, the expandable content should be visible
|
|
72
|
+
const branchContent = react_1.screen.getByText('Branch details for Repository one');
|
|
73
|
+
expect((_c = branchContent.closest('tr')) === null || _c === void 0 ? void 0 : _c.classList.contains('pf-m-expanded')).toBeTruthy();
|
|
74
|
+
}));
|
|
37
75
|
});
|
|
@@ -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;
|
|
@@ -17,17 +17,18 @@ const react_1 = require("react");
|
|
|
17
17
|
const react_table_1 = require("@patternfly/react-table");
|
|
18
18
|
const InternalContext_1 = require("../InternalContext");
|
|
19
19
|
const DataViewTable_1 = require("../DataViewTable");
|
|
20
|
+
const DataViewTh_1 = require("../DataViewTh/DataViewTh");
|
|
20
21
|
const DataViewTableHead = (_a) => {
|
|
21
|
-
var { isTreeTable = false, columns, ouiaId = 'DataViewTableHead' } = _a, props = __rest(_a, ["isTreeTable", "columns", "ouiaId"]);
|
|
22
|
+
var { isTreeTable = false, columns, ouiaId = 'DataViewTableHead', hasResizableColumns } = _a, props = __rest(_a, ["isTreeTable", "columns", "ouiaId", "hasResizableColumns"]);
|
|
22
23
|
const { selection } = (0, InternalContext_1.useInternalContext)();
|
|
23
24
|
const { onSelect, isSelected } = selection !== null && selection !== void 0 ? selection : {};
|
|
24
25
|
const cells = (0, react_1.useMemo)(() => [
|
|
25
|
-
onSelect && isSelected && !isTreeTable ? ((0, jsx_runtime_1.jsx)(react_table_1.Th, { screenReaderText:
|
|
26
|
+
onSelect && isSelected && !isTreeTable ? ((0, jsx_runtime_1.jsx)(react_table_1.Th, { screenReaderText: "Data selection table head cell" }, "row-select")) : null,
|
|
26
27
|
...columns.map((column, index) => {
|
|
27
28
|
var _a;
|
|
28
|
-
return ((0, jsx_runtime_1.jsx)(
|
|
29
|
+
return ((0, jsx_runtime_1.jsx)(DataViewTh_1.DataViewTh, { content: (0, DataViewTable_1.isDataViewThObject)(column) ? column.cell : column, resizableProps: (0, DataViewTable_1.isDataViewThObject)(column) ? column.resizableProps : undefined, "data-ouia-component-id": `${ouiaId}-th-${index}`, thProps: (0, DataViewTable_1.isDataViewThObject)(column) ? ((_a = column === null || column === void 0 ? void 0 : column.props) !== null && _a !== void 0 ? _a : {}) : {}, hasResizableColumns: hasResizableColumns }, index));
|
|
29
30
|
})
|
|
30
|
-
], [columns, ouiaId, onSelect, isSelected, isTreeTable]);
|
|
31
|
+
], [columns, ouiaId, onSelect, isSelected, isTreeTable, hasResizableColumns]);
|
|
31
32
|
return ((0, jsx_runtime_1.jsx)(react_table_1.Thead, Object.assign({ "data-ouia-component-id": `${ouiaId}-thead` }, props, { children: (0, jsx_runtime_1.jsx)(react_table_1.Tr, { ouiaId: `${ouiaId}-tr-head`, children: cells }) })));
|
|
32
33
|
};
|
|
33
34
|
exports.DataViewTableHead = 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
|
}
|
|
@@ -45,11 +45,38 @@ const getNodesAffectedBySelection = (allRows, node, isChecking, isSelected) => {
|
|
|
45
45
|
return Array.from(affectedNodes);
|
|
46
46
|
};
|
|
47
47
|
const DataViewTableTree = (_a) => {
|
|
48
|
-
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"]);
|
|
48
|
+
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"]);
|
|
49
49
|
const { selection, activeState } = (0, InternalContext_1.useInternalContext)();
|
|
50
50
|
const { onSelect, isSelected, isSelectDisabled } = selection !== null && selection !== void 0 ? selection : {};
|
|
51
51
|
const [expandedNodeIds, setExpandedNodeIds] = (0, react_1.useState)([]);
|
|
52
52
|
const [expandedDetailsNodeNames, setExpandedDetailsNodeIds] = (0, react_1.useState)([]);
|
|
53
|
+
// Helper function to collect all node IDs that have children (are expandable)
|
|
54
|
+
const getExpandableNodeIds = (nodes) => {
|
|
55
|
+
const expandableIds = [];
|
|
56
|
+
const traverse = (nodeList) => {
|
|
57
|
+
nodeList.forEach(node => {
|
|
58
|
+
if (node.children && node.children.length > 0) {
|
|
59
|
+
expandableIds.push(node.id);
|
|
60
|
+
traverse(node.children);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
traverse(nodes);
|
|
65
|
+
return expandableIds;
|
|
66
|
+
};
|
|
67
|
+
// Effect to handle expandAll behavior
|
|
68
|
+
// Memoize the expandable IDs to avoid recalculating when rows object reference changes but structure is the same
|
|
69
|
+
const expandableIds = (0, react_1.useMemo)(() => getExpandableNodeIds(rows), [rows]);
|
|
70
|
+
// Effect to handle expandAll behavior - only runs when IDs actually change
|
|
71
|
+
(0, react_1.useEffect)(() => {
|
|
72
|
+
if (expandAll) {
|
|
73
|
+
setExpandedNodeIds(expandableIds);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
setExpandedNodeIds([]);
|
|
77
|
+
}
|
|
78
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
|
+
}, [expandAll, expandableIds.join(',')]);
|
|
53
80
|
const activeHeadState = (0, react_1.useMemo)(() => activeState ? headStates === null || headStates === void 0 ? void 0 : headStates[activeState] : undefined, [activeState, headStates]);
|
|
54
81
|
const activeBodyState = (0, react_1.useMemo)(() => activeState ? bodyStates === null || bodyStates === void 0 ? void 0 : bodyStates[activeState] : undefined, [activeState, bodyStates]);
|
|
55
82
|
const nodes = (0, react_1.useMemo)(() => {
|
|
@@ -76,6 +76,10 @@ describe('DataViewTableTree component', () => {
|
|
|
76
76
|
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(DataView_1.DataView, { activeState: "error", children: (0, jsx_runtime_1.jsx)(DataViewTable_1.DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, bodyStates: { error: "Some error" }, rows: [] }) }));
|
|
77
77
|
expect(container).toMatchSnapshot();
|
|
78
78
|
});
|
|
79
|
+
test('should render tree table with all expandable nodes expanded', () => {
|
|
80
|
+
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(DataView_1.DataView, { selection: mockSelection, children: (0, jsx_runtime_1.jsx)(DataViewTable_1.DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, expandAll: true, rows: rows, leafIcon: (0, jsx_runtime_1.jsx)(react_icons_1.LeafIcon, {}), expandedIcon: (0, jsx_runtime_1.jsx)(react_icons_1.FolderOpenIcon, { "aria-hidden": true }), collapsedIcon: (0, jsx_runtime_1.jsx)(react_icons_1.FolderIcon, { "aria-hidden": true }) }) }));
|
|
81
|
+
expect(container).toMatchSnapshot();
|
|
82
|
+
});
|
|
79
83
|
test('should render tree table with a loading state', () => {
|
|
80
84
|
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(DataView_1.DataView, { activeState: "loading", children: (0, jsx_runtime_1.jsx)(DataViewTable_1.DataViewTable, { isTreeTable: true, "aria-label": 'Repositories table', ouiaId: ouiaId, columns: columns, bodyStates: { loading: "Data is loading" }, rows: [] }) }));
|
|
81
85
|
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;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DataViewTh = void 0;
|
|
18
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
|
+
const react_1 = require("react");
|
|
20
|
+
const react_table_1 = require("@patternfly/react-table");
|
|
21
|
+
const react_core_1 = require("@patternfly/react-core");
|
|
22
|
+
const react_jss_1 = require("react-jss");
|
|
23
|
+
const c_table_cell_PaddingBlockEnd_1 = __importDefault(require("@patternfly/react-tokens/dist/esm/c_table_cell_PaddingBlockEnd"));
|
|
24
|
+
const c_table_cell_PaddingInlineEnd_1 = __importDefault(require("@patternfly/react-tokens/dist/esm/c_table_cell_PaddingInlineEnd"));
|
|
25
|
+
const t_global_font_size_body_default_1 = __importDefault(require("@patternfly/react-tokens/dist/esm/t_global_font_size_body_default"));
|
|
26
|
+
const ResizeIcon = () => ((0, jsx_runtime_1.jsx)("svg", { className: "pf-v6-svg", viewBox: "0 0 1024 1024", fill: "currentColor", "aria-hidden": "true", role: "img", width: "1em", height: "1em", children: (0, jsx_runtime_1.jsx)("path", { fillRule: "evenodd", d: "M52.7,529.8l190.5,161.9c18.6,15.9,50.5,4.7,50.5-17.8v-324c0-22.4-31.8-33.6-50.5-17.8L52.7,494.2c-11.5,9.8-11.5,25.8,0,35.6ZM480.8,12.9h62.4v998.3h-62.4V12.9ZM971.3,529.8l-190.5,161.9c-18.6,15.9-50.5,4.7-50.5-17.8v-324c0-22.4,31.8-33.6,50.5-17.8l190.5,161.9c11.5,9.8,11.5,25.8,0,35.6Z" }) }));
|
|
27
|
+
const useStyles = (0, react_jss_1.createUseStyles)({
|
|
28
|
+
dataViewResizeableTh: {
|
|
29
|
+
[c_table_cell_PaddingInlineEnd_1.default.name]: `calc(${t_global_font_size_body_default_1.default.var} * 2)`
|
|
30
|
+
},
|
|
31
|
+
dataViewResizableButton: {
|
|
32
|
+
position: 'absolute',
|
|
33
|
+
insetInlineEnd: `calc(${t_global_font_size_body_default_1.default.var} / 2)`,
|
|
34
|
+
insetBlockEnd: c_table_cell_PaddingBlockEnd_1.default.var,
|
|
35
|
+
cursor: 'grab',
|
|
36
|
+
'&:active': {
|
|
37
|
+
cursor: 'grabbing'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const DataViewTh = (_a) => {
|
|
42
|
+
var { content, resizableProps = {}, hasResizableColumns = false, thProps } = _a, props = __rest(_a, ["content", "resizableProps", "hasResizableColumns", "thProps"]);
|
|
43
|
+
const thRef = (0, react_1.useRef)(null);
|
|
44
|
+
const [width, setWidth] = (0, react_1.useState)((resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.width) ? resizableProps.width : 0);
|
|
45
|
+
// Tracks the current column width for the onResize callback, because the width state is not updated until after the resize is complete
|
|
46
|
+
const trackedWidth = (0, react_1.useRef)(0);
|
|
47
|
+
const classes = useStyles();
|
|
48
|
+
const isResizable = (resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.isResizable) || false;
|
|
49
|
+
const increment = (resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.increment) || 5;
|
|
50
|
+
const shiftIncrement = (resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.shiftIncrement) || 25;
|
|
51
|
+
const resizeButtonAriaLabel = resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.resizeButtonAriaLabel;
|
|
52
|
+
const onResize = (resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.onResize) || undefined;
|
|
53
|
+
const screenReaderText = (resizableProps === null || resizableProps === void 0 ? void 0 : resizableProps.screenReaderText) || `Column ${width.toFixed(0)} pixels`;
|
|
54
|
+
const dataViewThClassName = isResizable ? classes.dataViewResizeableTh : undefined;
|
|
55
|
+
const resizeButtonRef = (0, react_1.useRef)(null);
|
|
56
|
+
const setInitialVals = (0, react_1.useRef)(true);
|
|
57
|
+
const dragOffset = (0, react_1.useRef)(0);
|
|
58
|
+
const isResizing = (0, react_1.useRef)(false);
|
|
59
|
+
const isInView = (0, react_1.useRef)(true);
|
|
60
|
+
if (isResizable && !resizeButtonAriaLabel) {
|
|
61
|
+
// eslint-disable-next-line no-console
|
|
62
|
+
console.warn('DataViewTh: Missing resizeButtonAriaLabel. An aria label must be passed to each resizable column to provide a context specific label for its resize button.');
|
|
63
|
+
}
|
|
64
|
+
(0, react_1.useEffect)(() => {
|
|
65
|
+
if (!isResizable) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const observed = resizeButtonRef.current;
|
|
69
|
+
const observer = new IntersectionObserver(([entry]) => {
|
|
70
|
+
isInView.current = entry.isIntersecting;
|
|
71
|
+
}, { threshold: 0.3 });
|
|
72
|
+
if (observed) {
|
|
73
|
+
observer.observe(observed);
|
|
74
|
+
}
|
|
75
|
+
return () => {
|
|
76
|
+
if (observed) {
|
|
77
|
+
observer.unobserve(observed);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}, []);
|
|
81
|
+
(0, react_1.useEffect)(() => {
|
|
82
|
+
var _a;
|
|
83
|
+
if ((isResizable || hasResizableColumns) && setInitialVals.current && width === 0) {
|
|
84
|
+
setWidth(((_a = thRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0);
|
|
85
|
+
setInitialVals.current = false;
|
|
86
|
+
}
|
|
87
|
+
}, [isResizable, hasResizableColumns, setInitialVals]);
|
|
88
|
+
const setDragOffset = (e) => {
|
|
89
|
+
var _a, _b;
|
|
90
|
+
const isRTL = (0, react_core_1.getLanguageDirection)(thRef.current) === 'rtl';
|
|
91
|
+
const startingMousePos = 'clientX' in e ? e.clientX : e.touches[0].clientX;
|
|
92
|
+
const startingColumnPos = (isRTL ? (_a = thRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left : (_b = thRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect().right) || 0;
|
|
93
|
+
dragOffset.current = startingColumnPos - startingMousePos;
|
|
94
|
+
};
|
|
95
|
+
const handleMousedown = (e) => {
|
|
96
|
+
e.stopPropagation();
|
|
97
|
+
e.preventDefault();
|
|
98
|
+
document.addEventListener('mousemove', callbackMouseMove);
|
|
99
|
+
document.addEventListener('mouseup', callbackMouseUp);
|
|
100
|
+
// When a user begins resizing a column, set the drag offset so the drag motion aligns with the column edge
|
|
101
|
+
if (dragOffset.current === 0) {
|
|
102
|
+
setDragOffset(e);
|
|
103
|
+
}
|
|
104
|
+
isResizing.current = true;
|
|
105
|
+
};
|
|
106
|
+
const handleMouseMove = (e) => {
|
|
107
|
+
const mousePos = e.clientX;
|
|
108
|
+
handleControlMove(e, dragOffset.current + mousePos);
|
|
109
|
+
};
|
|
110
|
+
const handleTouchStart = (e) => {
|
|
111
|
+
e.stopPropagation();
|
|
112
|
+
document.addEventListener('touchmove', callbackTouchMove, { passive: false });
|
|
113
|
+
document.addEventListener('touchend', callbackTouchEnd);
|
|
114
|
+
// When a user begins resizing a column, set the drag offset so the drag motion aligns with the column edge
|
|
115
|
+
if (dragOffset.current === 0) {
|
|
116
|
+
setDragOffset(e);
|
|
117
|
+
}
|
|
118
|
+
isResizing.current = true;
|
|
119
|
+
};
|
|
120
|
+
const handleTouchMove = (e) => {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
e.stopImmediatePropagation();
|
|
123
|
+
const touchPos = e.touches[0].clientX;
|
|
124
|
+
handleControlMove(e, touchPos);
|
|
125
|
+
};
|
|
126
|
+
const handleControlMove = (e, controlPosition) => {
|
|
127
|
+
var _a, _b;
|
|
128
|
+
e.stopPropagation();
|
|
129
|
+
if (!isResizing.current) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const columnRect = (_a = thRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
133
|
+
if (columnRect === undefined) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const mousePos = controlPosition;
|
|
137
|
+
const isRTL = (0, react_core_1.getLanguageDirection)(thRef.current) === 'rtl';
|
|
138
|
+
let newSize = isRTL ? (columnRect === null || columnRect === void 0 ? void 0 : columnRect.right) - mousePos : mousePos - (columnRect === null || columnRect === void 0 ? void 0 : columnRect.left);
|
|
139
|
+
// Prevent the column from shrinking below a specified minimum width
|
|
140
|
+
if (resizableProps.minWidth && newSize < resizableProps.minWidth) {
|
|
141
|
+
newSize = resizableProps.minWidth;
|
|
142
|
+
}
|
|
143
|
+
(_b = thRef.current) === null || _b === void 0 ? void 0 : _b.style.setProperty('min-width', newSize + 'px');
|
|
144
|
+
trackedWidth.current = newSize;
|
|
145
|
+
setWidth(newSize);
|
|
146
|
+
};
|
|
147
|
+
const handleMouseup = (e) => {
|
|
148
|
+
var _a;
|
|
149
|
+
if (!isResizing.current) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// Reset the isResizing and dragOffset values to their initial states
|
|
153
|
+
isResizing.current = false;
|
|
154
|
+
dragOffset.current = 0;
|
|
155
|
+
// Call the onResize callback with the new width
|
|
156
|
+
onResize && onResize(e, thProps === null || thProps === void 0 ? void 0 : thProps.id, trackedWidth.current);
|
|
157
|
+
// Handle scroll into view when column drag button is moved off screen
|
|
158
|
+
if (resizeButtonRef.current && !isInView.current) {
|
|
159
|
+
(_a = resizeButtonRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
160
|
+
}
|
|
161
|
+
document.removeEventListener('mousemove', callbackMouseMove);
|
|
162
|
+
document.removeEventListener('mouseup', callbackMouseUp);
|
|
163
|
+
};
|
|
164
|
+
const handleTouchEnd = (e) => {
|
|
165
|
+
e.stopPropagation();
|
|
166
|
+
if (!isResizing) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// Reset the isResizing and dragOffset values to their initial states
|
|
170
|
+
isResizing.current = false;
|
|
171
|
+
dragOffset.current = 0;
|
|
172
|
+
// Call the onResize callback with the new width
|
|
173
|
+
onResize && onResize(e, thProps === null || thProps === void 0 ? void 0 : thProps.id, trackedWidth.current);
|
|
174
|
+
document.removeEventListener('touchmove', callbackTouchMove);
|
|
175
|
+
document.removeEventListener('touchend', callbackTouchEnd);
|
|
176
|
+
};
|
|
177
|
+
const callbackMouseMove = (0, react_1.useCallback)(handleMouseMove, []);
|
|
178
|
+
const callbackTouchEnd = (0, react_1.useCallback)(handleTouchEnd, []);
|
|
179
|
+
const callbackTouchMove = (0, react_1.useCallback)(handleTouchMove, []);
|
|
180
|
+
const callbackMouseUp = (0, react_1.useCallback)(handleMouseup, []);
|
|
181
|
+
const handleKeys = (e) => {
|
|
182
|
+
var _a, _b;
|
|
183
|
+
const key = e.key;
|
|
184
|
+
if (key === 'Tab') {
|
|
185
|
+
isResizing.current = false;
|
|
186
|
+
}
|
|
187
|
+
if (key !== 'ArrowLeft' && key !== 'ArrowRight') {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
isResizing.current = true;
|
|
192
|
+
const isRTL = (0, react_core_1.getLanguageDirection)(thRef.current) === 'rtl';
|
|
193
|
+
const columnRect = (_a = thRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
194
|
+
let newSize = (columnRect === null || columnRect === void 0 ? void 0 : columnRect.width) || 0;
|
|
195
|
+
let delta = 0;
|
|
196
|
+
const _increment = e.shiftKey ? shiftIncrement : increment;
|
|
197
|
+
if (key === 'ArrowRight') {
|
|
198
|
+
if (isRTL) {
|
|
199
|
+
delta = -_increment;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
delta = _increment;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (key === 'ArrowLeft') {
|
|
206
|
+
if (isRTL) {
|
|
207
|
+
delta = _increment;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
delta = -_increment;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
newSize = newSize + delta;
|
|
214
|
+
(_b = thRef.current) === null || _b === void 0 ? void 0 : _b.style.setProperty('min-width', newSize + 'px');
|
|
215
|
+
setWidth(newSize);
|
|
216
|
+
onResize && onResize(e, thProps === null || thProps === void 0 ? void 0 : thProps.id, newSize);
|
|
217
|
+
};
|
|
218
|
+
const resizableContent = ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { "aria-live": "polite", className: "pf-v6-screen-reader", children: screenReaderText }), (0, jsx_runtime_1.jsx)(react_core_1.Button, { ref: resizeButtonRef, variant: "plain", hasNoPadding: true, icon: (0, jsx_runtime_1.jsx)(ResizeIcon, {}), onMouseDown: handleMousedown, onKeyDown: handleKeys, onTouchStart: handleTouchStart, "aria-label": resizeButtonAriaLabel, className: classes.dataViewResizableButton })] }));
|
|
219
|
+
return ((0, jsx_runtime_1.jsx)(react_table_1.Th, Object.assign({}, thProps, props, { style: width > 0 ? { minWidth: width } : undefined, ref: thRef, modifier: "truncate", className: dataViewThClassName }, (isResizable && { additionalContent: resizableContent }), { children: content })));
|
|
220
|
+
};
|
|
221
|
+
exports.DataViewTh = DataViewTh;
|
|
222
|
+
exports.default = exports.DataViewTh;
|
|
@@ -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 DataViewTh_1 = require("./DataViewTh");
|
|
22
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(DataViewTh_1).default; } });
|
|
23
|
+
__exportStar(require("./DataViewTh"), exports);
|