@indico-data/design-system 2.48.0 → 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.
Files changed (31) hide show
  1. package/lib/components/table/Table.stories.d.ts +1 -0
  2. package/lib/components/table/components/HorizontalStickyHeader.d.ts +10 -0
  3. package/lib/components/table/components/__tests__/HorizontalStickyHeader.test.d.ts +1 -0
  4. package/lib/components/table/components/helpers.d.ts +6 -0
  5. package/lib/components/table/hooks/usePinnedColumnsManager.d.ts +8 -0
  6. package/lib/components/table/sampleData.d.ts +4 -0
  7. package/lib/components/table/types.d.ts +11 -1
  8. package/lib/components/table/utils/processColumns.d.ts +2 -0
  9. package/lib/index.css +28 -9
  10. package/lib/index.d.ts +12 -1
  11. package/lib/index.esm.css +28 -9
  12. package/lib/index.esm.js +238 -2
  13. package/lib/index.esm.js.map +1 -1
  14. package/lib/index.js +238 -2
  15. package/lib/index.js.map +1 -1
  16. package/lib/utils/getPreviousHeadersWidth.d.ts +1 -0
  17. package/package.json +1 -1
  18. package/src/components/table/Table.mdx +134 -0
  19. package/src/components/table/Table.stories.tsx +71 -2
  20. package/src/components/table/Table.tsx +16 -1
  21. package/src/components/table/components/HorizontalStickyHeader.tsx +57 -0
  22. package/src/components/table/components/__tests__/HorizontalStickyHeader.test.tsx +104 -0
  23. package/src/components/table/components/helpers.ts +90 -0
  24. package/src/components/table/hooks/usePinnedColumnsManager.ts +146 -0
  25. package/src/components/table/{sampleData.ts → sampleData.tsx} +156 -1
  26. package/src/components/table/styles/Table.scss +32 -15
  27. package/src/components/table/styles/_variables.scss +2 -0
  28. package/src/components/table/types.ts +13 -1
  29. package/src/components/table/utils/processColumns.tsx +35 -0
  30. package/src/setup/setupTests.ts +8 -0
  31. package/src/utils/getPreviousHeadersWidth.ts +12 -0
@@ -5,3 +5,4 @@ declare const meta: Meta;
5
5
  export default meta;
6
6
  type Story = StoryObj<typeof Table<SampleDataRow>>;
7
7
  export declare const Default: Story;
8
+ export declare const PinnedColumns: Story;
@@ -0,0 +1,10 @@
1
+ interface HorizontalStickyHeaderProps {
2
+ children: React.ReactNode;
3
+ position: number;
4
+ onPinColumn?: (columnId: string) => void;
5
+ isPinned?: boolean;
6
+ forceUpdate?: number;
7
+ pinnedColumnIds: string[];
8
+ }
9
+ declare const HorizontalStickyHeader: ({ children, position, onPinColumn, isPinned, pinnedColumnIds, }: HorizontalStickyHeaderProps) => import("react/jsx-runtime").JSX.Element;
10
+ export default HorizontalStickyHeader;
@@ -0,0 +1,6 @@
1
+ import { CSSObject } from 'styled-components';
2
+ export declare const getPreviousHeadersWidth: (position: number, pinnedColumnIds: string[]) => number;
3
+ export declare const applyStickyStylesToTableHeader: (position: number, left: number) => Promise<void>;
4
+ export declare const sortPinnedColumns: <T>(columns: T[], pinnedColumnIds: string[]) => T[];
5
+ export declare const getPinnedColumnStyles: (isPinned: boolean, index: number, pinnedColumnIds: string[]) => CSSObject;
6
+ export declare const clearStickyStyles: (header: HTMLElement) => void;
@@ -0,0 +1,8 @@
1
+ import { TableColumn } from '../types';
2
+ /**
3
+ * Hook to manage pinned columns in a table
4
+ * Handles initialization, toggling, positioning and resizing of pinned columns
5
+ */
6
+ export declare const usePinnedColumnsManager: <T>(columns: TableColumn<T>[], canPinColumns: boolean, onPinnedColumnsChange?: (pinnedColumnIds: string[]) => void) => {
7
+ columnsWithPinning: TableColumn<T>[];
8
+ };
@@ -6,6 +6,10 @@ export interface SampleDataRow {
6
6
  weapon: string;
7
7
  backstory: string;
8
8
  favoriteMeal: string;
9
+ homeland: string;
10
+ alignment: string;
11
+ specialAbility: string;
12
+ test: string;
9
13
  }
10
14
  export declare const sampleData: SampleDataRow[];
11
15
  export declare const columns: TableColumn<SampleDataRow>[];
@@ -1,12 +1,22 @@
1
1
  import { Direction as RDTDirection, Alignment as RDTAlignment, TableColumn as RDTTableColumn, IDataTableProps } from 'react-data-table-component';
2
+ import { CSSObject } from 'styled-components';
2
3
  export type Direction = `${RDTDirection}`;
3
4
  export type Alignment = `${RDTAlignment}`;
4
- export type TableColumn<T> = RDTTableColumn<T>;
5
+ export interface PinnableColumn<T> extends RDTTableColumn<T> {
6
+ id: string;
7
+ isPinned?: boolean;
8
+ style?: CSSObject;
9
+ position?: number;
10
+ }
11
+ export type TableColumn<T> = PinnableColumn<T>;
5
12
  export interface TableProps<T> extends Omit<IDataTableProps<T>, 'paginationComponent' | 'direction' | 'subHeaderAlign'> {
13
+ columns: TableColumn<T>[];
6
14
  isDisabled?: boolean;
7
15
  isLoading?: boolean;
8
16
  direction?: Direction;
9
17
  subHeaderAlign?: 'left' | 'right' | 'center';
10
18
  isFullHeight?: boolean;
11
19
  totalEntriesText?: string;
20
+ canPinColumns?: boolean;
21
+ onPinnedColumnsChange?: (pinnedColumnIds: any[]) => void;
12
22
  }
@@ -0,0 +1,2 @@
1
+ import { TableColumn } from '../types';
2
+ export declare const processColumns: <T>(columns: TableColumn<T>[], pinnedColumnIds: string[], togglePinnedColumn: (id: string) => void) => TableColumn<T>[];
package/lib/index.css CHANGED
@@ -804,6 +804,8 @@ a:hover,
804
804
  --pf-table-highlighted-box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4), 0 8px 16px rgba(0, 0, 0, 0.3);
805
805
  --pf-table-font-size: var(--pf-font-size-body2);
806
806
  --pf-table-pagination-background-color: var(--pf-primary-color-700);
807
+ --pf-table-pinned-column-border-color: var(--pf-primary-color-100);
808
+ --pf-table-pinned-column-background-color: var(--pf-table-background-color);
807
809
  }
808
810
 
809
811
  .table-loading {
@@ -856,6 +858,20 @@ a:hover,
856
858
  .table-body::-webkit-scrollbar-thumb:hover {
857
859
  background: var(--pf-primary-color);
858
860
  }
861
+ .table .table__column__pin-action {
862
+ padding: 0;
863
+ padding-right: var(--pf-padding-1);
864
+ }
865
+ .table .table__column--is-pinned {
866
+ opacity: 1;
867
+ }
868
+ .table .table__column--is-not-pinned {
869
+ opacity: 0.3;
870
+ }
871
+ .table .table__header-cell {
872
+ display: flex;
873
+ align-items: center;
874
+ }
859
875
  .table > *:nth-child(3) {
860
876
  margin-top: auto;
861
877
  background-color: transparent;
@@ -881,27 +897,26 @@ a:hover,
881
897
  .table button:disabled svg {
882
898
  fill: var(--pf-table-disabled-button-color);
883
899
  }
900
+ .table .rdt_TableHead {
901
+ z-index: 3;
902
+ }
884
903
  .table .rdt_TableHeader {
885
904
  border-radius: var(--pf-rounded) 0;
886
905
  border: var(--pf-border-sm) solid var(--pf-table-border-color);
887
906
  border-bottom: none;
888
907
  }
889
- .table .rdt_TableHeadRow > :first-child,
890
- .table .rdt_TableRow > :first-child {
891
- padding-left: var(--pf-padding-4);
892
- min-width: 60px;
893
- justify-content: left;
894
- }
895
908
  .table .rdt_TableRow {
896
909
  border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
897
910
  border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
898
911
  }
912
+ .table .rdt_TableRow:hover {
913
+ border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
914
+ border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
915
+ outline-color: var(--pf-table-border-color);
916
+ }
899
917
  .table .rdt_TableRow:hover .rdt_TableCell {
900
918
  background-color: var(--pf-table-hover-color) !important;
901
919
  }
902
- .table .rdt_TableRow:first-child .rdt_TableCell {
903
- border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
904
- }
905
920
  .table .rdt_TableCell,
906
921
  .table .rdt_TableCol {
907
922
  font-size: var(--pf-table-font-size);
@@ -910,6 +925,10 @@ a:hover,
910
925
  .table .rdt_TableCol:not(:first-child) {
911
926
  border-left: var(--pf-border-sm) solid var(--pf-table-border-color);
912
927
  }
928
+ .table .rdt_TableCell:not(:last-of-type),
929
+ .table .rdt_TableCol:not(:last-of-type) {
930
+ border-bottom-width: 0;
931
+ }
913
932
  .table .table--striped .rdt_TableRow:nth-child(odd) .rdt_TableCell {
914
933
  background-color: var(--pf-table-stripe-color);
915
934
  }
package/lib/index.d.ts CHANGED
@@ -4,7 +4,8 @@ export * from '@floating-ui/react-dom';
4
4
  import React$1, { CSSProperties, MouseEventHandler, ReactElement } from 'react';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import { ContainerProps, RowProps, ColProps } from 'react-grid-system';
7
- import { IDataTableProps, Direction as Direction$1 } from 'react-data-table-component';
7
+ import { IDataTableProps, Direction as Direction$1, TableColumn as TableColumn$1 } from 'react-data-table-component';
8
+ import { CSSObject } from 'styled-components';
8
9
  import { Props as Props$7 } from 'react-select';
9
10
  import { DateRange, OnSelectHandler, Mode, CustomComponents, Matcher, Formatters, MonthChangeEventHandler, DayEventHandler } from 'react-day-picker';
10
11
 
@@ -184,13 +185,23 @@ type SelectOption = {
184
185
  };
185
186
 
186
187
  type Direction = `${Direction$1}`;
188
+ interface PinnableColumn<T> extends TableColumn$1<T> {
189
+ id: string;
190
+ isPinned?: boolean;
191
+ style?: CSSObject;
192
+ position?: number;
193
+ }
194
+ type TableColumn<T> = PinnableColumn<T>;
187
195
  interface TableProps<T> extends Omit<IDataTableProps<T>, 'paginationComponent' | 'direction' | 'subHeaderAlign'> {
196
+ columns: TableColumn<T>[];
188
197
  isDisabled?: boolean;
189
198
  isLoading?: boolean;
190
199
  direction?: Direction;
191
200
  subHeaderAlign?: 'left' | 'right' | 'center';
192
201
  isFullHeight?: boolean;
193
202
  totalEntriesText?: string;
203
+ canPinColumns?: boolean;
204
+ onPinnedColumnsChange?: (pinnedColumnIds: any[]) => void;
194
205
  }
195
206
 
196
207
  type PillSize = 'sm' | 'md' | 'lg';
package/lib/index.esm.css CHANGED
@@ -804,6 +804,8 @@ a:hover,
804
804
  --pf-table-highlighted-box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4), 0 8px 16px rgba(0, 0, 0, 0.3);
805
805
  --pf-table-font-size: var(--pf-font-size-body2);
806
806
  --pf-table-pagination-background-color: var(--pf-primary-color-700);
807
+ --pf-table-pinned-column-border-color: var(--pf-primary-color-100);
808
+ --pf-table-pinned-column-background-color: var(--pf-table-background-color);
807
809
  }
808
810
 
809
811
  .table-loading {
@@ -856,6 +858,20 @@ a:hover,
856
858
  .table-body::-webkit-scrollbar-thumb:hover {
857
859
  background: var(--pf-primary-color);
858
860
  }
861
+ .table .table__column__pin-action {
862
+ padding: 0;
863
+ padding-right: var(--pf-padding-1);
864
+ }
865
+ .table .table__column--is-pinned {
866
+ opacity: 1;
867
+ }
868
+ .table .table__column--is-not-pinned {
869
+ opacity: 0.3;
870
+ }
871
+ .table .table__header-cell {
872
+ display: flex;
873
+ align-items: center;
874
+ }
859
875
  .table > *:nth-child(3) {
860
876
  margin-top: auto;
861
877
  background-color: transparent;
@@ -881,27 +897,26 @@ a:hover,
881
897
  .table button:disabled svg {
882
898
  fill: var(--pf-table-disabled-button-color);
883
899
  }
900
+ .table .rdt_TableHead {
901
+ z-index: 3;
902
+ }
884
903
  .table .rdt_TableHeader {
885
904
  border-radius: var(--pf-rounded) 0;
886
905
  border: var(--pf-border-sm) solid var(--pf-table-border-color);
887
906
  border-bottom: none;
888
907
  }
889
- .table .rdt_TableHeadRow > :first-child,
890
- .table .rdt_TableRow > :first-child {
891
- padding-left: var(--pf-padding-4);
892
- min-width: 60px;
893
- justify-content: left;
894
- }
895
908
  .table .rdt_TableRow {
896
909
  border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
897
910
  border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
898
911
  }
912
+ .table .rdt_TableRow:hover {
913
+ border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
914
+ border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
915
+ outline-color: var(--pf-table-border-color);
916
+ }
899
917
  .table .rdt_TableRow:hover .rdt_TableCell {
900
918
  background-color: var(--pf-table-hover-color) !important;
901
919
  }
902
- .table .rdt_TableRow:first-child .rdt_TableCell {
903
- border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
904
- }
905
920
  .table .rdt_TableCell,
906
921
  .table .rdt_TableCol {
907
922
  font-size: var(--pf-table-font-size);
@@ -910,6 +925,10 @@ a:hover,
910
925
  .table .rdt_TableCol:not(:first-child) {
911
926
  border-left: var(--pf-border-sm) solid var(--pf-table-border-color);
912
927
  }
928
+ .table .rdt_TableCell:not(:last-of-type),
929
+ .table .rdt_TableCol:not(:last-of-type) {
930
+ border-bottom-width: 0;
931
+ }
913
932
  .table .table--striped .rdt_TableRow:nth-child(odd) .rdt_TableCell {
914
933
  background-color: var(--pf-table-stripe-color);
915
934
  }
package/lib/index.esm.js CHANGED
@@ -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;
@@ -7256,8 +7266,234 @@ const TablePagination = ({ rowsPerPage, rowCount, onChangePage, currentPage, tot
7256
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) }) })] }) }));
7257
7267
  };
7258
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
+
7259
7493
  const Table = (props) => {
7260
- const { responsive = true, direction = 'auto', keyField = 'id', striped = false, noDataComponent = 'built-in', isDisabled, isLoading, isFullHeight = false, subHeaderAlign = 'left', className, paginationTotalRows, totalEntriesText } = props, rest = __rest(props, ["responsive", "direction", "keyField", "striped", "noDataComponent", "isDisabled", "isLoading", "isFullHeight", "subHeaderAlign", "className", "paginationTotalRows", "totalEntriesText"]);
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);
7261
7497
  const combinedClassName = classNames(className, {
7262
7498
  'table--striped': striped,
7263
7499
  'table-body': true,
@@ -7265,7 +7501,7 @@ const Table = (props) => {
7265
7501
  const tableWrapperClassName = classNames('table', {
7266
7502
  'table--full-height': isFullHeight,
7267
7503
  });
7268
- return (jsx("div", { className: tableWrapperClassName, "data-testid": "table", 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, {}), pagination: true, paginationComponent: (props) => (jsx(TablePagination, Object.assign({}, props, { totalEntriesText: totalEntriesText }))), paginationTotalRows: paginationTotalRows }, rest)) }));
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)) }));
7269
7505
  };
7270
7506
 
7271
7507
  const Radio = React__default.forwardRef((_a, ref) => {