playbook_ui 14.15.0.pre.rc.4 → 14.15.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +127 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +55 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TablePagination.tsx +33 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +275 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +143 -3
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +66 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +195 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +45 -99
  10. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +73 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +52 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +80 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +123 -7
  14. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +153 -299
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +50 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_infinite_scroll.json +152002 -0
  17. data/app/pb_kits/playbook/pb_card/_card.tsx +2 -1
  18. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +4 -1
  19. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +2 -0
  20. data/app/pb_kits/playbook/pb_date_picker/index.ts +38 -0
  21. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +19 -3
  22. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +3 -3
  23. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +20 -37
  24. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +6 -6
  25. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +1 -0
  26. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -0
  27. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +5 -4
  28. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +2 -2
  29. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -1
  30. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +9 -2
  31. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +4 -0
  32. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.html.erb +40 -0
  33. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.jsx +50 -0
  34. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.md +3 -0
  35. data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +2 -0
  36. data/app/pb_kits/playbook/pb_form_pill/docs/index.js +1 -0
  37. data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +7 -1
  38. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +7 -0
  39. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +13 -3
  40. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +72 -0
  41. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +91 -0
  42. data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +2 -1
  43. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +1 -0
  44. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +6 -0
  45. data/app/pb_kits/playbook/pb_popover/_popover.tsx +1 -1
  46. data/app/pb_kits/playbook/pb_radio/_radio.tsx +85 -74
  47. data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.jsx +60 -0
  48. data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.md +1 -0
  49. data/app/pb_kits/playbook/pb_radio/docs/example.yml +2 -1
  50. data/app/pb_kits/playbook/pb_radio/docs/index.js +1 -0
  51. data/app/pb_kits/playbook/pb_radio/radio.test.js +16 -0
  52. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.jsx +58 -0
  53. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.md +1 -0
  54. data/app/pb_kits/playbook/pb_select/docs/example.yml +1 -0
  55. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  56. data/app/pb_kits/playbook/pb_select/select.html.erb +3 -5
  57. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +1 -5
  58. data/app/pb_kits/playbook/pb_selectable_card_icon/selectable_card_icon.html.erb +1 -4
  59. data/app/pb_kits/playbook/pb_selectable_icon/selectable_icon.html.erb +1 -5
  60. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +2 -2
  61. data/app/pb_kits/playbook/pb_title/_title.scss +32 -0
  62. data/app/pb_kits/playbook/pb_title/_title.tsx +10 -1
  63. data/app/pb_kits/playbook/pb_title/docs/_title_default.html.erb +1 -2
  64. data/app/pb_kits/playbook/pb_title/docs/_title_default.jsx +1 -1
  65. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.html.erb +7 -0
  66. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.jsx +54 -0
  67. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.md +1 -0
  68. data/app/pb_kits/playbook/pb_title/docs/example.yml +2 -0
  69. data/app/pb_kits/playbook/pb_title/docs/index.js +1 -0
  70. data/app/pb_kits/playbook/pb_title/title.rb +10 -1
  71. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +25 -0
  72. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.jsx +69 -0
  73. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.md +3 -0
  74. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -1
  75. data/app/pb_kits/playbook/pb_tooltip/docs/index.js +1 -0
  76. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +2 -1
  77. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +5 -1
  78. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +4 -1
  79. data/app/pb_kits/playbook/utilities/object.test.js +99 -0
  80. data/app/pb_kits/playbook/utilities/object.ts +29 -1
  81. data/dist/chunks/_typeahead-BhfaW1J9.js +36 -0
  82. data/dist/chunks/_weekday_stacked-CKRIELiF.js +45 -0
  83. data/dist/chunks/lazysizes-DHz07jlL.js +1 -0
  84. data/dist/chunks/{lib-Dmay5Z6U.js → lib-5OzNgeeu.js} +2 -2
  85. data/dist/chunks/{pb_form_validation-DdP7BnVX.js → pb_form_validation-DGhKbZtO.js} +1 -1
  86. data/dist/chunks/vendor.js +1 -1
  87. data/dist/playbook-doc.js +1 -1
  88. data/dist/playbook-rails-react-bindings.js +1 -1
  89. data/dist/playbook-rails.js +1 -1
  90. data/dist/playbook.css +1 -1
  91. data/lib/playbook/version.rb +1 -1
  92. metadata +34 -7
  93. data/dist/chunks/_typeahead-NXKDTf__.js +0 -36
  94. data/dist/chunks/_weekday_stacked-DtCYkCXM.js +0 -45
  95. data/dist/chunks/lazysizes-B7xYodB-.js +0 -1
@@ -31,12 +31,46 @@
31
31
  width: 100%;
32
32
  }
33
33
 
34
- .row-selection-actions-card {
35
- border-bottom-right-radius: 0px !important;
36
- border-bottom-left-radius: 0px !important;
37
- border-bottom-color: transparent;
38
- transition: height 300ms ease;
34
+ // Virtualized table styles
35
+ .virtualized-table-row {
36
+ display: table !important;
37
+ table-layout: fixed !important;
38
+ width: 100% !important;
39
+
40
+ td {
41
+ display: table-cell !important;
42
+ box-sizing: border-box !important;
43
+ white-space: nowrap;
44
+ overflow: hidden;
45
+ text-overflow: ellipsis;
39
46
  }
47
+
48
+ // Ensure the first column has proper width
49
+ td:first-child {
50
+ min-width: 180px;
51
+ }
52
+
53
+ // First column (typically the checkbox column)
54
+ td:first-child.checkbox-cell {
55
+ width: 40px !important; // Set a fixed width that matches header
56
+ min-width: 40px !important;
57
+ box-sizing: border-box !important;
58
+ text-align: center;
59
+ }
60
+
61
+ // Ensure the first data column has proper alignment with header
62
+ td:first-of-type:not(.checkbox-cell) {
63
+ min-width: 180px;
64
+ text-align: left;
65
+ }
66
+ }
67
+
68
+ .row-selection-actions-card {
69
+ border-bottom-right-radius: 0px !important;
70
+ border-bottom-left-radius: 0px !important;
71
+ border-bottom-color: transparent;
72
+ transition: height 300ms ease;
73
+ }
40
74
  .table-header-cells:first-child {
41
75
  min-width: 180px;
42
76
  }
@@ -67,6 +101,23 @@
67
101
  border-top-left-radius: 0px !important;
68
102
  border-top-right-radius: 0px !important;
69
103
  }
104
+
105
+ // Set fixed width for header cells to match table body
106
+ th {
107
+ box-sizing: border-box !important;
108
+ // Apply min-width to ensure consistent sizing
109
+ &.table-header-cells:first-child,
110
+ &.table-header-cells-custom:first-child {
111
+ min-width: 180px;
112
+ }
113
+
114
+ // Set fixed width for checkbox column
115
+ &.table-header-cells-custom {
116
+ width: 40px !important;
117
+ min-width: 40px !important;
118
+ box-sizing: border-box !important;
119
+ }
120
+ }
70
121
  }
71
122
 
72
123
  .pb_advanced_table_body {
@@ -87,6 +138,29 @@
87
138
  padding-left: 0px;
88
139
  }
89
140
  }
141
+
142
+ // Fix virtualized row borders
143
+ tr.virtualized-table-row {
144
+ border-bottom: 1px solid $border_light;
145
+
146
+ &.bg-silver {
147
+ td:first-child {
148
+ background-color: lighten($silver, $opacity_7);
149
+ }
150
+ }
151
+
152
+ &.bg-white {
153
+ td:first-child {
154
+ background-color: $white;
155
+ }
156
+ }
157
+
158
+ &.bg-row-selection {
159
+ td:first-child {
160
+ background-color: $info_subtle;
161
+ }
162
+ }
163
+ }
90
164
  }
91
165
 
92
166
  .table-header-cells-active:first-child {
@@ -129,7 +203,6 @@
129
203
  max-height: 1920px;
130
204
  overflow-y: auto;
131
205
  }
132
-
133
206
  // Icons
134
207
  .button-icon {
135
208
  display: flex;
@@ -251,6 +324,19 @@
251
324
  .bg-white td:first-child {
252
325
  background-color: $white;
253
326
  }
327
+
328
+ .virtualized-table-row {
329
+ &.bg-silver td:first-child {
330
+ background-color: lighten($silver, $opacity_7);
331
+ }
332
+ &.bg-white td:first-child {
333
+ background-color: $white;
334
+ }
335
+ &.bg-row-selection td:first-child {
336
+ background-color: $info_subtle;
337
+ }
338
+ }
339
+
254
340
  .row-selection-actions-card {
255
341
  border-right-width: 0px;
256
342
  border-left-width: 0px;
@@ -289,6 +375,25 @@
289
375
  background: $bg_dark;
290
376
  }
291
377
 
378
+ // Dark mode virtualized rows
379
+ .virtualized-table-row {
380
+ &.bg-white {
381
+ background: $bg_dark_card !important;
382
+
383
+ td:first-child {
384
+ background: $bg_dark_card !important;
385
+ }
386
+ }
387
+
388
+ &.bg-silver {
389
+ background: $bg_dark;
390
+
391
+ td:first-child {
392
+ background: $bg_dark;
393
+ }
394
+ }
395
+ }
396
+
292
397
  .table-header-cells:first-child, td:first-child, .pb_table_td:first-child {
293
398
  box-shadow: 1px 0px 0px 0px $border_dark !important;
294
399
  }
@@ -359,6 +464,17 @@
359
464
  .bg-white td:first-child {
360
465
  background-color: $bg_dark_card;
361
466
  }
467
+
468
+ // Dark mode virtualized rows
469
+ .virtualized-table-row {
470
+ &.bg-silver td:first-child {
471
+ background-color: $bg_dark;
472
+ }
473
+ &.bg-white td:first-child {
474
+ background-color: $bg_dark_card;
475
+ }
476
+ }
477
+
362
478
  .sticky-header {
363
479
  thead {
364
480
  th:first-child {
@@ -370,4 +486,4 @@
370
486
  }
371
487
  }
372
488
  }
373
- }
489
+ }
@@ -1,38 +1,23 @@
1
- import React, { useState, useEffect, useCallback, useRef } from "react"
2
- import classnames from "classnames"
1
+ import React, { useRef, useEffect } from "react";
2
+ import classnames from "classnames";
3
3
 
4
- import { GenericObject } from "../types"
4
+ import { GenericObject } from "../types";
5
+ import { Row, RowSelectionState } from "@tanstack/react-table";
5
6
 
6
- import {
7
- createColumnHelper,
8
- getCoreRowModel,
9
- getExpandedRowModel,
10
- getPaginationRowModel,
11
- getSortedRowModel,
12
- Row,
13
- useReactTable,
14
- Getter,
15
- RowSelectionState
16
- } from "@tanstack/react-table"
7
+ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
8
+ import { globalProps, GlobalProps } from "../utilities/globalProps";
17
9
 
18
- import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props"
19
- import { globalProps, GlobalProps } from "../utilities/globalProps"
10
+ import Table from "../pb_table/_table";
11
+ import { AdvancedTableProvider } from "./Context/AdvancedTableContext";
12
+ import { getVirtualizedContainerStyles } from "./Utilities/TableContainerStyles";
20
13
 
21
- import Table from "../pb_table/_table"
22
- import Card from "../pb_card/_card"
23
- import Caption from "../pb_caption/_caption"
24
- import Flex from "../pb_flex/_flex"
25
- import FlexItem from "../pb_flex/_flex_item"
14
+ import { TableHeader } from "./SubKits/TableHeader";
15
+ import { TableBody } from "./SubKits/TableBody";
16
+ import TablePagination from "./Components/TablePagination";
17
+ import TableActionBar from "./Components/TableActionBar";
26
18
 
27
- import AdvancedTableContext from "./Context/AdvancedTableContext"
28
-
29
- import { updateExpandAndCollapseState } from "./Utilities/ExpansionControlHelpers"
30
- import { showActionBar, hideActionBar } from "./Utilities/ActionBarAnimationHelper"
31
-
32
- import { CustomCell } from "./Components/CustomCell"
33
- import { TableHeader } from "./SubKits/TableHeader"
34
- import { TableBody } from "./SubKits/TableBody"
35
- import Pagination from "../pb_pagination/_pagination"
19
+ import { useTableState } from "./Hooks/useTableState";
20
+ import { useTableActions } from "./Hooks/useTableActions";
36
21
 
37
22
  type AdvancedTableProps = {
38
23
  aria?: { [key: string]: string }
@@ -63,7 +48,8 @@ type AdvancedTableProps = {
63
48
  tableProps?: GenericObject
64
49
  toggleExpansionIcon?: string | string[]
65
50
  onRowSelectionChange?: (arg: RowSelectionState) => void
66
- } & GlobalProps
51
+ virtualizedRows?: boolean
52
+ } & GlobalProps;
67
53
 
68
54
  const AdvancedTable = (props: AdvancedTableProps) => {
69
55
  const {
@@ -95,282 +81,149 @@ const AdvancedTable = (props: AdvancedTableProps) => {
95
81
  tableProps,
96
82
  toggleExpansionIcon = "arrows-from-line",
97
83
  onRowSelectionChange,
98
- } = props
99
-
100
- const [loadingStateRowCount, setLoadingStateRowCount] = useState(
101
- initialLoadingRowsCount
102
- )
103
-
104
- // Create a local state for expanded and setExpanded if expandedControl not used
105
- const [localExpanded, setLocalExpanded] = useState({})
106
-
107
- // Determine whether to use the prop or the local state
108
- const expanded = expandedControl ? expandedControl.value : localExpanded
109
- const setExpanded = expandedControl
110
- ? expandedControl.onChange
111
- : setLocalExpanded
112
-
113
- const columnHelper = createColumnHelper()
114
-
115
- //Row Selection
116
- const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
117
-
118
- //Create cells for columns, with customization for first column
119
- const createCellFunction = (cellAccessors: string[], customRenderer?: (row: Row<GenericObject>, value: any) => JSX.Element, isFirstColumn?: boolean) => {
120
- const columnCells = ({
121
- row,
122
- getValue,
123
- }: {
124
- row: Row<GenericObject>
125
- getValue: Getter<string>
126
- }) => {
127
- const rowData = row.original
128
-
129
- if (isFirstColumn) {
130
- switch (row.depth) {
131
- case 0: {
132
- return (
133
- <CustomCell
134
- customRenderer={customRenderer}
135
- getValue={getValue}
136
- onRowToggleClick={onRowToggleClick}
137
- row={row}
138
- selectableRows={selectableRows}
139
- />
140
- )
141
- }
142
- default: {
143
- // Handle other depths based on cellAccessors
144
- const depthAccessor = cellAccessors[row.depth - 1] // Adjust index for depth
145
- const accessorValue = rowData[depthAccessor]
146
- return accessorValue ? (
147
- <CustomCell
148
- customRenderer={customRenderer}
149
- onRowToggleClick={onRowToggleClick}
150
- row={row}
151
- selectableRows={selectableRows}
152
- value={accessorValue}
153
- />
154
- ) : (
155
- "N/A"
156
- )
157
- }
158
- }
159
- }
160
- return customRenderer
161
- ? customRenderer(row, getValue())
162
- : getValue()
163
- }
164
- return columnCells
165
- }
84
+ virtualizedRows = false,
85
+ } = props;
166
86
 
167
- const buildColumns = (columnDefinitions: GenericObject[], isRoot= true): any => {
168
- return (
169
- columnDefinitions &&
170
- columnDefinitions.map((column, index) => {
171
- const isFirstColumn = isRoot && index === 0;
172
- //Checking to see if grouped column or not
173
- if (column.columns && column.columns.length > 0) {
174
- return {
175
- header: column.label || "",
176
- columns: buildColumns(column.columns, false),
177
- };
178
- } else {
179
- // Define the base column structure
180
- const columnStructure = {
181
- ...columnHelper.accessor(column.accessor, {
182
- header: column.label || "",
183
- }),
184
- };
87
+ // Component refs
88
+ const tableWrapperRef = useRef<HTMLDivElement>(null);
185
89
 
186
- if (column.cellAccessors || column.customRenderer) {
187
- columnStructure.cell = createCellFunction(
188
- column.cellAccessors,
189
- column.customRenderer,
190
- isFirstColumn
191
- );
192
- }
193
-
194
- return columnStructure;
195
- }
196
- })
197
- );
198
- };
199
-
200
- //Create column array in format needed by Tanstack
201
- const columns = buildColumns(columnDefinitions);
202
-
203
- //Syntax for sorting Array if we want to manage state ourselves
204
- const sorting = [
205
- {
206
- id: columnDefinitions[0].accessor,
207
- desc:
208
- sortControl && sortControl.value !== null
209
- ? !sortControl.value.desc
210
- : false,
211
- },
212
- ]
213
-
214
- const customState = () => {
215
- if (sortControl && selectableRows) {
216
- return { state: { expanded, sorting, rowSelection } }
217
- } else if (sortControl) {
218
- return { state: { expanded, sorting } }
219
- } else if (selectableRows) {
220
- return { state: { expanded, rowSelection } }
221
- } else {
222
- return { state: { expanded } }
223
- }
224
- }
225
-
226
- const paginationInitializer = pagination ? {
227
- getPaginationRowModel: getPaginationRowModel(),
228
- paginateExpandedRows: false,
229
- initialState: {
230
- pagination: {
231
- pageIndex: paginationProps?.pageIndex ?? 0,
232
- pageSize: paginationProps?.pageSize ?? 20,
233
- },
234
- },
235
- } : {}
236
-
237
- //initialize table
238
- const table = useReactTable({
239
- data: loading ? Array(loadingStateRowCount).fill({}) : tableData,
240
- columns,
241
- onExpandedChange: setExpanded,
242
- getSubRows: (row: GenericObject) => row.children,
243
- getCoreRowModel: getCoreRowModel(),
244
- getExpandedRowModel: getExpandedRowModel(),
245
- getSortedRowModel: getSortedRowModel(),
246
- enableSortingRemoval: false,
247
- sortDescFirst: true,
248
- onRowSelectionChange: setRowSelection,
249
- getRowId: selectableRows ? row => row.id : undefined,
250
- ...customState(),
251
- ...paginationInitializer,
252
- ...tableOptions,
253
- })
254
-
255
- const tableRows = table.getRowModel()
256
-
257
- const hasAnySubRows = tableRows.rows.some(row => row.subRows && row.subRows.length > 0);
258
- const selectedRowsLength = Object.keys(table.getState().rowSelection).length
90
+ // Initialize table state
91
+ const {
92
+ table,
93
+ expanded,
94
+ setExpanded,
95
+ hasAnySubRows,
96
+ selectedRowsLength,
97
+ fetchNextPage,
98
+ updateLoadingStateRowCount,
99
+ fullData,
100
+ totalFetched,
101
+ isFetching
102
+ } = useTableState({
103
+ tableData,
104
+ columnDefinitions,
105
+ expandedControl,
106
+ sortControl,
107
+ onRowToggleClick,
108
+ selectableRows,
109
+ initialLoadingRowsCount,
110
+ loading,
111
+ pagination,
112
+ paginationProps,
113
+ virtualizedRows,
114
+ tableOptions,
115
+ onRowSelectionChange
116
+ });
259
117
 
260
- useEffect(() => {
261
- if (onRowSelectionChange) {
262
- onRowSelectionChange(table.getState().rowSelection)
263
- }
264
- } , [table.getState().rowSelection, onRowSelectionChange])
118
+ // Initialize table actions
119
+ const {
120
+ handleExpandOrCollapse,
121
+ onPageChange,
122
+ fetchMoreOnBottomReached
123
+ } = useTableActions({
124
+ table,
125
+ expanded,
126
+ setExpanded,
127
+ onToggleExpansionClick,
128
+ onRowSelectionChange
129
+ });
265
130
 
266
131
  // Set table row count for loading state
267
- const updateLoadingStateRowCount = useCallback(() => {
268
- const rowsCount = table.getRowModel().rows.length
269
- if (rowsCount !== loadingStateRowCount && rowsCount !== 0) {
270
- setLoadingStateRowCount(rowsCount)
271
- }
272
- }, [tableData, loadingStateRowCount])
273
-
274
132
  useEffect(() => {
275
133
  if (!loading) {
276
- updateLoadingStateRowCount()
134
+ updateLoadingStateRowCount();
277
135
  }
278
- }, [loading, updateLoadingStateRowCount])
136
+ }, [loading, updateLoadingStateRowCount]);
279
137
 
280
- const handleExpandOrCollapse = async (row: Row<GenericObject>) => {
281
- onToggleExpansionClick && onToggleExpansionClick(row)
282
-
283
- const expandedState = expanded;
284
- const targetParent = row?.parentId;
285
- const updatedRows = await updateExpandAndCollapseState(tableRows, expandedState, targetParent)
286
- setExpanded(updatedRows)
287
- }
138
+ // Check for infinite scroll
139
+ useEffect(() => {
140
+ fetchMoreOnBottomReached(
141
+ tableWrapperRef.current,
142
+ fetchNextPage,
143
+ isFetching,
144
+ totalFetched,
145
+ fullData.length
146
+ );
147
+ }, [fetchMoreOnBottomReached, fetchNextPage, isFetching, totalFetched, fullData.length]);
288
148
 
289
- const ariaProps = buildAriaProps(aria)
290
- const dataProps = buildDataProps(data)
291
- const htmlProps = buildHtmlProps(htmlOptions)
149
+ // Build CSS classes and props
150
+ const ariaProps = buildAriaProps(aria);
151
+ const dataProps = buildDataProps(data);
152
+ const htmlProps = buildHtmlProps(htmlOptions);
292
153
  const classes = classnames(
293
154
  buildCss("pb_advanced_table"),
294
155
  `advanced-table-responsive-${responsive}`,
295
- maxHeight ? `advanced-table-max-height-${maxHeight}` : '', // max height as kit prop not global prop to control overflow-y
156
+ maxHeight ? `advanced-table-max-height-${maxHeight}` : '',
296
157
  globalProps(props),
297
158
  className
298
- )
159
+ );
299
160
 
300
- const onPageChange = (page: number) => {
301
- table.setPageIndex(page - 1)
302
- }
303
- //When to show the actions bar as a whole
304
- const isActionBarVisible = selectableRows && showActionsBar && selectedRowsLength > 0
161
+ // Table wrapper styling with virtualization support
162
+ const tableWrapperStyle = virtualizedRows
163
+ ? getVirtualizedContainerStyles(maxHeight)
164
+ : {};
305
165
 
306
- //Ref and useEffect for animating the actions bar
307
- const cardRef = useRef(null);
308
- useEffect(() => {
309
- if (cardRef.current) {
310
- if (isActionBarVisible) {
311
- showActionBar(cardRef.current);
312
- } else {
313
- hideActionBar(cardRef.current);
314
- }
315
- }
316
- }, [isActionBarVisible]);
166
+ // Visibility flag for action bar
167
+ const isActionBarVisible = selectableRows && showActionsBar && selectedRowsLength > 0;
317
168
 
318
169
  return (
319
- <div {...ariaProps}
320
- {...dataProps}
170
+ <div
171
+ {...ariaProps}
172
+ {...dataProps}
321
173
  {...htmlProps}
322
- className={classes}
174
+ className={classes}
323
175
  id={id}
176
+ onScroll={virtualizedRows ? e => fetchMoreOnBottomReached(
177
+ e.currentTarget,
178
+ fetchNextPage,
179
+ isFetching,
180
+ totalFetched,
181
+ fullData.length
182
+ ) : undefined}
183
+ ref={tableWrapperRef}
184
+ style={tableWrapperStyle as React.CSSProperties}
324
185
  >
325
- <AdvancedTableContext.Provider
326
- value={{
327
- columnDefinitions,
328
- enableToggleExpansion,
329
- expanded,
330
- expandedControl,
331
- handleExpandOrCollapse,
332
- inlineRowLoading,
333
- isActionBarVisible,
334
- loading,
335
- responsive,
336
- setExpanded,
337
- sortControl,
338
- table,
339
- toggleExpansionIcon,
340
- showActionsBar,
341
- selectableRows,
342
- hasAnySubRows
343
- }}
186
+ <AdvancedTableProvider
187
+ columnDefinitions={columnDefinitions}
188
+ enableToggleExpansion={enableToggleExpansion}
189
+ enableVirtualization={virtualizedRows}
190
+ expanded={expanded}
191
+ expandedControl={expandedControl}
192
+ handleExpandOrCollapse={handleExpandOrCollapse}
193
+ hasAnySubRows={hasAnySubRows}
194
+ inlineRowLoading={inlineRowLoading}
195
+ isActionBarVisible={isActionBarVisible}
196
+ loading={loading}
197
+ responsive={responsive}
198
+ selectableRows={selectableRows}
199
+ setExpanded={setExpanded}
200
+ showActionsBar={showActionsBar}
201
+ sortControl={sortControl}
202
+ subRowHeaders={tableOptions?.subRowHeaders}
203
+ table={table}
204
+ tableContainerRef={tableWrapperRef}
205
+ toggleExpansionIcon={toggleExpansionIcon}
206
+ virtualizedRows={virtualizedRows}
344
207
  >
345
- <>
346
- {pagination &&
347
- <Pagination
348
- current={table.getState().pagination.pageIndex + 1}
349
- key={`pagination-top-${table.getState().pagination.pageIndex + 1}`}
350
- marginBottom="xs"
351
- onChange={onPageChange}
352
- range={paginationProps?.range ? paginationProps?.range : 5}
353
- total={table.getPageCount()}
354
- />
355
- }
356
- <Card
357
- borderNone={!isActionBarVisible}
358
- className={`${isActionBarVisible && "show-action-card row-selection-actions-card"}`}
359
- htmlOptions={{ ref: cardRef as any }}
360
- padding={`${isActionBarVisible ? "xs" : "none"}`}
361
- >
362
- <Flex alignItems="center"
363
- justify="between"
364
- >
365
- <Caption color="light"
366
- paddingLeft="xs"
367
- size="xs"
368
- >
369
- {selectedRowsLength} Selected
370
- </Caption>
371
- <FlexItem>{actions}</FlexItem>
372
- </Flex>
373
- </Card>
208
+ <React.Fragment>
209
+ {/* Top Pagination */}
210
+ {pagination && (
211
+ <TablePagination
212
+ onChange={onPageChange}
213
+ position="top"
214
+ range={paginationProps?.range}
215
+ table={table}
216
+ />
217
+ )}
218
+
219
+ {/* Selection Action Bar */}
220
+ <TableActionBar
221
+ actions={actions}
222
+ isVisible={isActionBarVisible}
223
+ selectedCount={selectedRowsLength}
224
+ />
225
+
226
+ {/* Main Table */}
374
227
  <Table
375
228
  className={`${loading ? "content-loading" : ""}`}
376
229
  dark={dark}
@@ -388,23 +241,24 @@ const AdvancedTable = (props: AdvancedTableProps) => {
388
241
  </>
389
242
  )}
390
243
  </Table>
391
- {pagination &&
392
- <Pagination
393
- current={table.getState().pagination.pageIndex + 1}
394
- key={`pagination-bottom-${table.getState().pagination.pageIndex + 1}`}
395
- marginTop="xs"
244
+
245
+ {/* Bottom Pagination */}
246
+ {pagination && (
247
+ <TablePagination
396
248
  onChange={onPageChange}
397
- range={paginationProps?.range ? paginationProps?.range : 5}
398
- total={table.getPageCount()}
249
+ position="bottom"
250
+ range={paginationProps?.range}
251
+ table={table}
399
252
  />
400
- }
401
- </>
402
- </AdvancedTableContext.Provider>
253
+ )}
254
+ </React.Fragment>
255
+ </AdvancedTableProvider>
403
256
  </div>
404
- )
405
- }
257
+ );
258
+ };
406
259
 
407
- AdvancedTable.Header = TableHeader
408
- AdvancedTable.Body = TableBody
260
+ // Re-export sub-components
261
+ AdvancedTable.Header = TableHeader;
262
+ AdvancedTable.Body = TableBody;
409
263
 
410
- export default AdvancedTable
264
+ export default AdvancedTable;