@indico-data/design-system 2.47.3 → 2.49.0
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/lib/components/index.d.ts +1 -0
- package/lib/components/pagination/Pagination.d.ts +2 -0
- package/lib/components/pagination/Pagination.stories.d.ts +6 -0
- package/lib/components/pagination/__tests__/Pagination.test.d.ts +1 -0
- package/lib/components/pagination/index.d.ts +1 -0
- package/lib/components/pagination/types.d.ts +6 -0
- package/lib/components/table/Table.stories.d.ts +1 -0
- package/lib/components/table/__tests__/Table.test.d.ts +1 -0
- package/lib/components/table/components/HorizontalStickyHeader.d.ts +10 -0
- package/lib/components/table/components/TablePagination.d.ts +9 -0
- package/lib/components/table/components/__tests__/HorizontalStickyHeader.test.d.ts +1 -0
- package/lib/components/table/components/__tests__/TablePagination.test.d.ts +1 -0
- package/lib/components/table/components/helpers.d.ts +6 -0
- package/lib/components/table/hooks/usePinnedColumnsManager.d.ts +8 -0
- package/lib/components/table/sampleData.d.ts +6 -0
- package/lib/components/table/types.d.ts +16 -5
- package/lib/components/table/utils/processColumns.d.ts +2 -0
- package/lib/index.css +78 -17
- package/lib/index.d.ts +16 -5
- package/lib/index.esm.css +78 -17
- package/lib/index.esm.js +305 -14
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +304 -13
- package/lib/index.js.map +1 -1
- package/lib/utils/getPreviousHeadersWidth.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/index.ts +1 -0
- package/src/components/pagination/Pagination.mdx +31 -0
- package/src/components/pagination/Pagination.stories.tsx +80 -0
- package/src/components/pagination/Pagination.tsx +117 -0
- package/src/components/pagination/__tests__/Pagination.test.tsx +91 -0
- package/src/components/pagination/index.ts +1 -0
- package/src/components/pagination/styles/Pagination.scss +22 -0
- package/src/components/pagination/types.ts +6 -0
- package/src/components/table/Table.mdx +136 -0
- package/src/components/table/Table.stories.tsx +91 -30
- package/src/components/table/Table.tsx +25 -2
- package/src/components/table/__tests__/Table.test.tsx +10 -0
- package/src/components/table/components/HorizontalStickyHeader.tsx +57 -0
- package/src/components/table/components/TablePagination.tsx +44 -0
- package/src/components/table/components/__tests__/HorizontalStickyHeader.test.tsx +104 -0
- package/src/components/table/components/__tests__/TablePagination.test.tsx +17 -0
- package/src/components/table/components/helpers.ts +90 -0
- package/src/components/table/hooks/usePinnedColumnsManager.ts +146 -0
- package/src/components/table/sampleData.tsx +436 -0
- package/src/components/table/styles/Table.scss +72 -24
- package/src/components/table/styles/_variables.scss +3 -0
- package/src/components/table/types.ts +19 -7
- package/src/components/table/utils/processColumns.tsx +35 -0
- package/src/setup/setupIcons.ts +4 -0
- package/src/setup/setupTests.ts +8 -0
- package/src/styles/index.scss +1 -0
- package/src/utils/getPreviousHeadersWidth.ts +12 -0
- package/src/components/table/sampleData.ts +0 -171
package/lib/index.js
CHANGED
|
@@ -230,7 +230,7 @@ const registerFontAwesomeIcons = (...icons) => {
|
|
|
230
230
|
fontawesomeSvgCore.library.add(...icons);
|
|
231
231
|
};
|
|
232
232
|
// Register the icons used directly in design system components
|
|
233
|
-
registerFontAwesomeIcons(freeSolidSvgIcons.faArrowDown, freeSolidSvgIcons.faArrowRight, freeSolidSvgIcons.faArrowLeft, freeSolidSvgIcons.faCalculator, freeSolidSvgIcons.faCheck, freeSolidSvgIcons.faCircleNotch, freeSolidSvgIcons.faMountainSun, freeSolidSvgIcons.faRocket, freeSolidSvgIcons.faWind, freeSolidSvgIcons.faEyeSlash, freeSolidSvgIcons.faEye, freeSolidSvgIcons.faCaretUp, freeSolidSvgIcons.faCaretDown, freeSolidSvgIcons.faTag, freeSolidSvgIcons.faPencilAlt, freeSolidSvgIcons.faSearch, freeSolidSvgIcons.faCog, freeSolidSvgIcons.faFileDownload, freeSolidSvgIcons.faQuestionCircle, freeSolidSvgIcons.faCopy, freeSolidSvgIcons.faXmark,
|
|
233
|
+
registerFontAwesomeIcons(freeSolidSvgIcons.faArrowDown, freeSolidSvgIcons.faArrowRight, freeSolidSvgIcons.faArrowLeft, freeSolidSvgIcons.faCalculator, freeSolidSvgIcons.faCheck, freeSolidSvgIcons.faCircleNotch, freeSolidSvgIcons.faMountainSun, freeSolidSvgIcons.faRocket, freeSolidSvgIcons.faWind, freeSolidSvgIcons.faEyeSlash, freeSolidSvgIcons.faEye, freeSolidSvgIcons.faCaretUp, freeSolidSvgIcons.faCaretDown, freeSolidSvgIcons.faTag, freeSolidSvgIcons.faPencilAlt, freeSolidSvgIcons.faSearch, freeSolidSvgIcons.faCog, freeSolidSvgIcons.faFileDownload, freeSolidSvgIcons.faQuestionCircle, freeSolidSvgIcons.faCopy, freeSolidSvgIcons.faXmark, freeSolidSvgIcons.faChevronLeft, freeSolidSvgIcons.faChevronRight,
|
|
234
234
|
// backwards compat, don't require registration of custom indicons
|
|
235
235
|
// might want to consider doing so in the future
|
|
236
236
|
...indiconDefinitions);
|
|
@@ -2628,6 +2628,16 @@ function __rest(s, e) {
|
|
|
2628
2628
|
return t;
|
|
2629
2629
|
}
|
|
2630
2630
|
|
|
2631
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
2632
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
2633
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
2634
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
2635
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
2636
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
2637
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2631
2641
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
2632
2642
|
var e = new Error(message);
|
|
2633
2643
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
@@ -7193,18 +7203,6 @@ const LoadingComponent = () => {
|
|
|
7193
7203
|
return jsxRuntime.jsx("div", { className: "table-loading", children: "Loading..." });
|
|
7194
7204
|
};
|
|
7195
7205
|
|
|
7196
|
-
const Table = (props) => {
|
|
7197
|
-
const { responsive = true, direction = 'auto', keyField = 'id', striped = false, noDataComponent = 'built-in', isDisabled, isLoading, isFullHeight = false, subHeaderAlign = 'left', className } = props, rest = __rest(props, ["responsive", "direction", "keyField", "striped", "noDataComponent", "isDisabled", "isLoading", "isFullHeight", "subHeaderAlign", "className"]);
|
|
7198
|
-
const combinedClassName = classNames(className, {
|
|
7199
|
-
'table--striped': striped,
|
|
7200
|
-
'table-body': true,
|
|
7201
|
-
});
|
|
7202
|
-
const tableWrapperClassName = classNames('table', {
|
|
7203
|
-
'table--full-height': isFullHeight,
|
|
7204
|
-
});
|
|
7205
|
-
return (jsxRuntime.jsx("div", { className: tableWrapperClassName, children: jsxRuntime.jsx(Xe, Object.assign({ responsive: responsive, direction: direction, subHeaderAlign: subHeaderAlign, keyField: keyField, striped: striped, className: combinedClassName, disabled: isDisabled, noDataComponent: noDataComponent, progressPending: isLoading, progressComponent: jsxRuntime.jsx(LoadingComponent, {}) }, rest)) }));
|
|
7206
|
-
};
|
|
7207
|
-
|
|
7208
7206
|
const Label = ({ label, name, isRequired }) => {
|
|
7209
7207
|
return (jsxRuntime.jsx("div", { "data-testid": `${name}-testId`, className: `form-label`, children: jsxRuntime.jsxs("label", { htmlFor: `${name}`, children: [label, isRequired ? jsxRuntime.jsx("span", { className: "text-error", children: " *" }) : ''] }) }));
|
|
7210
7208
|
};
|
|
@@ -7238,6 +7236,299 @@ const Input = React__namespace.default.forwardRef((_a, ref) => {
|
|
|
7238
7236
|
});
|
|
7239
7237
|
const LabeledInput = withLabel(Input);
|
|
7240
7238
|
|
|
7239
|
+
const Pagination = (_a) => {
|
|
7240
|
+
var { totalPages, currentPage = 1, onChange, className } = _a, rest = __rest(_a, ["totalPages", "currentPage", "onChange", "className"]);
|
|
7241
|
+
const [inputValue, setInputValue] = React.useState(currentPage.toString());
|
|
7242
|
+
const totalPagesText = `of ${totalPages}`;
|
|
7243
|
+
const classes = classNames('pagination', className);
|
|
7244
|
+
React.useEffect(() => {
|
|
7245
|
+
setInputValue(currentPage.toString());
|
|
7246
|
+
}, [currentPage]);
|
|
7247
|
+
const handleNextPage = () => {
|
|
7248
|
+
if (currentPage < totalPages) {
|
|
7249
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(currentPage + 1);
|
|
7250
|
+
}
|
|
7251
|
+
};
|
|
7252
|
+
const handlePreviousPage = () => {
|
|
7253
|
+
if (currentPage > 1) {
|
|
7254
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(currentPage - 1);
|
|
7255
|
+
}
|
|
7256
|
+
};
|
|
7257
|
+
const validateAndUpdatePage = (value) => {
|
|
7258
|
+
// If empty or invalid, reset to current page
|
|
7259
|
+
if (!value) {
|
|
7260
|
+
setInputValue(currentPage.toString());
|
|
7261
|
+
return;
|
|
7262
|
+
}
|
|
7263
|
+
const page = Number(value);
|
|
7264
|
+
if (!isNaN(page) && page > 0 && page <= totalPages) {
|
|
7265
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(page);
|
|
7266
|
+
}
|
|
7267
|
+
else {
|
|
7268
|
+
setInputValue(currentPage.toString());
|
|
7269
|
+
}
|
|
7270
|
+
};
|
|
7271
|
+
const isNextButtonDisabled = currentPage === totalPages;
|
|
7272
|
+
const isPreviousButtonDisabled = currentPage === 1;
|
|
7273
|
+
const hasError = Number(inputValue) > totalPages || Number(inputValue) < 1;
|
|
7274
|
+
return (jsxRuntime.jsx("div", Object.assign({ className: classes }, rest, { children: jsxRuntime.jsx(Container, { children: jsxRuntime.jsxs(Row, { gutterWidth: 12, align: "center", children: [jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("div", { className: "pagination__previous", children: jsxRuntime.jsx(Button$1, { "data-testid": "pagination-previous-button", ariaLabel: "Previous Page", variant: "link", onClick: handlePreviousPage, iconLeft: "chevron-left", isDisabled: isPreviousButtonDisabled }) }) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("div", { className: "pagination__current-page", children: jsxRuntime.jsx(LabeledInput, { "data-testid": "pagination-current-page-input", className: classNames('pagination__current-page-input', {
|
|
7275
|
+
'has-error': hasError,
|
|
7276
|
+
}), value: inputValue, name: "currentPage", label: "Current Page", hasHiddenLabel: true, onKeyDown: (e) => {
|
|
7277
|
+
if (e.key === 'Enter') {
|
|
7278
|
+
validateAndUpdatePage(e.currentTarget.value);
|
|
7279
|
+
}
|
|
7280
|
+
}, onChange: (e) => {
|
|
7281
|
+
const value = e.currentTarget.value;
|
|
7282
|
+
// Allow empty value or numbers
|
|
7283
|
+
if (value === '' || /^\d*$/.test(value)) {
|
|
7284
|
+
setInputValue(value);
|
|
7285
|
+
}
|
|
7286
|
+
}, onBlur: (e) => validateAndUpdatePage(e.currentTarget.value) }) }) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("p", { className: "pagination__page-total", children: totalPagesText }) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("div", { className: "pagination__next", children: jsxRuntime.jsx(Button$1, { "data-testid": "pagination-next-button", ariaLabel: "Next Page", variant: "link", onClick: handleNextPage, iconLeft: "chevron-right", isDisabled: isNextButtonDisabled }) }) })] }) }) })));
|
|
7287
|
+
};
|
|
7288
|
+
|
|
7289
|
+
const TablePagination = ({ rowsPerPage, rowCount, onChangePage, currentPage, totalEntriesText, }) => {
|
|
7290
|
+
const totalPages = Math.ceil(rowCount / rowsPerPage);
|
|
7291
|
+
return (jsxRuntime.jsx("div", { className: "table__pagination", children: jsxRuntime.jsxs(Row, { align: "center", justify: "between", children: [jsxRuntime.jsx(Col, { xs: "content", children: totalEntriesText && (jsxRuntime.jsx("span", { "data-testid": "table-pagination-total-entries", className: "table__pagination-total-entries", children: totalEntriesText })) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx(Pagination, { "data-testid": "table-pagination-component", totalPages: totalPages, currentPage: currentPage, onChange: (page) => onChangePage(page, rowsPerPage) }) })] }) }));
|
|
7292
|
+
};
|
|
7293
|
+
|
|
7294
|
+
// Gets the width of the previous pinned columns
|
|
7295
|
+
const getPreviousHeadersWidth = (position, pinnedColumnIds) => {
|
|
7296
|
+
let totalWidth = 0;
|
|
7297
|
+
// Add checkbox column width if it's pinned
|
|
7298
|
+
if (pinnedColumnIds.includes('checkbox-column')) {
|
|
7299
|
+
const checkboxCell = document.querySelector('.rdt_TableCol:not([data-column-id])');
|
|
7300
|
+
if (checkboxCell) {
|
|
7301
|
+
totalWidth += checkboxCell.offsetWidth;
|
|
7302
|
+
}
|
|
7303
|
+
}
|
|
7304
|
+
// Add widths of other pinned columns before this position
|
|
7305
|
+
const previousHeaders = Array.from({ length: position }, (_, i) => {
|
|
7306
|
+
const header = document.querySelector(`[data-column-id="sticky-column-${i}"]`);
|
|
7307
|
+
if (header && pinnedColumnIds.includes(`sticky-column-${i}`)) {
|
|
7308
|
+
return header;
|
|
7309
|
+
}
|
|
7310
|
+
return null;
|
|
7311
|
+
}).filter((header) => header !== null);
|
|
7312
|
+
// Calculate base width from previous columns
|
|
7313
|
+
totalWidth = previousHeaders.reduce((acc, header) => {
|
|
7314
|
+
return acc + header.offsetWidth;
|
|
7315
|
+
}, totalWidth);
|
|
7316
|
+
// Leave this for if we ever try to fix the auto width columns
|
|
7317
|
+
// There is a bug where borders cause the offset to be wrong, this keeps it in sync.
|
|
7318
|
+
// Add offset that increases by 1 every two columns after index 1
|
|
7319
|
+
// if (position >= 2) {
|
|
7320
|
+
// const additionalOffset = Math.floor((position - 2) / 2) + 1;
|
|
7321
|
+
// totalWidth += additionalOffset;
|
|
7322
|
+
// }
|
|
7323
|
+
return totalWidth;
|
|
7324
|
+
};
|
|
7325
|
+
// Applies sticky styles to the column header
|
|
7326
|
+
const applyStickyStylesToTableHeader = (position, left) => __awaiter(void 0, void 0, void 0, function* () {
|
|
7327
|
+
const header = document.querySelector(`[data-column-id="sticky-column-${position}"]`);
|
|
7328
|
+
if (header) {
|
|
7329
|
+
header.style.position = 'sticky';
|
|
7330
|
+
header.style.left = `${left}px`;
|
|
7331
|
+
header.style.zIndex = '3';
|
|
7332
|
+
header.style.backgroundColor =
|
|
7333
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7334
|
+
}
|
|
7335
|
+
});
|
|
7336
|
+
// Sorts the pinned columns so that any column that is pinned comes before any column that is not.
|
|
7337
|
+
const sortPinnedColumns = (columns, pinnedColumnIds) => {
|
|
7338
|
+
return [...columns].sort((a, b) => {
|
|
7339
|
+
const aIsPinned = pinnedColumnIds.includes(a.id);
|
|
7340
|
+
const bIsPinned = pinnedColumnIds.includes(b.id);
|
|
7341
|
+
if (aIsPinned && !bIsPinned)
|
|
7342
|
+
return -1; // a comes first
|
|
7343
|
+
if (!aIsPinned && bIsPinned)
|
|
7344
|
+
return 1; // b comes first
|
|
7345
|
+
return 0; // maintain relative order for columns with same pinned state
|
|
7346
|
+
});
|
|
7347
|
+
};
|
|
7348
|
+
// Gets the styles for the pinned columns
|
|
7349
|
+
const getPinnedColumnStyles = (isPinned, index, pinnedColumnIds) => {
|
|
7350
|
+
return isPinned
|
|
7351
|
+
? {
|
|
7352
|
+
position: 'sticky',
|
|
7353
|
+
left: `${getPreviousHeadersWidth(index, pinnedColumnIds)}px`,
|
|
7354
|
+
zIndex: 3,
|
|
7355
|
+
backgroundColor: 'var(--pf-table-pinned-column-background-color)',
|
|
7356
|
+
}
|
|
7357
|
+
: {
|
|
7358
|
+
position: undefined,
|
|
7359
|
+
left: undefined,
|
|
7360
|
+
zIndex: undefined,
|
|
7361
|
+
backgroundColor: undefined,
|
|
7362
|
+
};
|
|
7363
|
+
};
|
|
7364
|
+
const clearStickyStyles = (header) => {
|
|
7365
|
+
header.style.position = '';
|
|
7366
|
+
header.style.left = '';
|
|
7367
|
+
header.style.zIndex = '';
|
|
7368
|
+
header.style.backgroundColor = '';
|
|
7369
|
+
};
|
|
7370
|
+
|
|
7371
|
+
const HorizontalStickyHeader = ({ children, position, onPinColumn, isPinned = false, pinnedColumnIds, }) => {
|
|
7372
|
+
React.useEffect(() => {
|
|
7373
|
+
const calculateWidth = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
7374
|
+
yield new Promise((resolve) => setTimeout(resolve, 0));
|
|
7375
|
+
const header = document.querySelector(`[data-column-id="sticky-column-${position}"]`);
|
|
7376
|
+
if (header) {
|
|
7377
|
+
if (isPinned) {
|
|
7378
|
+
const width = getPreviousHeadersWidth(position, pinnedColumnIds);
|
|
7379
|
+
yield applyStickyStylesToTableHeader(position, width);
|
|
7380
|
+
}
|
|
7381
|
+
else {
|
|
7382
|
+
clearStickyStyles(header);
|
|
7383
|
+
}
|
|
7384
|
+
}
|
|
7385
|
+
});
|
|
7386
|
+
calculateWidth();
|
|
7387
|
+
}, [position, isPinned, pinnedColumnIds]);
|
|
7388
|
+
return (jsxRuntime.jsxs("div", { className: "table__header-cell", "data-testid": `sticky-column-${position}`, children: [jsxRuntime.jsx(Button$1, { "data-testid": `sticky-header-pin-button-${position}`, variant: "link", size: "sm", iconLeft: "pin", onClick: onPinColumn, ariaLabel: isPinned ? 'Unpin column' : 'Pin column', className: `table__column--${isPinned ? 'is-pinned' : 'is-not-pinned'} table__column__pin-action` }), jsxRuntime.jsx("div", { className: "table__header-content", children: children })] }));
|
|
7389
|
+
};
|
|
7390
|
+
|
|
7391
|
+
const processColumns = (columns, pinnedColumnIds, togglePinnedColumn) => {
|
|
7392
|
+
return columns.map((column, index) => {
|
|
7393
|
+
const dataColumnId = `sticky-column-${index}`;
|
|
7394
|
+
const isPinned = pinnedColumnIds.includes(dataColumnId);
|
|
7395
|
+
const headerContent = column.isPinned !== undefined ? (jsxRuntime.jsx(HorizontalStickyHeader, { position: index, isPinned: isPinned, onPinColumn: () => togglePinnedColumn(column.id), pinnedColumnIds: pinnedColumnIds, children: column.name })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: column.name }));
|
|
7396
|
+
return Object.assign(Object.assign({}, column), { name: headerContent, id: dataColumnId, style: getPinnedColumnStyles(isPinned, index, pinnedColumnIds) });
|
|
7397
|
+
});
|
|
7398
|
+
};
|
|
7399
|
+
|
|
7400
|
+
/**
|
|
7401
|
+
* Hook to manage pinned columns in a table
|
|
7402
|
+
* Handles initialization, toggling, positioning and resizing of pinned columns
|
|
7403
|
+
*/
|
|
7404
|
+
const usePinnedColumnsManager = (columns, canPinColumns, onPinnedColumnsChange) => {
|
|
7405
|
+
const pinnedColumnIds = columns.filter((column) => column.isPinned).map((column) => column.id);
|
|
7406
|
+
// `dataColumnIds` is the list of IDs used as `data-column-id` attributes on the table headers and cells
|
|
7407
|
+
const dataColumnIds = React.useMemo(() => {
|
|
7408
|
+
const ids = columns
|
|
7409
|
+
.map((column, index) => (column.isPinned ? `sticky-column-${index}` : null))
|
|
7410
|
+
.filter((id) => id !== null);
|
|
7411
|
+
return ids.length > 0 ? ['checkbox-column', ...ids] : ids;
|
|
7412
|
+
}, [columns]);
|
|
7413
|
+
// Toggle individual column pin state
|
|
7414
|
+
const togglePinnedColumn = React.useCallback((columnId) => {
|
|
7415
|
+
const prevPinnedColumns = pinnedColumnIds;
|
|
7416
|
+
// Handle unpinning
|
|
7417
|
+
if (prevPinnedColumns.some((id) => id === columnId)) {
|
|
7418
|
+
onPinnedColumnsChange === null || onPinnedColumnsChange === void 0 ? void 0 : onPinnedColumnsChange(prevPinnedColumns.filter((id) => id !== columnId));
|
|
7419
|
+
}
|
|
7420
|
+
else {
|
|
7421
|
+
onPinnedColumnsChange === null || onPinnedColumnsChange === void 0 ? void 0 : onPinnedColumnsChange(prevPinnedColumns.concat(columnId));
|
|
7422
|
+
}
|
|
7423
|
+
}, [pinnedColumnIds, onPinnedColumnsChange]);
|
|
7424
|
+
// Handle resize events and recalculate pinned column positions
|
|
7425
|
+
React.useEffect(() => {
|
|
7426
|
+
if (!canPinColumns)
|
|
7427
|
+
return;
|
|
7428
|
+
const recalculatePositions = () => {
|
|
7429
|
+
// Reset all column styles and remove last-pinned-column class
|
|
7430
|
+
const allCells = document.querySelectorAll('.rdt_TableCol, .rdt_TableCell');
|
|
7431
|
+
allCells.forEach((cell) => {
|
|
7432
|
+
cell.style.position = '';
|
|
7433
|
+
cell.style.left = '';
|
|
7434
|
+
cell.style.zIndex = '';
|
|
7435
|
+
cell.style.backgroundColor = '';
|
|
7436
|
+
cell.style.borderRight = '';
|
|
7437
|
+
});
|
|
7438
|
+
// Apply styles to pinned columns
|
|
7439
|
+
dataColumnIds.forEach((column, index) => {
|
|
7440
|
+
const isLastPinnedColumn = index === dataColumnIds.length - 1;
|
|
7441
|
+
if (column === 'checkbox-column') {
|
|
7442
|
+
// Handle header checkbox
|
|
7443
|
+
const headerCheckbox = document.querySelector('.rdt_TableCol:not([data-column-id])');
|
|
7444
|
+
if (headerCheckbox) {
|
|
7445
|
+
headerCheckbox.style.position = 'sticky';
|
|
7446
|
+
headerCheckbox.style.left = '0';
|
|
7447
|
+
headerCheckbox.style.zIndex = '4';
|
|
7448
|
+
headerCheckbox.style.backgroundColor =
|
|
7449
|
+
'var(--pf-table-background-color)';
|
|
7450
|
+
}
|
|
7451
|
+
// Handle cell checkboxes
|
|
7452
|
+
const cellCheckboxes = document.querySelectorAll('.rdt_TableCell:first-child');
|
|
7453
|
+
cellCheckboxes.forEach((cell) => {
|
|
7454
|
+
cell.style.position = 'sticky';
|
|
7455
|
+
cell.style.left = '0';
|
|
7456
|
+
cell.style.zIndex = '2';
|
|
7457
|
+
cell.style.backgroundColor =
|
|
7458
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7459
|
+
if (isLastPinnedColumn) {
|
|
7460
|
+
cell.style.borderRight =
|
|
7461
|
+
`2px solid var(--pf-table-pinned-column-border-color)`;
|
|
7462
|
+
}
|
|
7463
|
+
});
|
|
7464
|
+
}
|
|
7465
|
+
else {
|
|
7466
|
+
const columnIndex = parseInt(column.split('-')[2]);
|
|
7467
|
+
const left = getPreviousHeadersWidth(columnIndex, dataColumnIds);
|
|
7468
|
+
// Headers
|
|
7469
|
+
const headers = document.querySelectorAll(`.rdt_TableCol[data-column-id="sticky-column-${columnIndex}"]`);
|
|
7470
|
+
headers.forEach((header) => {
|
|
7471
|
+
header.style.position = 'sticky';
|
|
7472
|
+
header.style.left = `${left}px`;
|
|
7473
|
+
header.style.zIndex = '2';
|
|
7474
|
+
header.style.backgroundColor =
|
|
7475
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7476
|
+
if (isLastPinnedColumn) {
|
|
7477
|
+
header.style.borderRight =
|
|
7478
|
+
`2px solid var(--pf-table-pinned-column-border-color)`;
|
|
7479
|
+
}
|
|
7480
|
+
});
|
|
7481
|
+
// Cells
|
|
7482
|
+
const cells = document.querySelectorAll(`.rdt_TableCell[data-column-id="sticky-column-${columnIndex}"]`);
|
|
7483
|
+
cells.forEach((cell) => {
|
|
7484
|
+
cell.style.position = 'sticky';
|
|
7485
|
+
cell.style.left = `${left}px`;
|
|
7486
|
+
cell.style.zIndex = '2';
|
|
7487
|
+
cell.style.backgroundColor =
|
|
7488
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7489
|
+
if (isLastPinnedColumn) {
|
|
7490
|
+
cell.style.borderRight =
|
|
7491
|
+
`2px solid var(--pf-table-pinned-column-border-color)`;
|
|
7492
|
+
}
|
|
7493
|
+
});
|
|
7494
|
+
}
|
|
7495
|
+
});
|
|
7496
|
+
};
|
|
7497
|
+
// Set up resize observers
|
|
7498
|
+
const table = document.querySelector('.rdt_Table');
|
|
7499
|
+
const resizeObserver = new ResizeObserver(recalculatePositions);
|
|
7500
|
+
if (table) {
|
|
7501
|
+
resizeObserver.observe(table);
|
|
7502
|
+
}
|
|
7503
|
+
window.addEventListener('resize', recalculatePositions);
|
|
7504
|
+
return () => {
|
|
7505
|
+
resizeObserver.disconnect();
|
|
7506
|
+
window.removeEventListener('resize', recalculatePositions);
|
|
7507
|
+
};
|
|
7508
|
+
}, [canPinColumns, dataColumnIds]);
|
|
7509
|
+
// Process columns for rendering with pin state
|
|
7510
|
+
const columnsWithPinning = canPinColumns
|
|
7511
|
+
? sortPinnedColumns(processColumns(columns, dataColumnIds, togglePinnedColumn), dataColumnIds)
|
|
7512
|
+
: columns;
|
|
7513
|
+
return {
|
|
7514
|
+
columnsWithPinning, // Columns with pin state and handlers applied
|
|
7515
|
+
};
|
|
7516
|
+
};
|
|
7517
|
+
|
|
7518
|
+
const Table = (props) => {
|
|
7519
|
+
const { responsive = true, direction = 'auto', keyField = 'id', striped = false, noDataComponent = 'built-in', isDisabled, isLoading, isFullHeight = false, subHeaderAlign = 'left', className, paginationTotalRows, totalEntriesText, data, columns: initialColumns, canPinColumns = false, onPinnedColumnsChange } = props, rest = __rest(props, ["responsive", "direction", "keyField", "striped", "noDataComponent", "isDisabled", "isLoading", "isFullHeight", "subHeaderAlign", "className", "paginationTotalRows", "totalEntriesText", "data", "columns", "canPinColumns", "onPinnedColumnsChange"]);
|
|
7520
|
+
// Turns on/off column pinning.
|
|
7521
|
+
const { columnsWithPinning } = usePinnedColumnsManager(initialColumns, canPinColumns, onPinnedColumnsChange);
|
|
7522
|
+
const combinedClassName = classNames(className, {
|
|
7523
|
+
'table--striped': striped,
|
|
7524
|
+
'table-body': true,
|
|
7525
|
+
});
|
|
7526
|
+
const tableWrapperClassName = classNames('table', {
|
|
7527
|
+
'table--full-height': isFullHeight,
|
|
7528
|
+
});
|
|
7529
|
+
return (jsxRuntime.jsx("div", { className: tableWrapperClassName, "data-testid": "table", children: jsxRuntime.jsx(Xe, Object.assign({ data: data, columns: columnsWithPinning, responsive: responsive, direction: direction, subHeaderAlign: subHeaderAlign, keyField: keyField, striped: striped, className: combinedClassName, disabled: isDisabled, noDataComponent: noDataComponent, progressPending: isLoading, progressComponent: jsxRuntime.jsx(LoadingComponent, {}), pagination: true, paginationComponent: (props) => (jsxRuntime.jsx(TablePagination, Object.assign({}, props, { totalEntriesText: totalEntriesText }))), paginationTotalRows: paginationTotalRows, highlightOnHover: true, pointerOnHover: true }, rest)) }));
|
|
7530
|
+
};
|
|
7531
|
+
|
|
7241
7532
|
const Radio = React__namespace.default.forwardRef((_a, ref) => {
|
|
7242
7533
|
var { id, label, name, value, onChange, isDisabled } = _a, rest = __rest(_a, ["id", "label", "name", "value", "onChange", "isDisabled"]);
|
|
7243
7534
|
return (jsxRuntime.jsx("div", { className: "form-control", children: jsxRuntime.jsxs("div", { className: "radio-wrapper", children: [jsxRuntime.jsx("input", Object.assign({ "data-testid": `form-radio-input-${name}`, className: "radio-input", type: "radio", id: id, name: name, value: value, disabled: isDisabled, ref: ref, onChange: onChange, tabIndex: 0, "aria-describedby": id, "aria-label": label }, rest)), jsxRuntime.jsx("label", { htmlFor: id, className: "radio-input-label", "data-testid": `label-radio-input-${name}`, children: label })] }) }));
|