playbook_ui 14.15.0.pre.alpha.play1917lodashremoval2of36615 → 14.15.0.pre.rc.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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +3 -143
- data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +99 -45
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +7 -123
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +299 -153
- data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +1 -1
- data/app/pb_kits/playbook/pb_card/_card.tsx +1 -2
- data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +1 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -4
- data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +0 -2
- data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +6 -5
- data/app/pb_kits/playbook/pb_dialog/dialogHelper.js +0 -2
- data/app/pb_kits/playbook/pb_drawer/_drawer.scss +3 -43
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +3 -3
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +37 -20
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.html.erb +1 -20
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +6 -6
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +0 -1
- data/app/pb_kits/playbook/pb_drawer/docs/example.yml +0 -6
- data/app/pb_kits/playbook/pb_drawer/drawer.html.erb +12 -20
- data/app/pb_kits/playbook/pb_drawer/drawer.rb +1 -49
- data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +4 -5
- data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +2 -2
- data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.tsx +1 -2
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +2 -2
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +2 -9
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +0 -4
- data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_form_pill/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +1 -7
- data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +1 -1
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Slide.tsx +1 -1
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Slides.tsx +1 -1
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnails.tsx +1 -1
- data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +0 -7
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +3 -13
- data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +1 -2
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +0 -6
- data/app/pb_kits/playbook/pb_overlay/_overlay.scss +0 -13
- data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +1 -7
- data/app/pb_kits/playbook/pb_overlay/docs/example.yml +0 -3
- data/app/pb_kits/playbook/pb_overlay/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_overlay/overlay.html.erb +3 -5
- data/app/pb_kits/playbook/pb_overlay/overlay.rb +1 -16
- data/app/pb_kits/playbook/pb_overlay/overlay.test.jsx +0 -12
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +2 -2
- data/app/pb_kits/playbook/pb_popover/popover.test.js +1 -1
- data/app/pb_kits/playbook/pb_radio/_radio.tsx +74 -85
- data/app/pb_kits/playbook/pb_radio/docs/example.yml +1 -2
- data/app/pb_kits/playbook/pb_radio/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_radio/radio.test.js +0 -16
- data/app/pb_kits/playbook/pb_select/docs/example.yml +0 -1
- data/app/pb_kits/playbook/pb_select/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_select/select.html.erb +5 -3
- data/app/pb_kits/playbook/pb_select/select.rb +0 -8
- data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +5 -1
- data/app/pb_kits/playbook/pb_selectable_card_icon/selectable_card_icon.html.erb +4 -1
- data/app/pb_kits/playbook/pb_selectable_icon/selectable_icon.html.erb +5 -1
- data/app/pb_kits/playbook/pb_text_input/inputMask.ts +3 -2
- data/app/pb_kits/playbook/pb_timeline/_timeline.scss +2 -2
- data/app/pb_kits/playbook/pb_title/_title.scss +0 -32
- data/app/pb_kits/playbook/pb_title/_title.tsx +1 -10
- data/app/pb_kits/playbook/pb_title/docs/_title_default.html.erb +2 -1
- data/app/pb_kits/playbook/pb_title/docs/_title_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_title/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_title/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_title/title.rb +1 -10
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +3 -0
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +0 -25
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_icon.erb +10 -0
- data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -4
- data/app/pb_kits/playbook/pb_tooltip/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_tooltip/index.js +1 -1
- data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +2 -10
- data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +1 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +5 -51
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +1 -5
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills_async_custom_options.jsx +1 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills_async_users.jsx +1 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +0 -3
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_typeahead/index.ts +8 -61
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +2 -17
- data/app/pb_kits/playbook/utilities/object.ts +1 -103
- data/app/pb_kits/playbook/utilities/text.ts +1 -1
- data/dist/chunks/_typeahead-PqkcDf1H.js +36 -0
- data/dist/chunks/_weekday_stacked-BrSrpj7J.js +45 -0
- data/dist/chunks/{lib-e7oBFFDo.js → lib-D3us1bGD.js} +2 -2
- data/dist/chunks/{pb_form_validation-CMXevI1t.js → pb_form_validation-BpihMSOQ.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +2 -2
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +2 -2
- metadata +7 -61
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +0 -127
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +0 -55
- data/app/pb_kits/playbook/pb_advanced_table/Components/TablePagination.tsx +0 -33
- data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +0 -275
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +0 -66
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +0 -195
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +0 -73
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +0 -52
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +0 -80
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +0 -50
- data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_infinite_scroll.json +0 -152002
- data/app/pb_kits/playbook/pb_date_picker/index.ts +0 -38
- data/app/pb_kits/playbook/pb_dialog/index.js +0 -75
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.html.erb +0 -8
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.html.erb +0 -33
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.html.erb +0 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.html.erb +0 -24
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.html.erb +0 -21
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.md +0 -1
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.html.erb +0 -49
- data/app/pb_kits/playbook/pb_drawer/index.js +0 -257
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.html.erb +0 -40
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.jsx +0 -50
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.md +0 -3
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +0 -72
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +0 -91
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.html.erb +0 -11
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.jsx +0 -37
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_rails.md +0 -1
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_react.md +0 -1
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.html.erb +0 -11
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.md +0 -1
- data/app/pb_kits/playbook/pb_overlay/index.js +0 -61
- data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.jsx +0 -60
- data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.md +0 -1
- data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.jsx +0 -58
- data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.md +0 -1
- data/app/pb_kits/playbook/pb_select/index.js +0 -38
- data/app/pb_kits/playbook/pb_title/docs/_title_display_size.html.erb +0 -7
- data/app/pb_kits/playbook/pb_title/docs/_title_display_size.jsx +0 -54
- data/app/pb_kits/playbook/pb_title/docs/_title_display_size.md +0 -1
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.html.erb +0 -39
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.md +0 -3
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_icon_rails.html.erb +0 -22
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_interaction.html.erb +0 -26
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.jsx +0 -69
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.md +0 -3
- data/app/pb_kits/playbook/pb_tooltip/floating_ui.js +0 -282
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options.html.erb +0 -45
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options.md +0 -5
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options_pure_rails.html.erb +0 -33
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options_pure_rails.md +0 -3
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.jsx +0 -66
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.md +0 -1
- data/app/pb_kits/playbook/utilities/object.test.js +0 -237
- data/dist/chunks/_typeahead-CdVbIURO.js +0 -36
- data/dist/chunks/_weekday_stacked-BSTKfYPJ.js +0 -45
@@ -1,275 +0,0 @@
|
|
1
|
-
import React, { useContext, useLayoutEffect, useState, useEffect } from "react"
|
2
|
-
import classnames from "classnames"
|
3
|
-
import { flexRender, Cell } from "@tanstack/react-table"
|
4
|
-
import { VirtualItem } from "@tanstack/react-virtual"
|
5
|
-
|
6
|
-
import { GenericObject } from "../../types"
|
7
|
-
|
8
|
-
import { isChrome } from "../Utilities/BrowserCheck"
|
9
|
-
import { getVirtualizedRowStyle } from "../Utilities/TableContainerStyles"
|
10
|
-
|
11
|
-
import LoadingInline from "../../pb_loading_inline/_loading_inline"
|
12
|
-
import Checkbox from "../../pb_checkbox/_checkbox"
|
13
|
-
|
14
|
-
import { SubRowHeaderRow } from "../Components/SubRowHeaderRow"
|
15
|
-
import { LoadingCell } from "../Components/LoadingCell"
|
16
|
-
import { renderCollapsibleTrail } from "../Components/CollapsibleTrail"
|
17
|
-
|
18
|
-
import AdvancedTableContext from "../Context/AdvancedTableContext"
|
19
|
-
|
20
|
-
type VirtualizedTableViewProps = {
|
21
|
-
collapsibleTrail?: boolean
|
22
|
-
subRowHeaders?: string[]
|
23
|
-
}
|
24
|
-
|
25
|
-
export const VirtualizedTableView = ({
|
26
|
-
collapsibleTrail = true,
|
27
|
-
subRowHeaders,
|
28
|
-
}: VirtualizedTableViewProps) => {
|
29
|
-
const {
|
30
|
-
enableToggleExpansion,
|
31
|
-
handleExpandOrCollapse,
|
32
|
-
inlineRowLoading,
|
33
|
-
loading,
|
34
|
-
table,
|
35
|
-
selectableRows,
|
36
|
-
hasAnySubRows,
|
37
|
-
virtualizer,
|
38
|
-
flattenedItems,
|
39
|
-
} = useContext(AdvancedTableContext)
|
40
|
-
|
41
|
-
const columnPinning = table.getState().columnPinning || { left: [] };
|
42
|
-
const sortingState = JSON.stringify(table.getState().sorting || []);
|
43
|
-
|
44
|
-
// Store column widths extracted from header
|
45
|
-
const [columnWidths, setColumnWidths] = useState<{[key: string]: string}>({});
|
46
|
-
|
47
|
-
// Function to get header cell widths
|
48
|
-
const getHeaderCellWidths = () => {
|
49
|
-
const widths: {[key: string]: string} = {};
|
50
|
-
|
51
|
-
// Get all header cells
|
52
|
-
const headerCells = document.querySelectorAll('.table-header-cells, .table-header-cells-custom');
|
53
|
-
|
54
|
-
// If checkbox is present in header
|
55
|
-
if (selectableRows && !hasAnySubRows && headerCells.length > 0) {
|
56
|
-
widths['checkbox'] = `${headerCells[0].getBoundingClientRect().width}px`;
|
57
|
-
}
|
58
|
-
|
59
|
-
// Process regular header cells
|
60
|
-
table.getFlatHeaders().forEach((header: any, index: number) => {
|
61
|
-
// Adjust index if checkbox column exists
|
62
|
-
const headerIndex = (selectableRows && !hasAnySubRows) ? index + 1 : index;
|
63
|
-
|
64
|
-
if (headerCells[headerIndex]) {
|
65
|
-
const width = headerCells[headerIndex].getBoundingClientRect().width;
|
66
|
-
widths[header.id] = `${width}px`;
|
67
|
-
}
|
68
|
-
});
|
69
|
-
|
70
|
-
return widths;
|
71
|
-
};
|
72
|
-
|
73
|
-
// Debounce function to prevent too many updates during resize
|
74
|
-
const debounce = <T extends (...args: any[]) => any>(func: T, wait: number): ((...args: Parameters<T>) => void) => {
|
75
|
-
let timeout: ReturnType<typeof setTimeout>;
|
76
|
-
return function executedFunction(...args: Parameters<T>) {
|
77
|
-
const later = () => {
|
78
|
-
clearTimeout(timeout);
|
79
|
-
func(...args);
|
80
|
-
};
|
81
|
-
clearTimeout(timeout);
|
82
|
-
timeout = setTimeout(later, wait);
|
83
|
-
};
|
84
|
-
};
|
85
|
-
|
86
|
-
// Update column widths when component mounts and when sorting changes
|
87
|
-
useLayoutEffect(() => {
|
88
|
-
// Apply widths after a small delay to ensure header is rendered
|
89
|
-
const timer = setTimeout(() => {
|
90
|
-
setColumnWidths(getHeaderCellWidths());
|
91
|
-
}, 0);
|
92
|
-
|
93
|
-
return () => clearTimeout(timer);
|
94
|
-
}, [table, selectableRows, hasAnySubRows, sortingState]);
|
95
|
-
|
96
|
-
// Add window resize listener to update widths on window resize
|
97
|
-
useEffect(() => {
|
98
|
-
// Create debounced version of the width measurement function
|
99
|
-
const handleResize = debounce(() => {
|
100
|
-
setColumnWidths(getHeaderCellWidths());
|
101
|
-
}, 0);
|
102
|
-
|
103
|
-
// Add the event listener
|
104
|
-
window.addEventListener('resize', handleResize);
|
105
|
-
|
106
|
-
// Cleanup
|
107
|
-
return () => {
|
108
|
-
window.removeEventListener('resize', handleResize);
|
109
|
-
};
|
110
|
-
}, [table, selectableRows, hasAnySubRows]);
|
111
|
-
|
112
|
-
// Safety check
|
113
|
-
if (!virtualizer || !flattenedItems) {
|
114
|
-
return (
|
115
|
-
<tr>
|
116
|
-
<td colSpan={table.getAllFlatColumns().length || 1}>
|
117
|
-
No data to display.
|
118
|
-
</td>
|
119
|
-
</tr>
|
120
|
-
);
|
121
|
-
}
|
122
|
-
|
123
|
-
// 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
|
-
|
137
|
-
if (!virtualItems.length) {
|
138
|
-
return (
|
139
|
-
<tr>
|
140
|
-
<td colSpan={table.getAllFlatColumns().length || 1}>
|
141
|
-
No items to display.
|
142
|
-
</td>
|
143
|
-
</tr>
|
144
|
-
);
|
145
|
-
}
|
146
|
-
|
147
|
-
return (
|
148
|
-
<>
|
149
|
-
{virtualItems.map((virtualRow: VirtualItem) => {
|
150
|
-
const item = flattenedItems[virtualRow.index];
|
151
|
-
if (!item) return null;
|
152
|
-
|
153
|
-
// Use consistent row styling
|
154
|
-
const virtualItemStyle = getVirtualizedRowStyle(virtualRow.start);
|
155
|
-
|
156
|
-
if (item.type === 'header') {
|
157
|
-
return (
|
158
|
-
<tr
|
159
|
-
className="virtualized-table-row virtualized-header-row"
|
160
|
-
key={`header-${item.id}-sort-${sortingState}`}
|
161
|
-
style={virtualItemStyle}
|
162
|
-
>
|
163
|
-
<td colSpan={table.getAllFlatColumns().length}>
|
164
|
-
<SubRowHeaderRow
|
165
|
-
collapsibleTrail={collapsibleTrail}
|
166
|
-
enableToggleExpansion={enableToggleExpansion}
|
167
|
-
onClick={handleExpandOrCollapse}
|
168
|
-
row={item.row}
|
169
|
-
subRowHeaders={subRowHeaders}
|
170
|
-
table={table}
|
171
|
-
/>
|
172
|
-
</td>
|
173
|
-
</tr>
|
174
|
-
);
|
175
|
-
}
|
176
|
-
|
177
|
-
if (item.type === 'row') {
|
178
|
-
const row = item.row;
|
179
|
-
const isExpandable = row.getIsExpanded();
|
180
|
-
const rowHasNoChildren = row.original?.children && !row.original.children.length ? true : false;
|
181
|
-
const rowBackground = isExpandable && ((!inlineRowLoading && row.getCanExpand()) || (inlineRowLoading && rowHasNoChildren));
|
182
|
-
const rowColor = row.getIsSelected() ? "bg-row-selection" : rowBackground ? "bg-silver" : "bg-white";
|
183
|
-
|
184
|
-
return (
|
185
|
-
<tr
|
186
|
-
className={`virtualized-table-row ${rowColor} ${row.depth > 0 ? `depth-sub-row-${row.depth}` : ""}`}
|
187
|
-
data-index={virtualRow.index}
|
188
|
-
key={`row-${item.id}-sort-${sortingState}`}
|
189
|
-
ref={(node) => {
|
190
|
-
if (node) {
|
191
|
-
try {
|
192
|
-
virtualizer.measureElement(node);
|
193
|
-
} catch (err) {
|
194
|
-
// Silent error handling
|
195
|
-
}
|
196
|
-
}
|
197
|
-
}}
|
198
|
-
style={virtualItemStyle}
|
199
|
-
>
|
200
|
-
{/* Render custom checkbox column when we want selectableRows for non-expanding tables */}
|
201
|
-
{selectableRows && !hasAnySubRows && (
|
202
|
-
<td
|
203
|
-
className="checkbox-cell"
|
204
|
-
style={{ width: columnWidths['checkbox'] || 'auto' }}
|
205
|
-
>
|
206
|
-
<Checkbox
|
207
|
-
checked={row.getIsSelected()}
|
208
|
-
disabled={!row.getCanSelect()}
|
209
|
-
indeterminate={row.getIsSomeSelected()}
|
210
|
-
name={row.id}
|
211
|
-
onChange={row.getToggleSelectedHandler()}
|
212
|
-
/>
|
213
|
-
</td>
|
214
|
-
)}
|
215
|
-
|
216
|
-
{row.getVisibleCells().map((cell: Cell<GenericObject, unknown>, i: number) => {
|
217
|
-
const isPinnedLeft = columnPinning.left.includes(cell.column.id);
|
218
|
-
const isLastCell = cell.column.parent?.columns?.at(-1)?.id === cell.column.id;
|
219
|
-
const cellWidth = columnWidths[cell.column.id] || 'auto';
|
220
|
-
|
221
|
-
return (
|
222
|
-
<td
|
223
|
-
align="right"
|
224
|
-
className={classnames(
|
225
|
-
`${cell.id}-cell position_relative`,
|
226
|
-
isChrome() ? "chrome-styles" : "",
|
227
|
-
isPinnedLeft && 'pinned-left',
|
228
|
-
isLastCell && 'last-cell',
|
229
|
-
)}
|
230
|
-
key={`${cell.id}-data`}
|
231
|
-
style={{ width: cellWidth }}
|
232
|
-
>
|
233
|
-
{collapsibleTrail && i === 0 && row.depth > 0 && renderCollapsibleTrail(row.depth)}
|
234
|
-
<span id={`${cell.id}-span`}>
|
235
|
-
{loading ? (
|
236
|
-
<LoadingCell />
|
237
|
-
) : (
|
238
|
-
flexRender(cell.column.columnDef.cell, cell.getContext())
|
239
|
-
)}
|
240
|
-
</span>
|
241
|
-
</td>
|
242
|
-
);
|
243
|
-
})}
|
244
|
-
</tr>
|
245
|
-
);
|
246
|
-
}
|
247
|
-
|
248
|
-
if (item.type === 'loading') {
|
249
|
-
// Render loading indicator
|
250
|
-
const row = item.row;
|
251
|
-
const numberOfColumns = table.getAllFlatColumns().length;
|
252
|
-
|
253
|
-
return (
|
254
|
-
<tr
|
255
|
-
className="virtualized-table-row virtualized-loading-row"
|
256
|
-
key={`loading-${item.id}-sort-${sortingState}`}
|
257
|
-
style={virtualItemStyle}
|
258
|
-
>
|
259
|
-
<td
|
260
|
-
colSpan={numberOfColumns}
|
261
|
-
style={{ paddingLeft: `${row.depth === 0 ? 0.5 : (row.depth * 2)}em` }}
|
262
|
-
>
|
263
|
-
<LoadingInline />
|
264
|
-
</td>
|
265
|
-
</tr>
|
266
|
-
);
|
267
|
-
}
|
268
|
-
|
269
|
-
return null;
|
270
|
-
})}
|
271
|
-
</>
|
272
|
-
);
|
273
|
-
}
|
274
|
-
|
275
|
-
export default VirtualizedTableView;
|
@@ -1,66 +0,0 @@
|
|
1
|
-
import { useCallback, useEffect } from 'react';
|
2
|
-
import { Row } from "@tanstack/react-table";
|
3
|
-
import { GenericObject } from "../../types";
|
4
|
-
import { updateExpandAndCollapseState } from "../Utilities/ExpansionControlHelpers";
|
5
|
-
|
6
|
-
interface UseTableActionsProps {
|
7
|
-
table: any;
|
8
|
-
expanded: GenericObject;
|
9
|
-
setExpanded: (expanded: GenericObject) => void;
|
10
|
-
onToggleExpansionClick?: (arg: Row<GenericObject>) => void;
|
11
|
-
onRowSelectionChange?: (rowSelection: any) => void;
|
12
|
-
}
|
13
|
-
|
14
|
-
export function useTableActions({
|
15
|
-
table,
|
16
|
-
expanded,
|
17
|
-
setExpanded,
|
18
|
-
onToggleExpansionClick,
|
19
|
-
onRowSelectionChange
|
20
|
-
}: UseTableActionsProps) {
|
21
|
-
|
22
|
-
// Handle expand/collapse
|
23
|
-
const handleExpandOrCollapse = useCallback(async (row: Row<GenericObject>) => {
|
24
|
-
onToggleExpansionClick && onToggleExpansionClick(row);
|
25
|
-
|
26
|
-
const expandedState = expanded;
|
27
|
-
const targetParent = row?.parentId;
|
28
|
-
const updatedRows = await updateExpandAndCollapseState(table.getRowModel(), expandedState, targetParent);
|
29
|
-
setExpanded(updatedRows);
|
30
|
-
}, [expanded, setExpanded, onToggleExpansionClick, table]);
|
31
|
-
|
32
|
-
// Handle pagination
|
33
|
-
const onPageChange = useCallback((page: number) => {
|
34
|
-
table.setPageIndex(page - 1);
|
35
|
-
}, [table]);
|
36
|
-
|
37
|
-
// Handle scroll detection for infinite scroll/virtualization
|
38
|
-
const fetchMoreOnBottomReached = useCallback((
|
39
|
-
containerRefElement: HTMLDivElement | null,
|
40
|
-
fetchNextPage: () => void,
|
41
|
-
isFetching: boolean,
|
42
|
-
totalFetched: number,
|
43
|
-
totalDBRowCount: number
|
44
|
-
) => {
|
45
|
-
if (containerRefElement) {
|
46
|
-
const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
|
47
|
-
// If user scrolls near bottom, fetch more data
|
48
|
-
if (scrollHeight - scrollTop - clientHeight < 500 && !isFetching && totalFetched < totalDBRowCount) {
|
49
|
-
fetchNextPage();
|
50
|
-
}
|
51
|
-
}
|
52
|
-
}, []);
|
53
|
-
|
54
|
-
// Update selection state
|
55
|
-
useEffect(() => {
|
56
|
-
if (onRowSelectionChange) {
|
57
|
-
onRowSelectionChange(table.getState().rowSelection);
|
58
|
-
}
|
59
|
-
}, [table.getState().rowSelection, onRowSelectionChange]);
|
60
|
-
|
61
|
-
return {
|
62
|
-
handleExpandOrCollapse,
|
63
|
-
onPageChange,
|
64
|
-
fetchMoreOnBottomReached
|
65
|
-
};
|
66
|
-
}
|
@@ -1,195 +0,0 @@
|
|
1
|
-
import { useState, useCallback, useMemo } from 'react';
|
2
|
-
import {
|
3
|
-
useReactTable,
|
4
|
-
getCoreRowModel,
|
5
|
-
getExpandedRowModel,
|
6
|
-
getPaginationRowModel,
|
7
|
-
getSortedRowModel,
|
8
|
-
RowSelectionState,
|
9
|
-
Row
|
10
|
-
} from "@tanstack/react-table";
|
11
|
-
import { GenericObject } from "../../types";
|
12
|
-
import { createColumnHelper } from "@tanstack/react-table";
|
13
|
-
import { createCellFunction } from "../Utilities/CellRendererUtils";
|
14
|
-
|
15
|
-
interface UseTableStateProps {
|
16
|
-
tableData: GenericObject[];
|
17
|
-
columnDefinitions: GenericObject[];
|
18
|
-
expandedControl?: GenericObject;
|
19
|
-
sortControl?: GenericObject;
|
20
|
-
onRowToggleClick?: (arg: Row<GenericObject>) => void;
|
21
|
-
selectableRows?: boolean;
|
22
|
-
initialLoadingRowsCount?: number;
|
23
|
-
loading?: boolean | string;
|
24
|
-
pagination?: boolean;
|
25
|
-
paginationProps?: GenericObject;
|
26
|
-
virtualizedRows?: boolean;
|
27
|
-
tableOptions?: GenericObject;
|
28
|
-
onRowSelectionChange?: (arg: RowSelectionState) => void;
|
29
|
-
}
|
30
|
-
|
31
|
-
export function useTableState({
|
32
|
-
tableData,
|
33
|
-
columnDefinitions,
|
34
|
-
expandedControl,
|
35
|
-
sortControl,
|
36
|
-
onRowToggleClick,
|
37
|
-
selectableRows,
|
38
|
-
initialLoadingRowsCount = 10,
|
39
|
-
loading,
|
40
|
-
pagination = false,
|
41
|
-
paginationProps,
|
42
|
-
virtualizedRows = false,
|
43
|
-
tableOptions
|
44
|
-
}: UseTableStateProps) {
|
45
|
-
// Create a local state for expanded and setExpanded if expandedControl not used
|
46
|
-
const [localExpanded, setLocalExpanded] = useState({});
|
47
|
-
const [loadingStateRowCount, setLoadingStateRowCount] = useState(initialLoadingRowsCount);
|
48
|
-
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
49
|
-
|
50
|
-
// Determine whether to use the prop or the local state
|
51
|
-
const expanded = expandedControl ? expandedControl.value : localExpanded;
|
52
|
-
const setExpanded = expandedControl ? expandedControl.onChange : setLocalExpanded;
|
53
|
-
|
54
|
-
// Virtualized data handling (chunked loading)
|
55
|
-
const fetchSize = 20; // Number of rows per "page"
|
56
|
-
const [fullData] = useState(tableData); // All data from the JSON file
|
57
|
-
const [dataChunk, setDataChunk] = useState(fullData.slice(0, fetchSize)); // Initial chunk
|
58
|
-
const [totalFetched, setTotalFetched] = useState(fetchSize); // Track loaded rows
|
59
|
-
const [isFetching, setIsFetching] = useState(false);
|
60
|
-
|
61
|
-
// Create column structure
|
62
|
-
const columnHelper = createColumnHelper();
|
63
|
-
|
64
|
-
// Build columns with proper cell renderers
|
65
|
-
const buildColumns = useCallback((columnDefinitions: GenericObject[], isRoot = true): any[] => {
|
66
|
-
return columnDefinitions?.map((column, index) => {
|
67
|
-
const isFirstColumn = isRoot && index === 0;
|
68
|
-
|
69
|
-
// Handle grouped columns
|
70
|
-
if (column.columns && column.columns.length > 0) {
|
71
|
-
return {
|
72
|
-
header: column.label || "",
|
73
|
-
columns: buildColumns(column.columns, false),
|
74
|
-
};
|
75
|
-
}
|
76
|
-
|
77
|
-
// Define the base column structure
|
78
|
-
const columnStructure = {
|
79
|
-
...columnHelper.accessor(column.accessor, {
|
80
|
-
header: column.label || "",
|
81
|
-
}),
|
82
|
-
};
|
83
|
-
|
84
|
-
if (column.cellAccessors || column.customRenderer) {
|
85
|
-
columnStructure.cell = createCellFunction(
|
86
|
-
column.cellAccessors || [],
|
87
|
-
column.customRenderer,
|
88
|
-
isFirstColumn,
|
89
|
-
onRowToggleClick,
|
90
|
-
selectableRows
|
91
|
-
);
|
92
|
-
}
|
93
|
-
|
94
|
-
return columnStructure;
|
95
|
-
}) || [];
|
96
|
-
}, [columnHelper, onRowToggleClick, selectableRows]);
|
97
|
-
|
98
|
-
const columns = useMemo(() => buildColumns(columnDefinitions), [buildColumns, columnDefinitions]);
|
99
|
-
|
100
|
-
// Sorting configuration
|
101
|
-
const sorting = useMemo(() => ([{
|
102
|
-
id: columnDefinitions[0].accessor,
|
103
|
-
desc: sortControl && sortControl.value !== null ? !sortControl.value.desc : false,
|
104
|
-
}]), [columnDefinitions, sortControl]);
|
105
|
-
|
106
|
-
// Custom state based on features enabled
|
107
|
-
const customState = useCallback(() => {
|
108
|
-
if (sortControl && selectableRows) {
|
109
|
-
return { state: { expanded, sorting, rowSelection } };
|
110
|
-
} else if (sortControl) {
|
111
|
-
return { state: { expanded, sorting } };
|
112
|
-
} else if (selectableRows) {
|
113
|
-
return { state: { expanded, rowSelection } };
|
114
|
-
} else {
|
115
|
-
return { state: { expanded } };
|
116
|
-
}
|
117
|
-
}, [expanded, rowSelection, sortControl, selectableRows, sorting]);
|
118
|
-
|
119
|
-
// Pagination configuration
|
120
|
-
const paginationInitializer = useMemo(() => {
|
121
|
-
if (!pagination) return {};
|
122
|
-
|
123
|
-
return {
|
124
|
-
getPaginationRowModel: getPaginationRowModel(),
|
125
|
-
paginateExpandedRows: false,
|
126
|
-
initialState: {
|
127
|
-
pagination: {
|
128
|
-
pageIndex: paginationProps?.pageIndex ?? 0,
|
129
|
-
pageSize: paginationProps?.pageSize ?? 20,
|
130
|
-
},
|
131
|
-
},
|
132
|
-
};
|
133
|
-
}, [pagination, paginationProps]);
|
134
|
-
|
135
|
-
// Initialize the table
|
136
|
-
const table = useReactTable({
|
137
|
-
data: loading ? Array(loadingStateRowCount).fill({}) : (virtualizedRows ? dataChunk : tableData),
|
138
|
-
columns,
|
139
|
-
onExpandedChange: setExpanded,
|
140
|
-
getSubRows: (row: GenericObject) => row.children,
|
141
|
-
getCoreRowModel: getCoreRowModel(),
|
142
|
-
getExpandedRowModel: getExpandedRowModel(),
|
143
|
-
getSortedRowModel: getSortedRowModel(),
|
144
|
-
enableSortingRemoval: false,
|
145
|
-
sortDescFirst: true,
|
146
|
-
onRowSelectionChange: setRowSelection,
|
147
|
-
getRowId: selectableRows ? row => row.id : undefined,
|
148
|
-
meta: {
|
149
|
-
columnDefinitions
|
150
|
-
},
|
151
|
-
...customState(),
|
152
|
-
...paginationInitializer,
|
153
|
-
...tableOptions,
|
154
|
-
});
|
155
|
-
|
156
|
-
// Check if table has any sub-rows
|
157
|
-
const hasAnySubRows = table.getRowModel().rows.some(row => row.subRows && row.subRows.length > 0);
|
158
|
-
const selectedRowsLength = Object.keys(table.getState().rowSelection).length;
|
159
|
-
|
160
|
-
// Data fetching for virtualized view
|
161
|
-
const fetchNextPage = useCallback(() => {
|
162
|
-
if (isFetching || totalFetched >= fullData.length) return;
|
163
|
-
|
164
|
-
setIsFetching(true);
|
165
|
-
// Simulate API call delay
|
166
|
-
setTimeout(() => {
|
167
|
-
const nextChunk = fullData.slice(totalFetched, totalFetched + fetchSize);
|
168
|
-
setDataChunk(prev => [...prev, ...nextChunk]);
|
169
|
-
setTotalFetched(prev => prev + nextChunk.length);
|
170
|
-
setIsFetching(false);
|
171
|
-
}, 500);
|
172
|
-
}, [isFetching, totalFetched, fullData, fetchSize]);
|
173
|
-
|
174
|
-
// Update row count for loading state
|
175
|
-
const updateLoadingStateRowCount = useCallback(() => {
|
176
|
-
const rowsCount = table.getRowModel().rows.length;
|
177
|
-
if (rowsCount !== loadingStateRowCount && rowsCount !== 0) {
|
178
|
-
setLoadingStateRowCount(rowsCount);
|
179
|
-
}
|
180
|
-
}, [loadingStateRowCount, table]);
|
181
|
-
|
182
|
-
return {
|
183
|
-
table,
|
184
|
-
expanded,
|
185
|
-
setExpanded,
|
186
|
-
hasAnySubRows,
|
187
|
-
selectedRowsLength,
|
188
|
-
fetchNextPage,
|
189
|
-
updateLoadingStateRowCount,
|
190
|
-
rowSelection,
|
191
|
-
fullData,
|
192
|
-
totalFetched,
|
193
|
-
isFetching
|
194
|
-
};
|
195
|
-
}
|
@@ -1,73 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { Row, Getter } from "@tanstack/react-table";
|
3
|
-
import { GenericObject } from "../../types";
|
4
|
-
import { CustomCell } from "../Components/CustomCell";
|
5
|
-
|
6
|
-
/**
|
7
|
-
* Creates a cell render function for table columns
|
8
|
-
*
|
9
|
-
* @param cellAccessors Array of accessors to use based on row depth
|
10
|
-
* @param customRenderer Optional custom renderer function
|
11
|
-
* @param isFirstColumn Whether this is the first column (special handling)
|
12
|
-
* @param onRowToggleClick Optional callback for row toggle
|
13
|
-
* @param selectableRows Whether rows are selectable
|
14
|
-
*/
|
15
|
-
export const createCellFunction = (
|
16
|
-
cellAccessors: string[],
|
17
|
-
customRenderer?: (row: Row<GenericObject>, value: any) => JSX.Element,
|
18
|
-
isFirstColumn?: boolean,
|
19
|
-
onRowToggleClick?: (row: Row<GenericObject>) => void,
|
20
|
-
selectableRows?: boolean
|
21
|
-
) => {
|
22
|
-
// Add display name to the returned function
|
23
|
-
const cellRenderer = ({
|
24
|
-
row,
|
25
|
-
getValue,
|
26
|
-
}: {
|
27
|
-
row: Row<GenericObject>
|
28
|
-
getValue: Getter<string>
|
29
|
-
}) => {
|
30
|
-
const rowData = row.original;
|
31
|
-
|
32
|
-
if (isFirstColumn) {
|
33
|
-
switch (row.depth) {
|
34
|
-
case 0: {
|
35
|
-
return (
|
36
|
-
<CustomCell
|
37
|
-
customRenderer={customRenderer}
|
38
|
-
getValue={getValue}
|
39
|
-
onRowToggleClick={onRowToggleClick}
|
40
|
-
row={row}
|
41
|
-
selectableRows={selectableRows}
|
42
|
-
/>
|
43
|
-
);
|
44
|
-
}
|
45
|
-
default: {
|
46
|
-
// Handle other depths based on cellAccessors
|
47
|
-
const depthAccessor = cellAccessors[row.depth - 1]; // Adjust index for depth
|
48
|
-
const accessorValue = rowData[depthAccessor];
|
49
|
-
return accessorValue ? (
|
50
|
-
<CustomCell
|
51
|
-
customRenderer={customRenderer}
|
52
|
-
onRowToggleClick={onRowToggleClick}
|
53
|
-
row={row}
|
54
|
-
selectableRows={selectableRows}
|
55
|
-
value={accessorValue}
|
56
|
-
/>
|
57
|
-
) : (
|
58
|
-
"N/A"
|
59
|
-
);
|
60
|
-
}
|
61
|
-
}
|
62
|
-
}
|
63
|
-
|
64
|
-
return customRenderer
|
65
|
-
? customRenderer(row, getValue())
|
66
|
-
: getValue();
|
67
|
-
};
|
68
|
-
|
69
|
-
// Add a display name to the function to fix the react/display-name warning
|
70
|
-
cellRenderer.displayName = 'CellRenderer';
|
71
|
-
|
72
|
-
return cellRenderer;
|
73
|
-
};
|
@@ -1,52 +0,0 @@
|
|
1
|
-
import { Row } from "@tanstack/react-table"
|
2
|
-
import { GenericObject } from "../../types"
|
3
|
-
|
4
|
-
/**
|
5
|
-
* Determines the background color class for a row
|
6
|
-
*/
|
7
|
-
export const getRowColorClass = (
|
8
|
-
row: Row<GenericObject>,
|
9
|
-
inlineRowLoading: boolean
|
10
|
-
): string => {
|
11
|
-
const isExpandable = row.getIsExpanded();
|
12
|
-
const rowHasNoChildren = row.original?.children && !row.original.children.length ? true : false;
|
13
|
-
const rowBackground = isExpandable && ((!inlineRowLoading && row.getCanExpand()) || (inlineRowLoading && rowHasNoChildren));
|
14
|
-
|
15
|
-
return row.getIsSelected() ? "bg-row-selection" : rowBackground ? "bg-silver" : "bg-white";
|
16
|
-
}
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Determines if loading indicator should be shown for a row
|
20
|
-
*/
|
21
|
-
export const shouldShowLoadingIndicator = (
|
22
|
-
row: Row<GenericObject>,
|
23
|
-
inlineRowLoading: boolean,
|
24
|
-
cellAccessorsLength: number
|
25
|
-
): boolean => {
|
26
|
-
const isExpandable = row.getIsExpanded();
|
27
|
-
const rowHasNoChildren = row.original?.children && !row.original.children.length ? true : false;
|
28
|
-
|
29
|
-
return isExpandable &&
|
30
|
-
(inlineRowLoading && rowHasNoChildren) &&
|
31
|
-
(row.depth < cellAccessorsLength);
|
32
|
-
}
|
33
|
-
|
34
|
-
/**
|
35
|
-
* Creates a virtual item style object for virtualized rows
|
36
|
-
*/
|
37
|
-
export const createVirtualItemStyle = (startPosition: number): React.CSSProperties => {
|
38
|
-
return {
|
39
|
-
position: 'absolute',
|
40
|
-
top: 0,
|
41
|
-
left: 0,
|
42
|
-
width: '100%',
|
43
|
-
transform: `translateY(${startPosition}px)`,
|
44
|
-
};
|
45
|
-
}
|
46
|
-
|
47
|
-
/**
|
48
|
-
* Calculates padding left based on row depth
|
49
|
-
*/
|
50
|
-
export const getDepthPaddingLeft = (depth: number): string => {
|
51
|
-
return `${depth === 0 ? 0.5 : (depth * 2)}em`;
|
52
|
-
}
|