playbook_ui 14.21.2.pre.alpha.PLAY21318324 → 14.21.2.pre.alpha.PLAY22358326

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +1 -4
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +0 -8
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +36 -16
  5. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +18 -5
  6. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +37 -17
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +27 -8
  8. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +3 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +91 -40
  10. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +1 -4
  11. data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +3 -2
  12. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +32 -4
  13. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +32 -22
  14. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +10 -15
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.md +3 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +1 -1
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -3
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -1
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -1
  20. data/app/pb_kits/playbook/pb_filter/Filter/FilterSection.tsx +49 -0
  21. data/app/pb_kits/playbook/pb_filter/Filter/FilterSidebar.tsx +69 -0
  22. data/app/pb_kits/playbook/pb_filter/Filter/index.tsx +13 -0
  23. data/app/pb_kits/playbook/pb_filter/_filter.scss +4 -0
  24. data/app/pb_kits/playbook/pb_filter/docs/_filter_sidebar.jsx +224 -0
  25. data/app/pb_kits/playbook/pb_filter/docs/example.yml +1 -0
  26. data/app/pb_kits/playbook/pb_filter/docs/index.js +1 -0
  27. data/dist/chunks/{_typeahead-CoOpeYom.js → _typeahead-CVIBi3oA.js} +2 -2
  28. data/dist/chunks/_weekday_stacked-BknM0ZnU.js +45 -0
  29. data/dist/chunks/vendor.js +1 -1
  30. data/dist/playbook-doc.js +1 -1
  31. data/dist/playbook-rails-react-bindings.js +1 -1
  32. data/dist/playbook-rails.js +1 -1
  33. data/dist/playbook.css +1 -1
  34. data/lib/playbook/version.rb +1 -1
  35. metadata +7 -5
  36. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.jsx +0 -64
  37. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.md +0 -7
  38. data/dist/chunks/_weekday_stacked-BPs62iuT.js +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c17abab576d5fd7c20055de8ccd116937d25c593db8bd741469855415781fe06
4
- data.tar.gz: e8150dced7379d9fd97511d3bcbd847b12af8efde286c5810cbfb7a9e656428f
3
+ metadata.gz: 775191059b582c0fb74cc6d654e3b563226fbe855b9b9f267fa4cd982955fa2f
4
+ data.tar.gz: fca502f3f539f439b6471b266cc211b46bb0fcba13d00189e89ce0893df0a9be
5
5
  SHA512:
6
- metadata.gz: fec56b58208ddb3cc23e1c614ce43c8ab9bb05e47ed8f2c7a28e4aa851d2e5a1155177229fddca90ecad1950e34729f1b76a9fcae01f407e88841b54d6b47180
7
- data.tar.gz: ec52041b049419fd5027839e93e67beb4f006fdfb7dfef230fa9f7d9c6a94f8d6251d4dec33b91afa21aeab56295284229d0bcc55be40c828498f7a845823981
6
+ metadata.gz: 61fc896c9d0a0a65db99048f13c0ac4fe70a1bd3a036a807759a699bbdf7a10589898f04760eed3b77fab43f664d798bf9a7731dd20f761255d9f86be68317f5
7
+ data.tar.gz: 923bafc7292dbf1cd30e529e20add0175ca391d4e1630c9cacb1a4f26f2696209f80acc8aca8ba96e344c60eb7ef73e211778204a9aaab0b5159403a92bad7d5
@@ -19,7 +19,6 @@ interface CustomCellProps {
19
19
  value?: string
20
20
  customRenderer?: (row: Row<GenericObject>, value: string | undefined) => React.ReactNode
21
21
  selectableRows?: boolean
22
- customStyle?: GenericObject
23
22
  }
24
23
 
25
24
  export const CustomCell = ({
@@ -29,7 +28,6 @@ export const CustomCell = ({
29
28
  value,
30
29
  customRenderer,
31
30
  selectableRows,
32
- customStyle = {},
33
31
  }: CustomCellProps & GlobalProps) => {
34
32
  const { setExpanded, expanded, expandedControl, inlineRowLoading, hasAnySubRows } = useContext(AdvancedTableContext);
35
33
 
@@ -45,7 +43,7 @@ export const CustomCell = ({
45
43
  const renderButton = inlineRowLoading ? RowHasChildren : row.getCanExpand()
46
44
 
47
45
  return (
48
- <div style={{ paddingLeft: `${row.depth * 1.25}em`}}>
46
+ <div style={{ paddingLeft: `${row.depth * 1.25}em` }}>
49
47
  <Flex
50
48
  alignItems="center"
51
49
  columnGap="xs"
@@ -67,7 +65,6 @@ export const CustomCell = ({
67
65
  <button
68
66
  className="gray-icon expand-toggle-icon"
69
67
  onClick={() => handleOnExpand(row)}
70
- style={{ color: customStyle?.expandButtonColor }}
71
68
  >
72
69
  {row.getIsExpanded() ? (
73
70
  <Icon cursor="pointer"
@@ -27,7 +27,6 @@ const TableCellRenderer = ({
27
27
  loading = false,
28
28
  stickyLeftColumn,
29
29
  columnPinning,
30
- customRowStyle,
31
30
  columnDefinitions,
32
31
  }: {
33
32
  row: Row<GenericObject>
@@ -35,7 +34,6 @@ const TableCellRenderer = ({
35
34
  loading?: boolean | string
36
35
  stickyLeftColumn?: string[]
37
36
  columnPinning: { left: string[] }
38
- customRowStyle?: GenericObject
39
37
  columnDefinitions?: {[key:string]:any}[]
40
38
  }) => {
41
39
  return (
@@ -76,8 +74,6 @@ const TableCellRenderer = ({
76
74
  ? '180px'
77
75
  : `${column.getStart("left")}px`
78
76
  : undefined,
79
- backgroundColor: i === 0 && customRowStyle?.backgroundColor,
80
- color: customRowStyle?.fontColor,
81
77
  }}
82
78
  >
83
79
  {collapsibleTrail && i === 0 && row.depth > 0 && renderCollapsibleTrail(row.depth)}
@@ -111,7 +107,6 @@ export const RegularTableView = ({
111
107
  pinnedRows,
112
108
  headerHeight,
113
109
  rowHeight,
114
- rowStyling = [],
115
110
  sampleRowRef,
116
111
  } = useContext(AdvancedTableContext)
117
112
 
@@ -176,7 +171,6 @@ export const RegularTableView = ({
176
171
  const rowBackground = isExpandable && ((!inlineRowLoading && row.getCanExpand()) || (inlineRowLoading && rowHasNoChildren));
177
172
  const rowColor = row.getIsSelected() ? "bg-row-selection" : rowBackground ? "bg-silver" : "bg-white";
178
173
  const isFirstRegularRow = rowIndex === 0 && !row.getIsPinned();
179
- const customRowStyle = rowStyling?.length > 0 && rowStyling?.find((s: GenericObject) => s?.rowId === row.id);
180
174
 
181
175
  return (
182
176
  <React.Fragment key={`${row.index}-${row.id}-${row.depth}-row`}>
@@ -195,7 +189,6 @@ export const RegularTableView = ({
195
189
  className={`${rowColor} ${row.depth > 0 ? `depth-sub-row-${row.depth}` : ""}`}
196
190
  id={`${row.index}-${row.id}-${row.depth}-row`}
197
191
  ref={isFirstRegularRow ? sampleRowRef : null}
198
- style={{backgroundColor: customRowStyle?.backgroundColor, color: customRowStyle?.fontColor}}
199
192
  >
200
193
  {/* Render custom checkbox column when we want selectableRows for non-expanding tables */}
201
194
  {selectableRows && !hasAnySubRows && (
@@ -213,7 +206,6 @@ export const RegularTableView = ({
213
206
  collapsibleTrail={collapsibleTrail}
214
207
  columnDefinitions={columnDefinitions}
215
208
  columnPinning={columnPinning}
216
- customRowStyle={customRowStyle}
217
209
  loading={loading}
218
210
  row={row}
219
211
  stickyLeftColumn={stickyLeftColumn}
@@ -1,6 +1,6 @@
1
- import React, { useContext, useLayoutEffect, useState, useEffect } from "react"
1
+ import React, { useContext, useLayoutEffect, useState, useEffect, useRef } from "react"
2
2
  import classnames from "classnames"
3
- import { flexRender, Cell } from "@tanstack/react-table"
3
+ import { flexRender, Cell, Row } from "@tanstack/react-table"
4
4
  import { VirtualItem } from "@tanstack/react-virtual"
5
5
 
6
6
  import { GenericObject } from "../../types"
@@ -10,6 +10,8 @@ import { getVirtualizedRowStyle } from "../Utilities/TableContainerStyles"
10
10
 
11
11
  import LoadingInline from "../../pb_loading_inline/_loading_inline"
12
12
  import Checkbox from "../../pb_checkbox/_checkbox"
13
+ import Detail from "../../pb_detail/_detail"
14
+ import Flex from "../../pb_flex/_flex"
13
15
 
14
16
  import { SubRowHeaderRow } from "../Components/SubRowHeaderRow"
15
17
  import { LoadingCell } from "../Components/LoadingCell"
@@ -20,11 +22,13 @@ import AdvancedTableContext from "../Context/AdvancedTableContext"
20
22
  type VirtualizedTableViewProps = {
21
23
  collapsibleTrail?: boolean
22
24
  subRowHeaders?: string[]
25
+ isFetching: boolean
23
26
  }
24
27
 
25
28
  export const VirtualizedTableView = ({
26
29
  collapsibleTrail = true,
27
30
  subRowHeaders,
31
+ isFetching,
28
32
  }: VirtualizedTableViewProps) => {
29
33
  const {
30
34
  enableToggleExpansion,
@@ -36,6 +40,7 @@ export const VirtualizedTableView = ({
36
40
  hasAnySubRows,
37
41
  virtualizer,
38
42
  flattenedItems,
43
+ totalAvailableCount,
39
44
  } = useContext(AdvancedTableContext)
40
45
 
41
46
  const columnPinning = table.getState().columnPinning || { left: [] };
@@ -121,19 +126,7 @@ export const VirtualizedTableView = ({
121
126
  }
122
127
 
123
128
  // Get virtual items
124
- let virtualItems: VirtualItem[] = [];
125
- try {
126
- virtualItems = virtualizer.getVirtualItems();
127
- } catch (err) {
128
- return (
129
- <tr>
130
- <td colSpan={table.getAllFlatColumns().length || 1}>
131
- Error loading virtualized data.
132
- </td>
133
- </tr>
134
- );
135
- }
136
-
129
+ const virtualItems: VirtualItem[] = virtualizer.getVirtualItems?.() || [];
137
130
  if (!virtualItems.length) {
138
131
  return (
139
132
  <tr>
@@ -143,6 +136,9 @@ export const VirtualizedTableView = ({
143
136
  </tr>
144
137
  );
145
138
  }
139
+
140
+ // Establish # of Parent Rows (so that Footer count does not include every single row)
141
+ const topLevelRowCount = table.getRowModel().flatRows.filter((row: Row<GenericObject>) => row.depth === 0).length;
146
142
 
147
143
  return (
148
144
  <>
@@ -177,7 +173,7 @@ export const VirtualizedTableView = ({
177
173
  if (item.type === 'row') {
178
174
  const row = item.row;
179
175
  const isExpandable = row.getIsExpanded();
180
- const rowHasNoChildren = row.original?.children && !row.original.children.length ? true : false;
176
+ const rowHasNoChildren = row.original?.children && !row.original.children.length;
181
177
  const rowBackground = isExpandable && ((!inlineRowLoading && row.getCanExpand()) || (inlineRowLoading && rowHasNoChildren));
182
178
  const rowColor = row.getIsSelected() ? "bg-row-selection" : rowBackground ? "bg-silver" : "bg-white";
183
179
 
@@ -266,6 +262,30 @@ export const VirtualizedTableView = ({
266
262
  );
267
263
  }
268
264
 
265
+ if (item.type === 'footer') {
266
+ // Render footer
267
+ return (
268
+ <tr
269
+ className="virtualized-table-row virtualized-footer"
270
+ key={`footer-row`}
271
+ style={virtualItemStyle}
272
+ >
273
+ <td colSpan={table.getAllFlatColumns().length}>
274
+ <Flex align="center"
275
+ justify="center"
276
+ >
277
+
278
+ {isFetching ? (
279
+ <LoadingInline />
280
+ ) : (
281
+ <Detail text={`Showing ${topLevelRowCount} of ${totalAvailableCount} rows`} />
282
+ )}
283
+ </Flex>
284
+ </td>
285
+ </tr>
286
+ )
287
+ }
288
+
269
289
  return null;
270
290
  })}
271
291
  </>
@@ -8,7 +8,7 @@ import { getRowHeightEstimate } from '../Utilities/TableContainerStyles';
8
8
  const AdvancedTableContext = createContext<any>({});
9
9
 
10
10
  interface FlattenedItem {
11
- type: 'header' | 'row' | 'loading';
11
+ type: 'header' | 'row' | 'loading' | 'footer';
12
12
  row: Row<GenericObject>;
13
13
  id: string;
14
14
  }
@@ -116,6 +116,17 @@ export const AdvancedTableProvider = ({ children, ...props }: {
116
116
  }
117
117
  });
118
118
 
119
+ const isFetching = props.isFetching || false;
120
+ const shouldAddFooter = table && !isFetching && tableRows.length > 0
121
+
122
+ if (shouldAddFooter) {
123
+ items.push({
124
+ type: 'footer',
125
+ row: {} as Row<GenericObject>,
126
+ id: `footer-row`,
127
+ });
128
+ }
129
+
119
130
  return items;
120
131
  }, [
121
132
  isVirtualized,
@@ -159,10 +170,11 @@ export const AdvancedTableProvider = ({ children, ...props }: {
159
170
  useEffect(() => {
160
171
  if (isVirtualized && virtualizer && table && containerRef.current) {
161
172
  // Force recalculation of all virtual items
173
+ virtualizer.setOptions({
174
+ ...virtualizer.options,
175
+ count: flattenedItems.length,
176
+ });
162
177
  virtualizer.measure();
163
-
164
- // Reset scroll position when sorting changes
165
- containerRef.current.scrollTop = 0;
166
178
  }
167
179
  }, [
168
180
  isVirtualized,
@@ -170,7 +182,8 @@ export const AdvancedTableProvider = ({ children, ...props }: {
170
182
  table,
171
183
  containerRef,
172
184
  JSON.stringify(table?.getState().sorting || []),
173
- JSON.stringify(table?.getState().expanded || {})
185
+ JSON.stringify(table?.getState().expanded || {}),
186
+ flattenedItems.length,
174
187
  ]);
175
188
 
176
189
  const contextValue = {
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect } from 'react';
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { Row, RowPinningState } from "@tanstack/react-table";
3
3
  import { GenericObject } from "../../types";
4
4
  import { updateExpandAndCollapseState } from "../Utilities/ExpansionControlHelpers";
@@ -19,13 +19,21 @@ export function useTableActions({
19
19
  onRowSelectionChange
20
20
  }: UseTableActionsProps) {
21
21
 
22
+ // State to achieve 1 second delay before fetching more rows
23
+ const [bottomReached, setBottomReached] = useState(false)
24
+ const bottomTimeout = useRef<NodeJS.Timeout | null>(null)
25
+
22
26
  // Handle expand/collapse
23
27
  const handleExpandOrCollapse = useCallback(async (row: Row<GenericObject>) => {
24
- onToggleExpansionClick && onToggleExpansionClick(row);
25
- const expandedState = expanded;
26
- const targetParent = row?.parentId;
27
- const updatedRows = await updateExpandAndCollapseState(table.getRowModel(), expandedState, targetParent, undefined);
28
- setExpanded(updatedRows);
28
+ if (onToggleExpansionClick) onToggleExpansionClick(row)
29
+ const updatedExpandedState = await updateExpandAndCollapseState(
30
+ table.getRowModel(),
31
+ expanded,
32
+ row?.parentId,
33
+ undefined
34
+ )
35
+
36
+ setExpanded(updatedExpandedState)
29
37
  }, [expanded, setExpanded, onToggleExpansionClick, table]);
30
38
 
31
39
  // Handle pagination
@@ -35,20 +43,32 @@ export function useTableActions({
35
43
 
36
44
  // Handle scroll detection for infinite scroll/virtualization
37
45
  const fetchMoreOnBottomReached = useCallback((
38
- containerRefElement: HTMLDivElement | null,
39
- fetchNextPage: () => void,
40
- isFetching: boolean,
41
- totalFetched: number,
42
- totalDBRowCount: number
46
+ containerRef: HTMLDivElement | null,
47
+ fetchNextPage: () => void,
48
+ isFetching: boolean,
49
+ totalFetched: number,
50
+ totalDBRowCount: number
43
51
  ) => {
44
- if (containerRefElement) {
45
- const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
46
- // If user scrolls near bottom, fetch more data
47
- if (scrollHeight - scrollTop - clientHeight < 500 && !isFetching && totalFetched < totalDBRowCount) {
48
- fetchNextPage();
52
+ if (!containerRef || isFetching || totalFetched >= totalDBRowCount) return
53
+ const { scrollTop, scrollHeight, clientHeight } = containerRef
54
+ const distanceFromBottom = scrollHeight - scrollTop - clientHeight
55
+ // If user scrolls near bottom, fetch more data after 1 second delay
56
+ if (distanceFromBottom < 50) {
57
+ if (!bottomReached) {
58
+ setBottomReached(true)
59
+ bottomTimeout.current = setTimeout(() => {
60
+ fetchNextPage()
61
+ setBottomReached(false)
62
+ }, 1000)
63
+ }
64
+ } else {
65
+ setBottomReached(false)
66
+ if (bottomTimeout.current) {
67
+ clearTimeout(bottomTimeout.current)
68
+ bottomTimeout.current = null
49
69
  }
50
70
  }
51
- }, []);
71
+ },[bottomReached]);
52
72
 
53
73
  // Update selection state
54
74
  useEffect(() => {
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useMemo } from 'react';
1
+ import { useState, useCallback, useMemo, useEffect } from 'react';
2
2
  import {
3
3
  useReactTable,
4
4
  getCoreRowModel,
@@ -32,7 +32,6 @@ interface UseTableStateProps {
32
32
  tableOptions?: GenericObject;
33
33
  onRowSelectionChange?: (arg: RowSelectionState) => void;
34
34
  columnVisibilityControl?: GenericObject;
35
- rowStyling?: GenericObject;
36
35
  }
37
36
 
38
37
  export function useTableState({
@@ -50,8 +49,8 @@ export function useTableState({
50
49
  tableOptions,
51
50
  columnVisibilityControl,
52
51
  pinnedRows,
53
- rowStyling
54
52
  }: UseTableStateProps) {
53
+
55
54
  // Create a local state for expanded and setExpanded if expandedControl not used
56
55
  const [localExpanded, setLocalExpanded] = useState({});
57
56
  const [loadingStateRowCount, setLoadingStateRowCount] = useState(initialLoadingRowsCount);
@@ -65,8 +64,8 @@ export function useTableState({
65
64
  const setExpanded = expandedControl ? expandedControl.onChange : setLocalExpanded;
66
65
  const columnVisibility = (columnVisibilityControl && columnVisibilityControl.value) ? columnVisibilityControl.value : localColumnVisibility;
67
66
  const setColumnVisibility = (columnVisibilityControl && columnVisibilityControl.onChange) ? columnVisibilityControl.onChange : setLocalColumnVisibility;
68
- const rowPinning = pinnedRows && pinnedRows.value || localRowPinning;
69
- const setRowPinning = (pinnedRows && pinnedRows.onChange) ? pinnedRows.onChange : setLocalRowPinning;
67
+ const rowPinning = pinnedRows?.value ?? localRowPinning
68
+ const onRowPinningChange = pinnedRows?.onChange ?? setLocalRowPinning
70
69
 
71
70
  // Virtualized data handling (chunked loading)
72
71
  const fetchSize = 20; // Number of rows per "page"
@@ -104,8 +103,7 @@ export function useTableState({
104
103
  column.customRenderer,
105
104
  isFirstColumn,
106
105
  onRowToggleClick,
107
- selectableRows,
108
- rowStyling
106
+ selectableRows
109
107
  );
110
108
  }
111
109
 
@@ -168,7 +166,8 @@ export function useTableState({
168
166
  enableSortingRemoval: false,
169
167
  sortDescFirst: true,
170
168
  onRowSelectionChange: setRowSelection,
171
- getRowId: (selectableRows || pinnedRows || rowStyling) ? row => row.id : undefined,
169
+ onRowPinningChange,
170
+ getRowId: (selectableRows || pinnedRows) ? row => row.id : undefined,
172
171
  onColumnVisibilityChange: setColumnVisibility,
173
172
  meta: {
174
173
  columnDefinitions
@@ -178,6 +177,26 @@ export function useTableState({
178
177
  ...tableOptions,
179
178
  });
180
179
 
180
+ // Handle row pinning changes
181
+ useEffect(() => {
182
+ const topPins = pinnedRows?.value?.top ?? [];
183
+ if (topPins.length === 0) {
184
+ onRowPinningChange({ top: [] });
185
+ return;
186
+ }
187
+ const rows = table.getRowModel().rows;
188
+ const collectAllDescendantIds = (subs: Row<GenericObject>[]): string[] =>
189
+ subs.flatMap(r => [r.id, ...collectAllDescendantIds(r.subRows)]);
190
+ const allPinned: string[] = [];
191
+ topPins.forEach(id => {
192
+ const parent = rows.find(r => r.id === id && r.depth === 0);
193
+ if (parent) {
194
+ allPinned.push(parent.id, ...collectAllDescendantIds(parent.subRows));
195
+ }
196
+ });
197
+ onRowPinningChange({ top: allPinned });
198
+ }, [table, pinnedRows?.value?.top?.join(',')]);
199
+
181
200
  // Check if table has any sub-rows
182
201
  const hasAnySubRows = table.getRowModel().rows.some(row => row.subRows && row.subRows.length > 0);
183
202
  const selectedRowsLength = Object.keys(table.getState().rowSelection).length;
@@ -16,6 +16,7 @@ type TableBodyProps = {
16
16
  dark?: boolean
17
17
  id?: string
18
18
  subRowHeaders?: string[]
19
+ isFetching: boolean
19
20
  }
20
21
 
21
22
  export const TableBody = ({
@@ -24,6 +25,7 @@ export const TableBody = ({
24
25
  dark = false,
25
26
  id,
26
27
  subRowHeaders,
28
+ isFetching,
27
29
  ...props
28
30
  }: TableBodyProps) => {
29
31
 
@@ -63,6 +65,7 @@ export const TableBody = ({
63
65
  // Virtualized table view
64
66
  <VirtualizedTableView
65
67
  collapsibleTrail={collapsibleTrail}
68
+ isFetching={isFetching}
66
69
  subRowHeaders={subRowHeaders}
67
70
  />
68
71
  ) : (
@@ -40,9 +40,13 @@ export const TableHeader = ({
40
40
  showActionsBar,
41
41
  selectableRows,
42
42
  responsive,
43
- headerRef
43
+ headerRef,
44
+ virtualizedRows,
45
+ enableVirtualization,
44
46
  } = useContext(AdvancedTableContext)
45
47
 
48
+ const isVirtualized = virtualizedRows || enableVirtualization;
49
+
46
50
  const classes = classnames(
47
51
  buildCss("pb_advanced_table_header"),
48
52
  globalProps(props),
@@ -57,46 +61,93 @@ export const TableHeader = ({
57
61
  `${isChrome() ? "chrome-styles" : ""}`,
58
62
  `${responsive === "scroll" && "pinned-left"}`,
59
63
  );
64
+
65
+ const renderRegularTableHeader = () => (
66
+ <thead className={classes}
67
+ id={id}
68
+ >
69
+ {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>, index: number) => (
70
+ <tr
71
+ key={`${headerGroup.id}-headerGroup`}
72
+ ref={index === 0 ? headerRef : null}
73
+ >
74
+ {!hasAnySubRows && selectableRows && (
75
+ <th className={customCellClassnames}>
76
+ <Checkbox
77
+ checked={table?.getIsAllRowsSelected()}
78
+ indeterminate={table?.getIsSomeRowsSelected()}
79
+ onChange={table?.getToggleAllRowsSelectedHandler()}
80
+ />
81
+ </th>
82
+ )}
83
+ {headerGroup.headers.map(header => {
84
+ const isPinnedLeft = columnPinning.left.includes(header.id)
85
+ return (
86
+ <TableHeaderCell
87
+ enableSorting={enableSorting}
88
+ enableToggleExpansion={enableToggleExpansion}
89
+ handleExpandOrCollapse={handleExpandOrCollapse}
90
+ header={header}
91
+ headerChildren={children}
92
+ isPinnedLeft={isPinnedLeft}
93
+ key={`${header.id}-header`}
94
+ loading={loading}
95
+ sortIcon={sortIcon}
96
+ table={table}
97
+ />
98
+ )
99
+ })}
100
+ </tr>
101
+ ))}
102
+ </thead>
103
+ );
104
+
105
+ const renderVirtualizedTableHeader = () => (
106
+ <thead
107
+ className={classes}
108
+ data-virtualized="true"
109
+ id={id}
110
+ >
111
+ {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>, index: number) => (
112
+ <tr
113
+ className="virtualized-header-row-header"
114
+ key={`${headerGroup.id}-headerGroup-virtualized`}
115
+ ref={index === 0 ? headerRef : null}
116
+ >
117
+ {!hasAnySubRows && selectableRows && (
118
+ <th className={classnames(customCellClassnames, "virtualized-header-cell")}>
119
+ <Checkbox
120
+ checked={table?.getIsAllRowsSelected()}
121
+ indeterminate={table?.getIsSomeRowsSelected()}
122
+ onChange={table?.getToggleAllRowsSelectedHandler()}
123
+ />
124
+ </th>
125
+ )}
126
+ {headerGroup.headers.map(header => {
127
+ const isPinnedLeft = columnPinning.left.includes(header.id)
128
+ return (
129
+ <TableHeaderCell
130
+ enableSorting={enableSorting}
131
+ enableToggleExpansion={enableToggleExpansion}
132
+ handleExpandOrCollapse={handleExpandOrCollapse}
133
+ header={header}
134
+ headerChildren={children}
135
+ isPinnedLeft={isPinnedLeft}
136
+ isVirtualized
137
+ key={`${header.id}-header-virtualized`}
138
+ loading={loading}
139
+ sortIcon={sortIcon}
140
+ table={table}
141
+ />
142
+ )
143
+ })}
144
+ </tr>
145
+ ))}
146
+ </thead>
147
+ );
60
148
  return (
61
- <>
62
- <thead className={classes}
63
- id={id}
64
- >
65
- {/* Get the header groups (only one in this example) */}
66
- {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>, index: number) => (
67
- <tr
68
- key={`${headerGroup.id}-headerGroup`}
69
- ref={index === 0 ? headerRef : null}
70
- >
71
- {!hasAnySubRows && selectableRows && (
72
- <th className={customCellClassnames}>
73
- <Checkbox
74
- checked={table?.getIsAllRowsSelected()}
75
- indeterminate={table?.getIsSomeRowsSelected()}
76
- onChange={table?.getToggleAllRowsSelectedHandler()}
77
- />
78
- </th>
79
- )}
80
- {headerGroup.headers.map(header => {
81
- const isPinnedLeft = columnPinning.left.includes(header.id)
82
- return (
83
- <TableHeaderCell
84
- enableSorting={enableSorting}
85
- enableToggleExpansion={enableToggleExpansion}
86
- handleExpandOrCollapse={handleExpandOrCollapse}
87
- header={header}
88
- headerChildren={children}
89
- isPinnedLeft={isPinnedLeft}
90
- key={`${header.id}-header`}
91
- loading={loading}
92
- sortIcon={sortIcon}
93
- table={table}
94
- />
95
- )
96
- })}
97
- </tr>
98
- ))}
99
- </thead>
149
+ <>
150
+ {isVirtualized ? renderVirtualizedTableHeader() : renderRegularTableHeader()}
100
151
  </>
101
152
  )
102
153
  }
@@ -17,8 +17,7 @@ export const createCellFunction = (
17
17
  customRenderer?: (row: Row<GenericObject>, value: any) => JSX.Element,
18
18
  isFirstColumn?: boolean,
19
19
  onRowToggleClick?: (row: Row<GenericObject>) => void,
20
- selectableRows?: boolean,
21
- rowStyling?: GenericObject
20
+ selectableRows?: boolean
22
21
  ) => {
23
22
  // Add display name to the returned function
24
23
  const cellRenderer = ({
@@ -29,7 +28,6 @@ export const createCellFunction = (
29
28
  getValue: Getter<string>
30
29
  }) => {
31
30
  const rowData = row.original;
32
- const customStyle = rowStyling?.length > 0 && rowStyling?.find((s:GenericObject) => s?.rowId === row.id);
33
31
 
34
32
  if (isFirstColumn) {
35
33
  switch (row.depth) {
@@ -37,7 +35,6 @@ export const createCellFunction = (
37
35
  return (
38
36
  <CustomCell
39
37
  customRenderer={customRenderer}
40
- customStyle={customStyle}
41
38
  getValue={getValue}
42
39
  onRowToggleClick={onRowToggleClick}
43
40
  row={row}
@@ -57,7 +57,6 @@ export const getVirtualizedContainerStyles = (maxHeight?: string): React.CSSProp
57
57
  position: 'absolute',
58
58
  top: 0,
59
59
  left: 0,
60
- width: '100%',
61
60
  height: '40px', // Match standard table row height
62
61
  transform: `translateY(${startPosition}px)`,
63
62
  tableLayout: 'fixed',
@@ -67,12 +66,14 @@ export const getVirtualizedContainerStyles = (maxHeight?: string): React.CSSProp
67
66
  /**
68
67
  * Get height estimates for different row types
69
68
  */
70
- export const getRowHeightEstimate = (rowType: 'header' | 'row' | 'loading') => {
69
+ export const getRowHeightEstimate = (rowType: 'header' | 'row' | 'loading' | 'footer') => {
71
70
  switch (rowType) {
72
71
  case 'header':
73
72
  return 40; // Header height
74
73
  case 'loading':
75
74
  return 30; // Loading indicator height
75
+ case 'footer':
76
+ return 40
76
77
  case 'row':
77
78
  default:
78
79
  return 40; // Standard row height - match this to your design system