@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.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { library, findIconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
2
|
-
import { faArrowDown, faArrowRight, faArrowLeft, faCalculator, faCheck, faCircleNotch, faMountainSun, faRocket, faWind, faEyeSlash, faEye, faCaretUp, faCaretDown, faTag, faPencilAlt, faSearch, faCog, faFileDownload, faQuestionCircle, faCopy, faXmark } from '@fortawesome/free-solid-svg-icons';
|
|
2
|
+
import { faArrowDown, faArrowRight, faArrowLeft, faCalculator, faCheck, faCircleNotch, faMountainSun, faRocket, faWind, faEyeSlash, faEye, faCaretUp, faCaretDown, faTag, faPencilAlt, faSearch, faCog, faFileDownload, faQuestionCircle, faCopy, faXmark, faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import React__default, { useLayoutEffect, useEffect, createContext, useState, useRef, useContext, useCallback, useImperativeHandle, forwardRef, useMemo, isValidElement, useId as useId$1 } from 'react';
|
|
@@ -205,7 +205,7 @@ const registerFontAwesomeIcons = (...icons) => {
|
|
|
205
205
|
library.add(...icons);
|
|
206
206
|
};
|
|
207
207
|
// Register the icons used directly in design system components
|
|
208
|
-
registerFontAwesomeIcons(faArrowDown, faArrowRight, faArrowLeft, faCalculator, faCheck, faCircleNotch, faMountainSun, faRocket, faWind, faEyeSlash, faEye, faCaretUp, faCaretDown, faTag, faPencilAlt, faSearch, faCog, faFileDownload, faQuestionCircle, faCopy, faXmark,
|
|
208
|
+
registerFontAwesomeIcons(faArrowDown, faArrowRight, faArrowLeft, faCalculator, faCheck, faCircleNotch, faMountainSun, faRocket, faWind, faEyeSlash, faEye, faCaretUp, faCaretDown, faTag, faPencilAlt, faSearch, faCog, faFileDownload, faQuestionCircle, faCopy, faXmark, faChevronLeft, faChevronRight,
|
|
209
209
|
// backwards compat, don't require registration of custom indicons
|
|
210
210
|
// might want to consider doing so in the future
|
|
211
211
|
...indiconDefinitions);
|
|
@@ -2603,6 +2603,16 @@ function __rest(s, e) {
|
|
|
2603
2603
|
return t;
|
|
2604
2604
|
}
|
|
2605
2605
|
|
|
2606
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
2607
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
2608
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
2609
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
2610
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
2611
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
2612
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
2613
|
+
});
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2606
2616
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
2607
2617
|
var e = new Error(message);
|
|
2608
2618
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
@@ -7168,18 +7178,6 @@ const LoadingComponent = () => {
|
|
|
7168
7178
|
return jsx("div", { className: "table-loading", children: "Loading..." });
|
|
7169
7179
|
};
|
|
7170
7180
|
|
|
7171
|
-
const Table = (props) => {
|
|
7172
|
-
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"]);
|
|
7173
|
-
const combinedClassName = classNames(className, {
|
|
7174
|
-
'table--striped': striped,
|
|
7175
|
-
'table-body': true,
|
|
7176
|
-
});
|
|
7177
|
-
const tableWrapperClassName = classNames('table', {
|
|
7178
|
-
'table--full-height': isFullHeight,
|
|
7179
|
-
});
|
|
7180
|
-
return (jsx("div", { className: tableWrapperClassName, children: jsx(Xe, Object.assign({ responsive: responsive, direction: direction, subHeaderAlign: subHeaderAlign, keyField: keyField, striped: striped, className: combinedClassName, disabled: isDisabled, noDataComponent: noDataComponent, progressPending: isLoading, progressComponent: jsx(LoadingComponent, {}) }, rest)) }));
|
|
7181
|
-
};
|
|
7182
|
-
|
|
7183
7181
|
const Label = ({ label, name, isRequired }) => {
|
|
7184
7182
|
return (jsx("div", { "data-testid": `${name}-testId`, className: `form-label`, children: jsxs("label", { htmlFor: `${name}`, children: [label, isRequired ? jsx("span", { className: "text-error", children: " *" }) : ''] }) }));
|
|
7185
7183
|
};
|
|
@@ -7213,6 +7211,299 @@ const Input = React__default.forwardRef((_a, ref) => {
|
|
|
7213
7211
|
});
|
|
7214
7212
|
const LabeledInput = withLabel(Input);
|
|
7215
7213
|
|
|
7214
|
+
const Pagination = (_a) => {
|
|
7215
|
+
var { totalPages, currentPage = 1, onChange, className } = _a, rest = __rest(_a, ["totalPages", "currentPage", "onChange", "className"]);
|
|
7216
|
+
const [inputValue, setInputValue] = useState(currentPage.toString());
|
|
7217
|
+
const totalPagesText = `of ${totalPages}`;
|
|
7218
|
+
const classes = classNames('pagination', className);
|
|
7219
|
+
useEffect(() => {
|
|
7220
|
+
setInputValue(currentPage.toString());
|
|
7221
|
+
}, [currentPage]);
|
|
7222
|
+
const handleNextPage = () => {
|
|
7223
|
+
if (currentPage < totalPages) {
|
|
7224
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(currentPage + 1);
|
|
7225
|
+
}
|
|
7226
|
+
};
|
|
7227
|
+
const handlePreviousPage = () => {
|
|
7228
|
+
if (currentPage > 1) {
|
|
7229
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(currentPage - 1);
|
|
7230
|
+
}
|
|
7231
|
+
};
|
|
7232
|
+
const validateAndUpdatePage = (value) => {
|
|
7233
|
+
// If empty or invalid, reset to current page
|
|
7234
|
+
if (!value) {
|
|
7235
|
+
setInputValue(currentPage.toString());
|
|
7236
|
+
return;
|
|
7237
|
+
}
|
|
7238
|
+
const page = Number(value);
|
|
7239
|
+
if (!isNaN(page) && page > 0 && page <= totalPages) {
|
|
7240
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(page);
|
|
7241
|
+
}
|
|
7242
|
+
else {
|
|
7243
|
+
setInputValue(currentPage.toString());
|
|
7244
|
+
}
|
|
7245
|
+
};
|
|
7246
|
+
const isNextButtonDisabled = currentPage === totalPages;
|
|
7247
|
+
const isPreviousButtonDisabled = currentPage === 1;
|
|
7248
|
+
const hasError = Number(inputValue) > totalPages || Number(inputValue) < 1;
|
|
7249
|
+
return (jsx("div", Object.assign({ className: classes }, rest, { children: jsx(Container, { children: jsxs(Row, { gutterWidth: 12, align: "center", children: [jsx(Col, { xs: "content", children: jsx("div", { className: "pagination__previous", children: jsx(Button$1, { "data-testid": "pagination-previous-button", ariaLabel: "Previous Page", variant: "link", onClick: handlePreviousPage, iconLeft: "chevron-left", isDisabled: isPreviousButtonDisabled }) }) }), jsx(Col, { xs: "content", children: jsx("div", { className: "pagination__current-page", children: jsx(LabeledInput, { "data-testid": "pagination-current-page-input", className: classNames('pagination__current-page-input', {
|
|
7250
|
+
'has-error': hasError,
|
|
7251
|
+
}), value: inputValue, name: "currentPage", label: "Current Page", hasHiddenLabel: true, onKeyDown: (e) => {
|
|
7252
|
+
if (e.key === 'Enter') {
|
|
7253
|
+
validateAndUpdatePage(e.currentTarget.value);
|
|
7254
|
+
}
|
|
7255
|
+
}, onChange: (e) => {
|
|
7256
|
+
const value = e.currentTarget.value;
|
|
7257
|
+
// Allow empty value or numbers
|
|
7258
|
+
if (value === '' || /^\d*$/.test(value)) {
|
|
7259
|
+
setInputValue(value);
|
|
7260
|
+
}
|
|
7261
|
+
}, onBlur: (e) => validateAndUpdatePage(e.currentTarget.value) }) }) }), jsx(Col, { xs: "content", children: jsx("p", { className: "pagination__page-total", children: totalPagesText }) }), jsx(Col, { xs: "content", children: jsx("div", { className: "pagination__next", children: jsx(Button$1, { "data-testid": "pagination-next-button", ariaLabel: "Next Page", variant: "link", onClick: handleNextPage, iconLeft: "chevron-right", isDisabled: isNextButtonDisabled }) }) })] }) }) })));
|
|
7262
|
+
};
|
|
7263
|
+
|
|
7264
|
+
const TablePagination = ({ rowsPerPage, rowCount, onChangePage, currentPage, totalEntriesText, }) => {
|
|
7265
|
+
const totalPages = Math.ceil(rowCount / rowsPerPage);
|
|
7266
|
+
return (jsx("div", { className: "table__pagination", children: jsxs(Row, { align: "center", justify: "between", children: [jsx(Col, { xs: "content", children: totalEntriesText && (jsx("span", { "data-testid": "table-pagination-total-entries", className: "table__pagination-total-entries", children: totalEntriesText })) }), jsx(Col, { xs: "content", children: jsx(Pagination, { "data-testid": "table-pagination-component", totalPages: totalPages, currentPage: currentPage, onChange: (page) => onChangePage(page, rowsPerPage) }) })] }) }));
|
|
7267
|
+
};
|
|
7268
|
+
|
|
7269
|
+
// Gets the width of the previous pinned columns
|
|
7270
|
+
const getPreviousHeadersWidth = (position, pinnedColumnIds) => {
|
|
7271
|
+
let totalWidth = 0;
|
|
7272
|
+
// Add checkbox column width if it's pinned
|
|
7273
|
+
if (pinnedColumnIds.includes('checkbox-column')) {
|
|
7274
|
+
const checkboxCell = document.querySelector('.rdt_TableCol:not([data-column-id])');
|
|
7275
|
+
if (checkboxCell) {
|
|
7276
|
+
totalWidth += checkboxCell.offsetWidth;
|
|
7277
|
+
}
|
|
7278
|
+
}
|
|
7279
|
+
// Add widths of other pinned columns before this position
|
|
7280
|
+
const previousHeaders = Array.from({ length: position }, (_, i) => {
|
|
7281
|
+
const header = document.querySelector(`[data-column-id="sticky-column-${i}"]`);
|
|
7282
|
+
if (header && pinnedColumnIds.includes(`sticky-column-${i}`)) {
|
|
7283
|
+
return header;
|
|
7284
|
+
}
|
|
7285
|
+
return null;
|
|
7286
|
+
}).filter((header) => header !== null);
|
|
7287
|
+
// Calculate base width from previous columns
|
|
7288
|
+
totalWidth = previousHeaders.reduce((acc, header) => {
|
|
7289
|
+
return acc + header.offsetWidth;
|
|
7290
|
+
}, totalWidth);
|
|
7291
|
+
// Leave this for if we ever try to fix the auto width columns
|
|
7292
|
+
// There is a bug where borders cause the offset to be wrong, this keeps it in sync.
|
|
7293
|
+
// Add offset that increases by 1 every two columns after index 1
|
|
7294
|
+
// if (position >= 2) {
|
|
7295
|
+
// const additionalOffset = Math.floor((position - 2) / 2) + 1;
|
|
7296
|
+
// totalWidth += additionalOffset;
|
|
7297
|
+
// }
|
|
7298
|
+
return totalWidth;
|
|
7299
|
+
};
|
|
7300
|
+
// Applies sticky styles to the column header
|
|
7301
|
+
const applyStickyStylesToTableHeader = (position, left) => __awaiter(void 0, void 0, void 0, function* () {
|
|
7302
|
+
const header = document.querySelector(`[data-column-id="sticky-column-${position}"]`);
|
|
7303
|
+
if (header) {
|
|
7304
|
+
header.style.position = 'sticky';
|
|
7305
|
+
header.style.left = `${left}px`;
|
|
7306
|
+
header.style.zIndex = '3';
|
|
7307
|
+
header.style.backgroundColor =
|
|
7308
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7309
|
+
}
|
|
7310
|
+
});
|
|
7311
|
+
// Sorts the pinned columns so that any column that is pinned comes before any column that is not.
|
|
7312
|
+
const sortPinnedColumns = (columns, pinnedColumnIds) => {
|
|
7313
|
+
return [...columns].sort((a, b) => {
|
|
7314
|
+
const aIsPinned = pinnedColumnIds.includes(a.id);
|
|
7315
|
+
const bIsPinned = pinnedColumnIds.includes(b.id);
|
|
7316
|
+
if (aIsPinned && !bIsPinned)
|
|
7317
|
+
return -1; // a comes first
|
|
7318
|
+
if (!aIsPinned && bIsPinned)
|
|
7319
|
+
return 1; // b comes first
|
|
7320
|
+
return 0; // maintain relative order for columns with same pinned state
|
|
7321
|
+
});
|
|
7322
|
+
};
|
|
7323
|
+
// Gets the styles for the pinned columns
|
|
7324
|
+
const getPinnedColumnStyles = (isPinned, index, pinnedColumnIds) => {
|
|
7325
|
+
return isPinned
|
|
7326
|
+
? {
|
|
7327
|
+
position: 'sticky',
|
|
7328
|
+
left: `${getPreviousHeadersWidth(index, pinnedColumnIds)}px`,
|
|
7329
|
+
zIndex: 3,
|
|
7330
|
+
backgroundColor: 'var(--pf-table-pinned-column-background-color)',
|
|
7331
|
+
}
|
|
7332
|
+
: {
|
|
7333
|
+
position: undefined,
|
|
7334
|
+
left: undefined,
|
|
7335
|
+
zIndex: undefined,
|
|
7336
|
+
backgroundColor: undefined,
|
|
7337
|
+
};
|
|
7338
|
+
};
|
|
7339
|
+
const clearStickyStyles = (header) => {
|
|
7340
|
+
header.style.position = '';
|
|
7341
|
+
header.style.left = '';
|
|
7342
|
+
header.style.zIndex = '';
|
|
7343
|
+
header.style.backgroundColor = '';
|
|
7344
|
+
};
|
|
7345
|
+
|
|
7346
|
+
const HorizontalStickyHeader = ({ children, position, onPinColumn, isPinned = false, pinnedColumnIds, }) => {
|
|
7347
|
+
useEffect(() => {
|
|
7348
|
+
const calculateWidth = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
7349
|
+
yield new Promise((resolve) => setTimeout(resolve, 0));
|
|
7350
|
+
const header = document.querySelector(`[data-column-id="sticky-column-${position}"]`);
|
|
7351
|
+
if (header) {
|
|
7352
|
+
if (isPinned) {
|
|
7353
|
+
const width = getPreviousHeadersWidth(position, pinnedColumnIds);
|
|
7354
|
+
yield applyStickyStylesToTableHeader(position, width);
|
|
7355
|
+
}
|
|
7356
|
+
else {
|
|
7357
|
+
clearStickyStyles(header);
|
|
7358
|
+
}
|
|
7359
|
+
}
|
|
7360
|
+
});
|
|
7361
|
+
calculateWidth();
|
|
7362
|
+
}, [position, isPinned, pinnedColumnIds]);
|
|
7363
|
+
return (jsxs("div", { className: "table__header-cell", "data-testid": `sticky-column-${position}`, children: [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` }), jsx("div", { className: "table__header-content", children: children })] }));
|
|
7364
|
+
};
|
|
7365
|
+
|
|
7366
|
+
const processColumns = (columns, pinnedColumnIds, togglePinnedColumn) => {
|
|
7367
|
+
return columns.map((column, index) => {
|
|
7368
|
+
const dataColumnId = `sticky-column-${index}`;
|
|
7369
|
+
const isPinned = pinnedColumnIds.includes(dataColumnId);
|
|
7370
|
+
const headerContent = column.isPinned !== undefined ? (jsx(HorizontalStickyHeader, { position: index, isPinned: isPinned, onPinColumn: () => togglePinnedColumn(column.id), pinnedColumnIds: pinnedColumnIds, children: column.name })) : (jsx(Fragment, { children: column.name }));
|
|
7371
|
+
return Object.assign(Object.assign({}, column), { name: headerContent, id: dataColumnId, style: getPinnedColumnStyles(isPinned, index, pinnedColumnIds) });
|
|
7372
|
+
});
|
|
7373
|
+
};
|
|
7374
|
+
|
|
7375
|
+
/**
|
|
7376
|
+
* Hook to manage pinned columns in a table
|
|
7377
|
+
* Handles initialization, toggling, positioning and resizing of pinned columns
|
|
7378
|
+
*/
|
|
7379
|
+
const usePinnedColumnsManager = (columns, canPinColumns, onPinnedColumnsChange) => {
|
|
7380
|
+
const pinnedColumnIds = columns.filter((column) => column.isPinned).map((column) => column.id);
|
|
7381
|
+
// `dataColumnIds` is the list of IDs used as `data-column-id` attributes on the table headers and cells
|
|
7382
|
+
const dataColumnIds = useMemo(() => {
|
|
7383
|
+
const ids = columns
|
|
7384
|
+
.map((column, index) => (column.isPinned ? `sticky-column-${index}` : null))
|
|
7385
|
+
.filter((id) => id !== null);
|
|
7386
|
+
return ids.length > 0 ? ['checkbox-column', ...ids] : ids;
|
|
7387
|
+
}, [columns]);
|
|
7388
|
+
// Toggle individual column pin state
|
|
7389
|
+
const togglePinnedColumn = useCallback((columnId) => {
|
|
7390
|
+
const prevPinnedColumns = pinnedColumnIds;
|
|
7391
|
+
// Handle unpinning
|
|
7392
|
+
if (prevPinnedColumns.some((id) => id === columnId)) {
|
|
7393
|
+
onPinnedColumnsChange === null || onPinnedColumnsChange === void 0 ? void 0 : onPinnedColumnsChange(prevPinnedColumns.filter((id) => id !== columnId));
|
|
7394
|
+
}
|
|
7395
|
+
else {
|
|
7396
|
+
onPinnedColumnsChange === null || onPinnedColumnsChange === void 0 ? void 0 : onPinnedColumnsChange(prevPinnedColumns.concat(columnId));
|
|
7397
|
+
}
|
|
7398
|
+
}, [pinnedColumnIds, onPinnedColumnsChange]);
|
|
7399
|
+
// Handle resize events and recalculate pinned column positions
|
|
7400
|
+
useEffect(() => {
|
|
7401
|
+
if (!canPinColumns)
|
|
7402
|
+
return;
|
|
7403
|
+
const recalculatePositions = () => {
|
|
7404
|
+
// Reset all column styles and remove last-pinned-column class
|
|
7405
|
+
const allCells = document.querySelectorAll('.rdt_TableCol, .rdt_TableCell');
|
|
7406
|
+
allCells.forEach((cell) => {
|
|
7407
|
+
cell.style.position = '';
|
|
7408
|
+
cell.style.left = '';
|
|
7409
|
+
cell.style.zIndex = '';
|
|
7410
|
+
cell.style.backgroundColor = '';
|
|
7411
|
+
cell.style.borderRight = '';
|
|
7412
|
+
});
|
|
7413
|
+
// Apply styles to pinned columns
|
|
7414
|
+
dataColumnIds.forEach((column, index) => {
|
|
7415
|
+
const isLastPinnedColumn = index === dataColumnIds.length - 1;
|
|
7416
|
+
if (column === 'checkbox-column') {
|
|
7417
|
+
// Handle header checkbox
|
|
7418
|
+
const headerCheckbox = document.querySelector('.rdt_TableCol:not([data-column-id])');
|
|
7419
|
+
if (headerCheckbox) {
|
|
7420
|
+
headerCheckbox.style.position = 'sticky';
|
|
7421
|
+
headerCheckbox.style.left = '0';
|
|
7422
|
+
headerCheckbox.style.zIndex = '4';
|
|
7423
|
+
headerCheckbox.style.backgroundColor =
|
|
7424
|
+
'var(--pf-table-background-color)';
|
|
7425
|
+
}
|
|
7426
|
+
// Handle cell checkboxes
|
|
7427
|
+
const cellCheckboxes = document.querySelectorAll('.rdt_TableCell:first-child');
|
|
7428
|
+
cellCheckboxes.forEach((cell) => {
|
|
7429
|
+
cell.style.position = 'sticky';
|
|
7430
|
+
cell.style.left = '0';
|
|
7431
|
+
cell.style.zIndex = '2';
|
|
7432
|
+
cell.style.backgroundColor =
|
|
7433
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7434
|
+
if (isLastPinnedColumn) {
|
|
7435
|
+
cell.style.borderRight =
|
|
7436
|
+
`2px solid var(--pf-table-pinned-column-border-color)`;
|
|
7437
|
+
}
|
|
7438
|
+
});
|
|
7439
|
+
}
|
|
7440
|
+
else {
|
|
7441
|
+
const columnIndex = parseInt(column.split('-')[2]);
|
|
7442
|
+
const left = getPreviousHeadersWidth(columnIndex, dataColumnIds);
|
|
7443
|
+
// Headers
|
|
7444
|
+
const headers = document.querySelectorAll(`.rdt_TableCol[data-column-id="sticky-column-${columnIndex}"]`);
|
|
7445
|
+
headers.forEach((header) => {
|
|
7446
|
+
header.style.position = 'sticky';
|
|
7447
|
+
header.style.left = `${left}px`;
|
|
7448
|
+
header.style.zIndex = '2';
|
|
7449
|
+
header.style.backgroundColor =
|
|
7450
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7451
|
+
if (isLastPinnedColumn) {
|
|
7452
|
+
header.style.borderRight =
|
|
7453
|
+
`2px solid var(--pf-table-pinned-column-border-color)`;
|
|
7454
|
+
}
|
|
7455
|
+
});
|
|
7456
|
+
// Cells
|
|
7457
|
+
const cells = document.querySelectorAll(`.rdt_TableCell[data-column-id="sticky-column-${columnIndex}"]`);
|
|
7458
|
+
cells.forEach((cell) => {
|
|
7459
|
+
cell.style.position = 'sticky';
|
|
7460
|
+
cell.style.left = `${left}px`;
|
|
7461
|
+
cell.style.zIndex = '2';
|
|
7462
|
+
cell.style.backgroundColor =
|
|
7463
|
+
'var(--pf-table-pinned-column-background-color)';
|
|
7464
|
+
if (isLastPinnedColumn) {
|
|
7465
|
+
cell.style.borderRight =
|
|
7466
|
+
`2px solid var(--pf-table-pinned-column-border-color)`;
|
|
7467
|
+
}
|
|
7468
|
+
});
|
|
7469
|
+
}
|
|
7470
|
+
});
|
|
7471
|
+
};
|
|
7472
|
+
// Set up resize observers
|
|
7473
|
+
const table = document.querySelector('.rdt_Table');
|
|
7474
|
+
const resizeObserver = new ResizeObserver(recalculatePositions);
|
|
7475
|
+
if (table) {
|
|
7476
|
+
resizeObserver.observe(table);
|
|
7477
|
+
}
|
|
7478
|
+
window.addEventListener('resize', recalculatePositions);
|
|
7479
|
+
return () => {
|
|
7480
|
+
resizeObserver.disconnect();
|
|
7481
|
+
window.removeEventListener('resize', recalculatePositions);
|
|
7482
|
+
};
|
|
7483
|
+
}, [canPinColumns, dataColumnIds]);
|
|
7484
|
+
// Process columns for rendering with pin state
|
|
7485
|
+
const columnsWithPinning = canPinColumns
|
|
7486
|
+
? sortPinnedColumns(processColumns(columns, dataColumnIds, togglePinnedColumn), dataColumnIds)
|
|
7487
|
+
: columns;
|
|
7488
|
+
return {
|
|
7489
|
+
columnsWithPinning, // Columns with pin state and handlers applied
|
|
7490
|
+
};
|
|
7491
|
+
};
|
|
7492
|
+
|
|
7493
|
+
const Table = (props) => {
|
|
7494
|
+
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"]);
|
|
7495
|
+
// Turns on/off column pinning.
|
|
7496
|
+
const { columnsWithPinning } = usePinnedColumnsManager(initialColumns, canPinColumns, onPinnedColumnsChange);
|
|
7497
|
+
const combinedClassName = classNames(className, {
|
|
7498
|
+
'table--striped': striped,
|
|
7499
|
+
'table-body': true,
|
|
7500
|
+
});
|
|
7501
|
+
const tableWrapperClassName = classNames('table', {
|
|
7502
|
+
'table--full-height': isFullHeight,
|
|
7503
|
+
});
|
|
7504
|
+
return (jsx("div", { className: tableWrapperClassName, "data-testid": "table", children: 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: jsx(LoadingComponent, {}), pagination: true, paginationComponent: (props) => (jsx(TablePagination, Object.assign({}, props, { totalEntriesText: totalEntriesText }))), paginationTotalRows: paginationTotalRows, highlightOnHover: true, pointerOnHover: true }, rest)) }));
|
|
7505
|
+
};
|
|
7506
|
+
|
|
7216
7507
|
const Radio = React__default.forwardRef((_a, ref) => {
|
|
7217
7508
|
var { id, label, name, value, onChange, isDisabled } = _a, rest = __rest(_a, ["id", "label", "name", "value", "onChange", "isDisabled"]);
|
|
7218
7509
|
return (jsx("div", { className: "form-control", children: jsxs("div", { className: "radio-wrapper", children: [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)), jsx("label", { htmlFor: id, className: "radio-input-label", "data-testid": `label-radio-input-${name}`, children: label })] }) }));
|