beautiful-grid 1.0.13 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -6
- package/cjs/BGrid.js +388 -44
- package/cjs/components/CellNavigationDomSync.js +8 -0
- package/cjs/components/CellTextEditorGateway.js +13 -9
- package/cjs/components/ColResizer.js +13 -7
- package/cjs/components/MasterDetailCell.js +145 -0
- package/cjs/components/MasterDetailContext.js +42 -0
- package/cjs/components/Table.js +162 -52
- package/cjs/components/TableBody.js +7 -3
- package/cjs/components/TableBodyCell.js +2 -1
- package/cjs/components/TableSummary.js +25 -34
- package/cjs/components/TableSummaryFronzen.js +36 -34
- package/cjs/store/createAppStore.js +2 -0
- package/cjs/utils/cellSelectionGeometry.js +32 -6
- package/cjs/utils/columnVisibility.js +17 -14
- package/cjs/utils/index.js +1 -0
- package/cjs/utils/rowHeightMetrics.js +47 -6
- package/cjs/utils/summary.js +55 -0
- package/cjs/utils/useRowReorderController.js +5 -1
- package/esm/BGrid.js +387 -72
- package/esm/components/CellNavigationDomSync.js +8 -0
- package/esm/components/CellTextEditorGateway.js +12 -9
- package/esm/components/ColResizer.js +8 -2
- package/esm/components/MasterDetailCell.js +101 -0
- package/esm/components/MasterDetailContext.js +5 -0
- package/esm/components/Table.js +151 -42
- package/esm/components/TableBody.js +6 -2
- package/esm/components/TableBodyCell.js +2 -1
- package/esm/components/TableSummary.js +26 -29
- package/esm/components/TableSummaryFronzen.js +26 -29
- package/esm/store/createAppStore.js +2 -0
- package/esm/utils/cellSelectionGeometry.js +31 -5
- package/esm/utils/columnVisibility.js +21 -18
- package/esm/utils/index.js +1 -0
- package/esm/utils/rowHeightMetrics.js +46 -6
- package/esm/utils/summary.js +35 -0
- package/esm/utils/useRowReorderController.js +5 -1
- package/package.json +1 -1
- package/style.css +164 -14
- package/types/BGrid.d.ts +1 -1
- package/types/components/MasterDetailCell.d.ts +21 -0
- package/types/components/MasterDetailContext.d.ts +20 -0
- package/types/components/Table.d.ts +1 -0
- package/types/components/TableBody.d.ts +2 -1
- package/types/store/createAppStore.d.ts +1 -1
- package/types/types.d.ts +70 -4
- package/types/utils/cellSelectionGeometry.d.ts +3 -1
- package/types/utils/index.d.ts +1 -0
- package/types/utils/rowHeightMetrics.d.ts +15 -1
- package/types/utils/summary.d.ts +13 -0
|
@@ -46,12 +46,18 @@ function ColResizer({ container, columnIndex, hideHandle, bordered, frozenBounda
|
|
|
46
46
|
targetDiv.style.top = '-9999px';
|
|
47
47
|
targetDiv.innerHTML = `<table><thead>${headFrozenHTML}</thead><tbody>${bodyFrozenHTML}</tbody></table>
|
|
48
48
|
<table><thead>${headHTML}</thead><tbody>${bodyHTML}</tbody></table>`;
|
|
49
|
-
|
|
49
|
+
// Measure with the grid's inherited font and real header/body padding.
|
|
50
|
+
targetDiv.querySelectorAll('table').forEach(table => {
|
|
51
|
+
table.className = 'bgrid-head-table bgrid-body-table';
|
|
52
|
+
table.style.tableLayout = 'auto';
|
|
53
|
+
table.style.width = 'max-content';
|
|
54
|
+
});
|
|
55
|
+
const bodyTarget = container.current;
|
|
50
56
|
bodyTarget.append(targetDiv);
|
|
51
57
|
await delay(30);
|
|
52
58
|
const targetTd = targetDiv.querySelector(`tr td.bgrid-head-cell[data-column-index="${columnIndex}"]`);
|
|
53
59
|
if (targetTd) {
|
|
54
|
-
setColumnWidth(columnIndex, { width: targetTd.
|
|
60
|
+
setColumnWidth(columnIndex, { width: Math.ceil(targetTd.offsetWidth) + 1 });
|
|
55
61
|
setColumnWidth(columnIndex, { updateColumns: true });
|
|
56
62
|
}
|
|
57
63
|
targetDiv.remove();
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { getColumnId } from '../utils';
|
|
3
|
+
import { useMasterDetailContext } from './MasterDetailContext';
|
|
4
|
+
export function MasterDetailCell({ column, item, sourceIndex, children }) {
|
|
5
|
+
const masterDetail = useMasterDetailContext();
|
|
6
|
+
if (!masterDetail || getColumnId(column) !== masterDetail.expandColumnId) {
|
|
7
|
+
return React.createElement(React.Fragment, null, children);
|
|
8
|
+
}
|
|
9
|
+
const rowKey = masterDetail.getRowKey(item.values);
|
|
10
|
+
if (rowKey === undefined || rowKey === null) {
|
|
11
|
+
return React.createElement(React.Fragment, null, children);
|
|
12
|
+
}
|
|
13
|
+
const isExpandable = masterDetail.hasDetail(item, sourceIndex);
|
|
14
|
+
const expanded = masterDetail.expandedKeysSet.has(rowKey);
|
|
15
|
+
const toggleId = masterDetail.getToggleElementId(rowKey);
|
|
16
|
+
const detailId = masterDetail.getDetailElementId(rowKey);
|
|
17
|
+
return (React.createElement("span", { className: 'bgrid-master-detail-cell' },
|
|
18
|
+
isExpandable ? (React.createElement("button", { type: 'button', id: toggleId, className: 'bgrid-master-detail-toggle', "aria-expanded": expanded, "aria-controls": expanded ? detailId : undefined, "aria-label": expanded ? masterDetail.collapseAriaLabel : masterDetail.expandAriaLabel, disabled: masterDetail.disabled, onClick: event => {
|
|
19
|
+
event.stopPropagation();
|
|
20
|
+
masterDetail.toggle(rowKey, item, sourceIndex);
|
|
21
|
+
}, onKeyDown: event => {
|
|
22
|
+
// Prevent master grid cell navigation from capturing Space or Enter on the toggle button
|
|
23
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
24
|
+
event.stopPropagation();
|
|
25
|
+
}
|
|
26
|
+
} },
|
|
27
|
+
React.createElement("span", { className: 'bgrid-master-detail-icon', "aria-hidden": 'true' }, expanded ? masterDetail.icons?.expanded ?? '⌄' : masterDetail.icons?.collapsed ?? '›'))) : (React.createElement("span", { className: 'bgrid-master-detail-toggle-spacer', "aria-hidden": 'true' })),
|
|
28
|
+
React.createElement("span", { className: 'bgrid-master-detail-cell-content' }, children)));
|
|
29
|
+
}
|
|
30
|
+
export function MasterDetailRow({ item, sourceIndex, visibleIndex, detailHeight, isLeftRegion, viewportWidth, colSpan, frozenColumnsWidth, }) {
|
|
31
|
+
const masterDetail = useMasterDetailContext();
|
|
32
|
+
if (!masterDetail)
|
|
33
|
+
return null;
|
|
34
|
+
const rowKey = masterDetail.getRowKey(item.values);
|
|
35
|
+
if (rowKey === undefined || rowKey === null || !masterDetail.expandedKeysSet.has(rowKey)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const toggleId = masterDetail.getToggleElementId(rowKey);
|
|
39
|
+
const detailId = masterDetail.getDetailElementId(rowKey);
|
|
40
|
+
if (isLeftRegion) {
|
|
41
|
+
return (React.createElement("tr", { className: 'bgrid-detail-frozen-row', "aria-hidden": 'true', "data-detail-ri": visibleIndex, style: {
|
|
42
|
+
height: detailHeight,
|
|
43
|
+
['--bgrid-item-cell-height']: `${detailHeight}px`,
|
|
44
|
+
} },
|
|
45
|
+
React.createElement("td", { colSpan: colSpan, style: {
|
|
46
|
+
height: detailHeight,
|
|
47
|
+
maxHeight: 'none',
|
|
48
|
+
padding: 0,
|
|
49
|
+
margin: 0,
|
|
50
|
+
} })));
|
|
51
|
+
}
|
|
52
|
+
return (React.createElement("tr", { className: 'bgrid-detail-row', "data-bgrid-detail-owner": 'true', "data-detail-ri": visibleIndex, style: {
|
|
53
|
+
height: detailHeight,
|
|
54
|
+
['--bgrid-item-cell-height']: `${detailHeight}px`,
|
|
55
|
+
} },
|
|
56
|
+
React.createElement("td", { colSpan: colSpan, className: 'bgrid-detail-cell', style: {
|
|
57
|
+
height: detailHeight,
|
|
58
|
+
maxHeight: 'none',
|
|
59
|
+
padding: 0,
|
|
60
|
+
margin: 0,
|
|
61
|
+
verticalAlign: 'top',
|
|
62
|
+
} },
|
|
63
|
+
React.createElement(DetailPanelContent, { item: item, rowKey: rowKey, sourceIndex: sourceIndex, visibleIndex: visibleIndex, detailHeight: detailHeight, viewportWidth: viewportWidth, frozenColumnsWidth: frozenColumnsWidth, toggleId: toggleId, detailId: detailId, detailRender: masterDetail.detailRender, collapse: () => masterDetail.collapse(rowKey) })),
|
|
64
|
+
React.createElement("td", { "data-none": 'true' })));
|
|
65
|
+
}
|
|
66
|
+
function DetailPanelContent({ item, rowKey, sourceIndex, visibleIndex, detailHeight, viewportWidth, frozenColumnsWidth, toggleId, detailId, detailRender, collapse, }) {
|
|
67
|
+
const panelRef = React.useRef(null);
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
const panel = panelRef.current;
|
|
70
|
+
return () => {
|
|
71
|
+
const active = document.activeElement;
|
|
72
|
+
if (active && panel && panel.contains(active)) {
|
|
73
|
+
const toggle = document.getElementById(toggleId);
|
|
74
|
+
toggle?.focus();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}, [toggleId]);
|
|
78
|
+
const contentHeight = Math.max(detailHeight - 1, 0);
|
|
79
|
+
return (React.createElement("div", { ref: panelRef, id: detailId, role: 'region', "aria-labelledby": toggleId, className: 'bgrid-master-detail-panel', "data-bgrid-detail-owner": 'true', "data-visible-index": visibleIndex, "data-source-index": sourceIndex, style: {
|
|
80
|
+
position: 'sticky',
|
|
81
|
+
left: frozenColumnsWidth ?? 0,
|
|
82
|
+
width: viewportWidth > 0 ? viewportWidth : undefined,
|
|
83
|
+
maxWidth: '100%',
|
|
84
|
+
height: contentHeight,
|
|
85
|
+
minHeight: contentHeight,
|
|
86
|
+
maxHeight: contentHeight,
|
|
87
|
+
boxSizing: 'border-box',
|
|
88
|
+
overflow: 'auto',
|
|
89
|
+
}, onPointerDown: e => {
|
|
90
|
+
e.stopPropagation();
|
|
91
|
+
}, onContextMenu: e => {
|
|
92
|
+
e.stopPropagation();
|
|
93
|
+
} }, detailRender({
|
|
94
|
+
item,
|
|
95
|
+
rowKey,
|
|
96
|
+
sourceIndex,
|
|
97
|
+
visibleIndex,
|
|
98
|
+
expanded: true,
|
|
99
|
+
collapse,
|
|
100
|
+
})));
|
|
101
|
+
}
|
package/esm/components/Table.js
CHANGED
|
@@ -58,11 +58,12 @@ function Table(props) {
|
|
|
58
58
|
itemPadding: s.itemPadding,
|
|
59
59
|
})));
|
|
60
60
|
// [Selector Group 2] Header, Footer, Summary - 헤더/푸터/요약
|
|
61
|
-
const { headerHeight, footerHeight, bottomBarHeight, summaryHeight } = useAppStore(useShallow(s => ({
|
|
61
|
+
const { headerHeight, footerHeight, bottomBarHeight, summaryHeight, summaryRowHeight } = useAppStore(useShallow(s => ({
|
|
62
62
|
headerHeight: s.headerHeight,
|
|
63
63
|
footerHeight: s.footerHeight,
|
|
64
64
|
bottomBarHeight: s.bottomBarHeight,
|
|
65
65
|
summaryHeight: s.summaryHeight,
|
|
66
|
+
summaryRowHeight: s.summaryRowHeight,
|
|
66
67
|
})));
|
|
67
68
|
// [Selector Group 3] Scroll State - 스크롤 상태
|
|
68
69
|
const { scrollLeft, scrollTop } = useAppStore(useShallow(s => ({
|
|
@@ -113,7 +114,7 @@ function Table(props) {
|
|
|
113
114
|
cellInteractionSession: s.cellInteractionSession,
|
|
114
115
|
})));
|
|
115
116
|
// [Selector Group 6] State Setters - 차원 설정자
|
|
116
|
-
const { setHeight, setWidth, setContentBodyHeight, setDisplayItemCount, setHeaderHeight, setFooterHeight, setBottomBarHeight, setSummaryHeight, setItemHeight, setItemPadding, setLoading, setSpinning, setDisabled, } = useAppStore(useShallow(s => ({
|
|
117
|
+
const { setHeight, setWidth, setContentBodyHeight, setDisplayItemCount, setHeaderHeight, setFooterHeight, setBottomBarHeight, setSummaryHeight, setSummaryRowHeight, setItemHeight, setItemPadding, setLoading, setSpinning, setDisabled, } = useAppStore(useShallow(s => ({
|
|
117
118
|
setHeight: s.setHeight,
|
|
118
119
|
setWidth: s.setWidth,
|
|
119
120
|
setContentBodyHeight: s.setContentBodyHeight,
|
|
@@ -122,6 +123,7 @@ function Table(props) {
|
|
|
122
123
|
setFooterHeight: s.setFooterHeight,
|
|
123
124
|
setBottomBarHeight: s.setBottomBarHeight,
|
|
124
125
|
setSummaryHeight: s.setSummaryHeight,
|
|
126
|
+
setSummaryRowHeight: s.setSummaryRowHeight,
|
|
125
127
|
setItemHeight: s.setItemHeight,
|
|
126
128
|
setItemPadding: s.setItemPadding,
|
|
127
129
|
setLoading: s.setLoading,
|
|
@@ -204,20 +206,29 @@ function Table(props) {
|
|
|
204
206
|
const variableRowOffsets = rowHeightMetrics.variable ? rowHeightMetrics.offsets : undefined;
|
|
205
207
|
const scrollableBodyHeight = Math.max(contentBodyHeight - frozenRowsHeight, 0);
|
|
206
208
|
const scrollOverscanRows = Math.max(KEYBOARD_NAVIGATION_ROW_WINDOW_SIZE, Math.ceil(scrollableBodyHeight / Math.max(trHeight, 1)));
|
|
207
|
-
const mainViewportWidth = Math.max(width - (frozenColumnsWidth ?? 0), 0);
|
|
208
209
|
const logicalBodyContentHeight = rowHeightMetrics.totalHeight;
|
|
210
|
+
const scrollContainerRef = useRef(null);
|
|
211
|
+
const scrollableColumnsWidth = React.useMemo(() => columns.slice(props.frozenColumnIndex ?? 0).reduce((totalWidth, column) => totalWidth + (column.width ?? 100), 0), [columns, props.frozenColumnIndex]);
|
|
212
|
+
const stickyTopHeight = headerHeight + (summary?.position === 'top' ? summaryHeight : 0);
|
|
213
|
+
const stickyBottomHeight = summary?.position === 'bottom' ? summaryHeight : 0;
|
|
214
|
+
const stickyFixedHeight = stickyTopHeight + stickyBottomHeight;
|
|
215
|
+
const scrollPlaneContentWidth = (frozenColumnsWidth ?? 0) + scrollableColumnsWidth;
|
|
216
|
+
const measuredScrollbarMetrics = useScrollbarMetrics(scrollContainerRef, [data.length, itemHeight, itemPadding, contentBodyHeight, width], scrollPlaneContentWidth, stickyFixedHeight);
|
|
217
|
+
// Native horizontal scrollbars occupy viewport space; use the measured body height for every scroll path.
|
|
218
|
+
const effectiveBodyHeight = scrollbar.variant === 'native'
|
|
219
|
+
? measuredScrollbarMetrics.vertical.viewportSize || contentBodyHeight
|
|
220
|
+
: contentBodyHeight;
|
|
209
221
|
const virtualScrollWindowMetrics = React.useMemo(() => getVirtualScrollWindowMetrics({
|
|
210
222
|
logicalContentHeight: logicalBodyContentHeight,
|
|
211
|
-
viewportHeight:
|
|
223
|
+
viewportHeight: effectiveBodyHeight,
|
|
212
224
|
enabled: scrollbar.variant !== 'native',
|
|
213
|
-
}), [
|
|
225
|
+
}), [effectiveBodyHeight, logicalBodyContentHeight, scrollbar.variant]);
|
|
214
226
|
const [virtualScrollBase, setVirtualScrollBase] = React.useState(0);
|
|
215
227
|
const virtualScrollBaseRef = useRef(0);
|
|
216
228
|
const containerRef = useRef(null);
|
|
217
229
|
const searchPopoverRef = useRef(null);
|
|
218
230
|
const editorPortalRef = useRef(null);
|
|
219
231
|
const bodyContainerRef = useRef(null);
|
|
220
|
-
const scrollContainerRef = useRef(null);
|
|
221
232
|
const logicalVerticalScrollState = React.useMemo(() => ({
|
|
222
233
|
scrollTop,
|
|
223
234
|
scrollHeight: virtualScrollWindowMetrics.logicalContentHeight,
|
|
@@ -275,6 +286,8 @@ function Table(props) {
|
|
|
275
286
|
rowCount: data.length,
|
|
276
287
|
rowHeight: trHeight,
|
|
277
288
|
rowOffsets: variableRowOffsets,
|
|
289
|
+
rowHeights: rowHeightMetrics.heights,
|
|
290
|
+
detailHeights: rowHeightMetrics.detailHeights,
|
|
278
291
|
frozenColumnCount: props.frozenColumnIndex ?? 0,
|
|
279
292
|
frozenRowCount,
|
|
280
293
|
frozenColumnsWidth: frozenColumnsWidth ?? 0,
|
|
@@ -285,6 +298,8 @@ function Table(props) {
|
|
|
285
298
|
frozenColumnsWidth,
|
|
286
299
|
frozenRowCount,
|
|
287
300
|
props.frozenColumnIndex,
|
|
301
|
+
rowHeightMetrics.detailHeights,
|
|
302
|
+
rowHeightMetrics.heights,
|
|
288
303
|
trHeight,
|
|
289
304
|
variableRowOffsets,
|
|
290
305
|
]);
|
|
@@ -294,6 +309,8 @@ function Table(props) {
|
|
|
294
309
|
rowCount: data.length,
|
|
295
310
|
rowHeight: trHeight,
|
|
296
311
|
rowOffsets: variableRowOffsets,
|
|
312
|
+
rowHeights: rowHeightMetrics.heights,
|
|
313
|
+
detailHeights: rowHeightMetrics.detailHeights,
|
|
297
314
|
frozenColumnCount: props.frozenColumnIndex ?? 0,
|
|
298
315
|
frozenRowCount,
|
|
299
316
|
frozenColumnsWidth: frozenColumnsWidth ?? 0,
|
|
@@ -304,21 +321,13 @@ function Table(props) {
|
|
|
304
321
|
frozenColumnsWidth,
|
|
305
322
|
frozenRowCount,
|
|
306
323
|
props.frozenColumnIndex,
|
|
324
|
+
rowHeightMetrics.detailHeights,
|
|
325
|
+
rowHeightMetrics.heights,
|
|
307
326
|
trHeight,
|
|
308
327
|
variableRowOffsets,
|
|
309
328
|
]);
|
|
310
329
|
const activeOverlayFill = activeCellSelected;
|
|
311
330
|
const activeOverlayRing = !!activeCell && !hasMultiCellSelection;
|
|
312
|
-
const renderSelectionOverlay = (quadrant) => {
|
|
313
|
-
const topQuadrant = quadrant === 'top-left' || quadrant === 'top-main';
|
|
314
|
-
const leftQuadrant = quadrant === 'top-left' || quadrant === 'body-left';
|
|
315
|
-
return (React.createElement(CellSelectionOverlay, { quadrant: quadrant, selectionFragments: selectionFragments, activeFragments: activeFragments, activeFill: activeOverlayFill, activeRing: activeOverlayRing, viewport: {
|
|
316
|
-
left: leftQuadrant ? 0 : scrollLeft,
|
|
317
|
-
top: topQuadrant ? 0 : scrollTop,
|
|
318
|
-
width: leftQuadrant ? frozenColumnsWidth ?? 0 : mainViewportWidth,
|
|
319
|
-
height: topQuadrant ? frozenRowsHeight : scrollableBodyHeight,
|
|
320
|
-
}, offsetTop: !topQuadrant && virtualScrollWindowMetrics.enabled ? virtualScrollBase : 0 }));
|
|
321
|
-
};
|
|
322
331
|
const visibleScrollableRows = React.useMemo(() => getVisibleScrollableRowRange({
|
|
323
332
|
scrollTop,
|
|
324
333
|
viewportHeight: scrollableBodyHeight,
|
|
@@ -455,14 +464,9 @@ function Table(props) {
|
|
|
455
464
|
storeRowKey,
|
|
456
465
|
storeSourceIndexByVisibleIndex,
|
|
457
466
|
]);
|
|
458
|
-
const scrollableColumnsWidth = React.useMemo(() => columns.slice(props.frozenColumnIndex ?? 0).reduce((totalWidth, column) => totalWidth + (column.width ?? 100), 0), [columns, props.frozenColumnIndex]);
|
|
459
|
-
const stickyTopHeight = headerHeight + (summary?.position === 'top' ? summaryHeight : 0);
|
|
460
|
-
const stickyBottomHeight = summary?.position === 'bottom' ? summaryHeight : 0;
|
|
461
|
-
const stickyFixedHeight = stickyTopHeight + stickyBottomHeight;
|
|
462
467
|
const scrollViewportHeight = contentBodyHeight + stickyFixedHeight;
|
|
463
468
|
const physicalScrollableRowsHeight = Math.max(virtualScrollWindowMetrics.physicalContentHeight - frozenRowsHeight, 0);
|
|
464
469
|
const scrollPlaneHeight = stickyFixedHeight + virtualScrollWindowMetrics.physicalContentHeight;
|
|
465
|
-
const scrollPlaneContentWidth = (frozenColumnsWidth ?? 0) + scrollableColumnsWidth;
|
|
466
470
|
const scrollPlaneWidth = Math.max(width, scrollPlaneContentWidth);
|
|
467
471
|
const customVerticalScrollbarGutter = scrollbar.vertical.visible && scrollbar.variant === 'classic'
|
|
468
472
|
? 'var(--bgrid-scrollbar-classic-gutter-size)'
|
|
@@ -471,8 +475,9 @@ function Table(props) {
|
|
|
471
475
|
: undefined;
|
|
472
476
|
const scrollPlaneMinWidth = customVerticalScrollbarGutter
|
|
473
477
|
? `max(100%, calc(${scrollPlaneContentWidth}px + ${customVerticalScrollbarGutter}))`
|
|
474
|
-
:
|
|
475
|
-
|
|
478
|
+
: scrollbar.variant === 'native'
|
|
479
|
+
? `max(100%, ${scrollPlaneContentWidth}px)`
|
|
480
|
+
: scrollPlaneWidth;
|
|
476
481
|
const scrollbarMetrics = React.useMemo(() => virtualScrollWindowMetrics.enabled
|
|
477
482
|
? {
|
|
478
483
|
...measuredScrollbarMetrics,
|
|
@@ -491,6 +496,25 @@ function Table(props) {
|
|
|
491
496
|
right: (frozenColumnsWidth ?? 0) + measuredVerticalScrollbarGutter,
|
|
492
497
|
bottom: stickyFixedHeight + frozenRowsHeight,
|
|
493
498
|
};
|
|
499
|
+
const verticalScrollbarGutterWidth = scrollbar.vertical.visible && scrollbar.variant === 'classic'
|
|
500
|
+
? 25
|
|
501
|
+
: scrollbar.vertical.visible && scrollbar.variant === 'modern'
|
|
502
|
+
? 24
|
|
503
|
+
: 0;
|
|
504
|
+
const horizontalViewportSize = scrollbarMetrics.horizontal.viewportSize > 0
|
|
505
|
+
? scrollbarMetrics.horizontal.viewportSize
|
|
506
|
+
: Math.max(width - containerBorderWidth * 2, 0);
|
|
507
|
+
const mainViewportWidth = Math.max(horizontalViewportSize - (frozenColumnsWidth ?? 0) - verticalScrollbarGutterWidth, 0);
|
|
508
|
+
const renderSelectionOverlay = (quadrant) => {
|
|
509
|
+
const topQuadrant = quadrant === 'top-left' || quadrant === 'top-main';
|
|
510
|
+
const leftQuadrant = quadrant === 'top-left' || quadrant === 'body-left';
|
|
511
|
+
return (React.createElement(CellSelectionOverlay, { quadrant: quadrant, selectionFragments: selectionFragments, activeFragments: activeFragments, activeFill: activeOverlayFill, activeRing: activeOverlayRing, viewport: {
|
|
512
|
+
left: leftQuadrant ? 0 : scrollLeft,
|
|
513
|
+
top: topQuadrant ? 0 : scrollTop,
|
|
514
|
+
width: leftQuadrant ? frozenColumnsWidth ?? 0 : mainViewportWidth,
|
|
515
|
+
height: topQuadrant ? frozenRowsHeight : scrollableBodyHeight,
|
|
516
|
+
}, offsetTop: !topQuadrant && virtualScrollWindowMetrics.enabled ? virtualScrollBase : 0 }));
|
|
517
|
+
};
|
|
494
518
|
const showBottomBar = shouldRenderBottomBar({
|
|
495
519
|
hasPage: !!page,
|
|
496
520
|
hasHorizontalOverflow: scrollbarMetrics.horizontal.hasOverflow,
|
|
@@ -707,6 +731,8 @@ function Table(props) {
|
|
|
707
731
|
return;
|
|
708
732
|
hoveredRowIndexesRef.current.forEach(hoveredIndex => {
|
|
709
733
|
containerRef.current?.querySelectorAll(`tr[data-ri="${hoveredIndex}"]`).forEach(el => {
|
|
734
|
+
if (el.closest('[role="grid"], [role="treegrid"]') !== containerRef.current)
|
|
735
|
+
return;
|
|
710
736
|
el.classList.remove('bgrid-row-hover');
|
|
711
737
|
});
|
|
712
738
|
});
|
|
@@ -722,6 +748,8 @@ function Table(props) {
|
|
|
722
748
|
clearHoveredRow();
|
|
723
749
|
rowIndexes.forEach(rowIndex => {
|
|
724
750
|
containerRef.current?.querySelectorAll(`tr[data-ri="${rowIndex}"]`).forEach(el => {
|
|
751
|
+
if (el.closest('[role="grid"], [role="treegrid"]') !== containerRef.current)
|
|
752
|
+
return;
|
|
725
753
|
el.classList.add('bgrid-row-hover');
|
|
726
754
|
});
|
|
727
755
|
});
|
|
@@ -755,15 +783,25 @@ function Table(props) {
|
|
|
755
783
|
clearHoveredRow();
|
|
756
784
|
return;
|
|
757
785
|
}
|
|
758
|
-
const target = evt.target;
|
|
786
|
+
const target = evt.target instanceof HTMLElement ? evt.target : null;
|
|
787
|
+
const detailOwner = target?.closest('[data-bgrid-detail-owner]');
|
|
788
|
+
if (detailOwner && containerRef.current?.contains(detailOwner)) {
|
|
789
|
+
clearHoveredRow();
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
759
792
|
updateAxisSelectionByTarget(target);
|
|
760
793
|
const physicalCellPosition = getCellPosition(target, containerRef.current);
|
|
761
794
|
const cellPosition = physicalCellPosition ? toLogicalCellPosition(physicalCellPosition) : undefined;
|
|
762
795
|
if (cellSelectionEnabled && cellSelectionDragRef.current && cellPosition) {
|
|
763
796
|
setCellSelectionRanges(updateSelectionDragRange(cellSelectionDragRef.current, getRangeFromDrag(cellSelectionDragRef.current, cellPosition)));
|
|
764
797
|
}
|
|
798
|
+
const targetGrid = target?.closest('[role="grid"], [role="treegrid"]');
|
|
799
|
+
if (targetGrid && targetGrid !== containerRef.current && containerRef.current?.contains(targetGrid)) {
|
|
800
|
+
clearHoveredRow();
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
765
803
|
const tr = target?.closest('tr[data-ri]');
|
|
766
|
-
if (!tr ||
|
|
804
|
+
if (!tr || tr.closest('[role="grid"], [role="treegrid"]') !== containerRef.current) {
|
|
767
805
|
clearHoveredRow();
|
|
768
806
|
return;
|
|
769
807
|
}
|
|
@@ -788,6 +826,13 @@ function Table(props) {
|
|
|
788
826
|
const onBodyPointerDownCapture = useCallback((evt) => {
|
|
789
827
|
if (disabled)
|
|
790
828
|
return;
|
|
829
|
+
const target = evt.target instanceof Element ? evt.target : null;
|
|
830
|
+
const detailOwner = target?.closest('[data-bgrid-detail-owner]');
|
|
831
|
+
if (detailOwner && containerRef.current?.contains(detailOwner))
|
|
832
|
+
return;
|
|
833
|
+
const targetGrid = target?.closest('[role="grid"], [role="treegrid"]');
|
|
834
|
+
if (targetGrid && targetGrid !== containerRef.current && containerRef.current?.contains(targetGrid))
|
|
835
|
+
return;
|
|
791
836
|
const navEnabled = cellNavigationOptions?.enabled ?? true;
|
|
792
837
|
if (!cellSelectionEnabled && !navEnabled)
|
|
793
838
|
return;
|
|
@@ -1314,6 +1359,8 @@ function Table(props) {
|
|
|
1314
1359
|
setFooterHeight(props.footerHeight);
|
|
1315
1360
|
if (props.summaryHeight !== undefined)
|
|
1316
1361
|
setSummaryHeight(props.summaryHeight);
|
|
1362
|
+
if (props.summaryRowHeight !== undefined)
|
|
1363
|
+
setSummaryRowHeight(props.summaryRowHeight);
|
|
1317
1364
|
if (props.itemHeight !== undefined)
|
|
1318
1365
|
setItemHeight(props.itemHeight);
|
|
1319
1366
|
if (props.itemPadding !== undefined)
|
|
@@ -1323,12 +1370,14 @@ function Table(props) {
|
|
|
1323
1370
|
props.headerHeight,
|
|
1324
1371
|
props.footerHeight,
|
|
1325
1372
|
props.summaryHeight,
|
|
1373
|
+
props.summaryRowHeight,
|
|
1326
1374
|
props.itemHeight,
|
|
1327
1375
|
props.itemPadding,
|
|
1328
1376
|
setWidth,
|
|
1329
1377
|
setHeaderHeight,
|
|
1330
1378
|
setFooterHeight,
|
|
1331
1379
|
setSummaryHeight,
|
|
1380
|
+
setSummaryRowHeight,
|
|
1332
1381
|
setItemHeight,
|
|
1333
1382
|
setItemPadding,
|
|
1334
1383
|
]);
|
|
@@ -1895,6 +1944,19 @@ function Table(props) {
|
|
|
1895
1944
|
const activeElement = document.activeElement;
|
|
1896
1945
|
if (!container || (activeElement !== container && !container.contains(activeElement)))
|
|
1897
1946
|
return;
|
|
1947
|
+
const target = evt.target instanceof Element ? evt.target : null;
|
|
1948
|
+
const detailOwner = target?.closest('[data-bgrid-detail-owner]');
|
|
1949
|
+
if (detailOwner && container.contains(detailOwner))
|
|
1950
|
+
return;
|
|
1951
|
+
const activeDetailOwner = activeElement instanceof Element ? activeElement.closest('[data-bgrid-detail-owner]') : null;
|
|
1952
|
+
if (activeDetailOwner && container.contains(activeDetailOwner))
|
|
1953
|
+
return;
|
|
1954
|
+
const targetGrid = target?.closest('[role="grid"], [role="treegrid"]');
|
|
1955
|
+
if (targetGrid && targetGrid !== container && container.contains(targetGrid))
|
|
1956
|
+
return;
|
|
1957
|
+
const activeGrid = activeElement instanceof Element ? activeElement.closest('[role="grid"], [role="treegrid"]') : null;
|
|
1958
|
+
if (activeGrid && activeGrid !== container && container.contains(activeGrid))
|
|
1959
|
+
return;
|
|
1898
1960
|
if (disabled) {
|
|
1899
1961
|
stopArrowRepeat();
|
|
1900
1962
|
return;
|
|
@@ -1908,7 +1970,7 @@ function Table(props) {
|
|
|
1908
1970
|
evt.stopPropagation();
|
|
1909
1971
|
requestSearchOpen(true, 'shortcut');
|
|
1910
1972
|
setTimeout(() => {
|
|
1911
|
-
const input = container.
|
|
1973
|
+
const input = Array.from(container.querySelectorAll('.bgrid-search-input')).find(el => el.closest('[role="grid"], [role="treegrid"]') === container);
|
|
1912
1974
|
input?.focus({ preventScroll: true });
|
|
1913
1975
|
input?.select();
|
|
1914
1976
|
}, searchOpen ? 0 : 1);
|
|
@@ -1919,7 +1981,7 @@ function Table(props) {
|
|
|
1919
1981
|
return;
|
|
1920
1982
|
const isShift = evt.shiftKey;
|
|
1921
1983
|
if (!cellInteractionSession && activeCell && (evt.key === 'ContextMenu' || (isShift && evt.key === 'F10'))) {
|
|
1922
|
-
const targetCell = container.
|
|
1984
|
+
const targetCell = Array.from(container.querySelectorAll(`td[data-bgrid-cell="true"][data-row-index="${activeCell.rowIndex}"][data-column-index="${activeCell.columnIndex}"]`)).find(el => el.closest('[role="grid"], [role="treegrid"]') === container);
|
|
1923
1985
|
const rect = targetCell?.getBoundingClientRect();
|
|
1924
1986
|
if (rect && openCellContextMenu(activeCell, rect.left + 8, rect.top + Math.min(rect.height, 20), true)) {
|
|
1925
1987
|
evt.preventDefault();
|
|
@@ -2121,6 +2183,19 @@ function Table(props) {
|
|
|
2121
2183
|
const activeElement = document.activeElement;
|
|
2122
2184
|
if (!container || (activeElement !== container && !container.contains(activeElement)))
|
|
2123
2185
|
return;
|
|
2186
|
+
const target = evt.target instanceof Element ? evt.target : null;
|
|
2187
|
+
const detailOwner = target?.closest('[data-bgrid-detail-owner]');
|
|
2188
|
+
if (detailOwner && container.contains(detailOwner))
|
|
2189
|
+
return;
|
|
2190
|
+
const activeDetailOwner = activeElement instanceof Element ? activeElement.closest('[data-bgrid-detail-owner]') : null;
|
|
2191
|
+
if (activeDetailOwner && container.contains(activeDetailOwner))
|
|
2192
|
+
return;
|
|
2193
|
+
const targetGrid = target?.closest('[role="grid"], [role="treegrid"]');
|
|
2194
|
+
if (targetGrid && targetGrid !== container && container.contains(targetGrid))
|
|
2195
|
+
return;
|
|
2196
|
+
const activeGrid = activeElement instanceof Element ? activeElement.closest('[role="grid"], [role="treegrid"]') : null;
|
|
2197
|
+
if (activeGrid && activeGrid !== container && container.contains(activeGrid))
|
|
2198
|
+
return;
|
|
2124
2199
|
if (keyboardRuntimeRef.current.disabled)
|
|
2125
2200
|
return;
|
|
2126
2201
|
if (isInteractiveTarget(evt.target))
|
|
@@ -2133,6 +2208,19 @@ function Table(props) {
|
|
|
2133
2208
|
const activeElement = document.activeElement;
|
|
2134
2209
|
if (!container || (activeElement !== container && !container.contains(activeElement)))
|
|
2135
2210
|
return;
|
|
2211
|
+
const target = evt.target instanceof Element ? evt.target : null;
|
|
2212
|
+
const detailOwner = target?.closest('[data-bgrid-detail-owner]');
|
|
2213
|
+
if (detailOwner && container.contains(detailOwner))
|
|
2214
|
+
return;
|
|
2215
|
+
const activeDetailOwner = activeElement instanceof Element ? activeElement.closest('[data-bgrid-detail-owner]') : null;
|
|
2216
|
+
if (activeDetailOwner && container.contains(activeDetailOwner))
|
|
2217
|
+
return;
|
|
2218
|
+
const targetGrid = target?.closest('[role="grid"], [role="treegrid"]');
|
|
2219
|
+
if (targetGrid && targetGrid !== container && container.contains(targetGrid))
|
|
2220
|
+
return;
|
|
2221
|
+
const activeGrid = activeElement instanceof Element ? activeElement.closest('[role="grid"], [role="treegrid"]') : null;
|
|
2222
|
+
if (activeGrid && activeGrid !== container && container.contains(activeGrid))
|
|
2223
|
+
return;
|
|
2136
2224
|
if (keyboardRuntimeRef.current.disabled)
|
|
2137
2225
|
return;
|
|
2138
2226
|
if (keyboardRuntimeRef.current.editItemIndex !== undefined && keyboardRuntimeRef.current.editItemIndex >= 0) {
|
|
@@ -2151,13 +2239,23 @@ function Table(props) {
|
|
|
2151
2239
|
}
|
|
2152
2240
|
};
|
|
2153
2241
|
const handlePointerDown = (evt) => {
|
|
2242
|
+
const container = containerRef.current;
|
|
2243
|
+
const target = evt.target;
|
|
2244
|
+
if (!container)
|
|
2245
|
+
return;
|
|
2246
|
+
const detailOwner = target instanceof Element ? target.closest('[data-bgrid-detail-owner]') : null;
|
|
2247
|
+
const targetGrid = target instanceof Element ? target.closest('[role="grid"], [role="treegrid"]') : null;
|
|
2248
|
+
if ((detailOwner && container.contains(detailOwner)) ||
|
|
2249
|
+
(targetGrid && targetGrid !== container && container.contains(targetGrid))) {
|
|
2250
|
+
const { clearCellSelection, endCellSelectionDrag } = keyboardRuntimeRef.current;
|
|
2251
|
+
endCellSelectionDrag();
|
|
2252
|
+
clearCellSelection();
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2154
2255
|
const { clearCellSelection, clearCellSelectionOnOutsideClick, endCellSelectionDrag } = keyboardRuntimeRef.current;
|
|
2155
2256
|
if (!clearCellSelectionOnOutsideClick)
|
|
2156
2257
|
return;
|
|
2157
|
-
|
|
2158
|
-
const target = evt.target;
|
|
2159
|
-
if (!container ||
|
|
2160
|
-
(target instanceof Node && container.contains(target)) ||
|
|
2258
|
+
if ((target instanceof Node && container.contains(target)) ||
|
|
2161
2259
|
isPointInsideElement(container, evt.clientX, evt.clientY)) {
|
|
2162
2260
|
return;
|
|
2163
2261
|
}
|
|
@@ -2192,7 +2290,7 @@ function Table(props) {
|
|
|
2192
2290
|
}, className: className, tabIndex: 0, "aria-disabled": disabled ? 'true' : undefined, onFocus: event => {
|
|
2193
2291
|
if (event.target !== event.currentTarget)
|
|
2194
2292
|
return;
|
|
2195
|
-
const gateway = event.currentTarget.
|
|
2293
|
+
const gateway = Array.from(event.currentTarget.querySelectorAll('[data-bgrid-text-editor-gateway="true"]')).find(el => el.closest('[role="grid"], [role="treegrid"]') === event.currentTarget);
|
|
2196
2294
|
if (gateway instanceof HTMLInputElement) {
|
|
2197
2295
|
gateway.focus({ preventScroll: true });
|
|
2198
2296
|
}
|
|
@@ -2206,9 +2304,16 @@ function Table(props) {
|
|
|
2206
2304
|
React.createElement(ScrollContainer, { ref: scrollContainerRef, role: 'rfdg-scroll-container', "data-bgrid-scroll-plane": 'sticky', style: { height: scrollViewportHeight }, onPointerDownCapture: onBodyPointerDownCapture, onPointerOverCapture: onBodyPointerOverCapture, onPointerLeave: onBodyPointerLeave, onContextMenuCapture: event => {
|
|
2207
2305
|
if (disabled)
|
|
2208
2306
|
return;
|
|
2307
|
+
const target = event.target instanceof HTMLElement ? event.target : null;
|
|
2308
|
+
const detailOwner = target?.closest('[data-bgrid-detail-owner]');
|
|
2309
|
+
if (detailOwner && containerRef.current?.contains(detailOwner))
|
|
2310
|
+
return;
|
|
2311
|
+
const targetGrid = target?.closest('[role="grid"], [role="treegrid"]');
|
|
2312
|
+
if (targetGrid && targetGrid !== containerRef.current && containerRef.current?.contains(targetGrid))
|
|
2313
|
+
return;
|
|
2209
2314
|
if (isInteractiveTarget(event.target))
|
|
2210
2315
|
return;
|
|
2211
|
-
const cell = getCellPosition(
|
|
2316
|
+
const cell = getCellPosition(target, containerRef.current);
|
|
2212
2317
|
if (!cell)
|
|
2213
2318
|
return;
|
|
2214
2319
|
if (openCellContextMenu(cell, event.clientX, event.clientY, false)) {
|
|
@@ -2229,8 +2334,8 @@ function Table(props) {
|
|
|
2229
2334
|
React.createElement(TableSummary, { position: 'top' })))),
|
|
2230
2335
|
React.createElement("div", { className: 'bgrid-virtual-row-backdrop', "aria-hidden": 'true', style: {
|
|
2231
2336
|
top: stickyTopHeight,
|
|
2232
|
-
height:
|
|
2233
|
-
marginBottom: -
|
|
2337
|
+
height: effectiveBodyHeight,
|
|
2338
|
+
marginBottom: -effectiveBodyHeight,
|
|
2234
2339
|
} }),
|
|
2235
2340
|
React.createElement("div", { className: 'bgrid-body-scroll-content', style: { height: virtualScrollWindowMetrics.physicalContentHeight } },
|
|
2236
2341
|
frozenRowCount > 0 && (React.createElement("div", { className: 'bgrid-frozen-rows-layer', style: { height: frozenRowsHeight, top: stickyTopHeight }, "data-bgrid-row-band": 'frozen' },
|
|
@@ -2238,7 +2343,7 @@ function Table(props) {
|
|
|
2238
2343
|
React.createElement(TableBodyFrozen, { rowKeyRegistry: rowKeyRegistry, rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top-frozen', quadrant: 'top-left', allowRowReorder: false }),
|
|
2239
2344
|
renderSelectionOverlay('top-left'))),
|
|
2240
2345
|
React.createElement("div", { className: 'bgrid-frozen-rows-main', style: { left: frozenColumnsWidth }, role: 'rfdg-frozen-rows-main' },
|
|
2241
|
-
React.createElement(TableBody, { rowKeyRegistry: rowKeyRegistry, rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top', quadrant: 'top-main', allowRowReorder: false }),
|
|
2346
|
+
React.createElement(TableBody, { rowKeyRegistry: rowKeyRegistry, rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top', quadrant: 'top-main', allowRowReorder: false, viewportWidth: mainViewportWidth }),
|
|
2242
2347
|
renderSelectionOverlay('top-main')))),
|
|
2243
2348
|
React.createElement("div", { className: 'bgrid-scrollable-rows-layer', style: { height: physicalScrollableRowsHeight }, "data-bgrid-row-band": 'scrollable' },
|
|
2244
2349
|
(frozenColumnsWidth ?? 0) > 0 && (React.createElement(FrozenScrollContent, { style: {
|
|
@@ -2254,7 +2359,7 @@ function Table(props) {
|
|
|
2254
2359
|
: visibleScrollableRows.paddingTop,
|
|
2255
2360
|
height: physicalScrollableRowsHeight,
|
|
2256
2361
|
} },
|
|
2257
|
-
React.createElement(TableBody, { rowKeyRegistry: rowKeyRegistry, rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, quadrant: 'body-main' }),
|
|
2362
|
+
React.createElement(TableBody, { rowKeyRegistry: rowKeyRegistry, rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, quadrant: 'body-main', viewportWidth: mainViewportWidth }),
|
|
2258
2363
|
renderSelectionOverlay('body-main')))),
|
|
2259
2364
|
summary && summary.position === 'bottom' && (React.createElement(SummaryContainer, { position: 'bottom', style: { height: summaryHeight, bottom: 0 }, role: 'rfdg-summary-container' },
|
|
2260
2365
|
(frozenColumnsWidth ?? 0) > 0 && (React.createElement(FrozenSummary, { style: { width: frozenColumnsWidth }, role: 'rfdg-frozen-summary' },
|
|
@@ -2275,18 +2380,20 @@ function Table(props) {
|
|
|
2275
2380
|
React.createElement(Loading, { active: loading }))));
|
|
2276
2381
|
}
|
|
2277
2382
|
function getAxisSelectionTarget(target, container) {
|
|
2278
|
-
if (!target || !container)
|
|
2383
|
+
if (!target || !container || !(target instanceof Element))
|
|
2279
2384
|
return undefined;
|
|
2280
2385
|
const lineNumberCell = target.closest('.bgrid-line-number-cell[data-row-index]');
|
|
2281
|
-
if (lineNumberCell instanceof HTMLElement &&
|
|
2386
|
+
if (lineNumberCell instanceof HTMLElement && lineNumberCell.closest('[role="grid"], [role="treegrid"]') === container) {
|
|
2282
2387
|
const rowIndex = Number(lineNumberCell.dataset.rowIndex);
|
|
2283
2388
|
if (Number.isFinite(rowIndex)) {
|
|
2284
2389
|
return { axis: 'row', startIndex: rowIndex, endIndex: rowIndex };
|
|
2285
2390
|
}
|
|
2286
2391
|
}
|
|
2287
2392
|
const headerCell = target.closest('[data-header-cell-type][data-column-index][data-bgrid-axis-selectable="true"]');
|
|
2288
|
-
if (!(headerCell instanceof HTMLTableCellElement) ||
|
|
2393
|
+
if (!(headerCell instanceof HTMLTableCellElement) ||
|
|
2394
|
+
headerCell.closest('[role="grid"], [role="treegrid"]') !== container) {
|
|
2289
2395
|
return undefined;
|
|
2396
|
+
}
|
|
2290
2397
|
if (target.closest('.bgrid-col-resizer, .bgrid-toolbox-trigger-btn'))
|
|
2291
2398
|
return undefined;
|
|
2292
2399
|
if (headerCell.classList.contains('drag-item') && target.closest('.bgrid-column-drag-handle'))
|
|
@@ -2323,8 +2430,10 @@ function updateAxisSelectionDragRange(dragState, activeRange) {
|
|
|
2323
2430
|
return nextRanges;
|
|
2324
2431
|
}
|
|
2325
2432
|
function getCellPosition(target, container) {
|
|
2326
|
-
|
|
2327
|
-
|
|
2433
|
+
if (!target || !(target instanceof Element))
|
|
2434
|
+
return undefined;
|
|
2435
|
+
const cell = target.closest('td[data-bgrid-cell="true"]');
|
|
2436
|
+
if (!(cell instanceof HTMLElement) || cell.closest('[role="grid"], [role="treegrid"]') !== container)
|
|
2328
2437
|
return undefined;
|
|
2329
2438
|
const rowIndex = Number(cell.dataset.rowIndex);
|
|
2330
2439
|
const columnIndex = Number(cell.dataset.columnIndex);
|
|
@@ -5,6 +5,7 @@ import TableColGroup from './TableColGroup';
|
|
|
5
5
|
import TableColGroupFrozen from './TableColGroupFrozen';
|
|
6
6
|
import { getCellValueByRowKey, getRowReorderOffset, getRowReorderRole, useBodyData, } from '../utils';
|
|
7
7
|
import { TableBodyRow } from './TableBodyRow';
|
|
8
|
+
import { MasterDetailRow } from './MasterDetailCell';
|
|
8
9
|
import { BGridDataItemStatus } from '../types';
|
|
9
10
|
export function getVisibleColumnRange(columns, firstScrollableColumnIndex, scrollLeft, viewportWidth) {
|
|
10
11
|
const lastColumnIndex = columns.length - 1;
|
|
@@ -102,7 +103,7 @@ function getRowReactKey(item, sourceIndex, rowKey, registry) {
|
|
|
102
103
|
}
|
|
103
104
|
return `bgrid-row-source:${sourceIndex}`;
|
|
104
105
|
}
|
|
105
|
-
function TableBody({ rowKeyRegistry, region = 'main', rowRange, style, role, quadrant, allowRowReorder = true, onRowReorderPointerDown, onRowReorderKeyDown, rowHeightMetrics, }) {
|
|
106
|
+
function TableBody({ rowKeyRegistry, region = 'main', rowRange, style, role, quadrant, allowRowReorder = true, onRowReorderPointerDown, onRowReorderKeyDown, rowHeightMetrics, viewportWidth, }) {
|
|
106
107
|
const isLeftRegion = region === 'left';
|
|
107
108
|
// [Selector Group 1] Scroll & Dimensions - 스크롤 및 차원
|
|
108
109
|
const { scrollTop, scrollLeft, width, frozenColumnsWidth, itemHeight, itemPadding, displayItemCount } = useAppStore(useShallow(s => ({
|
|
@@ -225,7 +226,10 @@ function TableBody({ rowKeyRegistry, region = 'main', rowRange, style, role, qua
|
|
|
225
226
|
const isRowEditing = cellInteractionSession?.kind === 'editor' &&
|
|
226
227
|
(cellInteractionSession.cell.rowIndex === ri || cellInteractionSession.hostCell.rowIndex === ri);
|
|
227
228
|
const rowReactKey = getRowReactKey(item, sourceIndex, rowKey, rowKeyRegistry);
|
|
228
|
-
|
|
229
|
+
const detailHeight = rowHeightMetrics?.detailHeights?.[ri] ?? 0;
|
|
230
|
+
return (React.createElement(React.Fragment, { key: rowReactKey },
|
|
231
|
+
React.createElement(TableBodyRow, { item: item, data: data, ri: ri, sourceIndex: sourceIndex, columns: columns, startCIdx: startCIdx, endCIdx: endCIdx, frozenColumnIndex: frozenColumnIndex, isLeftRegion: isLeftRegion, showLineNumber: showLineNumber ?? false, hasRowChecked: hasRowChecked, isRadio: Boolean(isRadio), checked: checkedAll === true || checkedIndexesMap.get(sourceIndex), rowCheckedDisabled: Boolean(disabled || rowChecked?.disabled?.(sourceIndex, item)), rowStatus: rowStatus, active: active, className: className, resolvedRowHeight: resolvedRowHeight, itemHeight: itemHeight, itemPadding: itemPadding, editable: Boolean(editable), disabled: Boolean(disabled), editTrigger: editTrigger, hasOnClick: hasOnClick, cellMergeOptions: cellMergeOptions, mergeColumns: mergeColumns, odd: !mergeColumns ? ri % 2 === 0 : undefined, variant: variant, rowReorderEnabled: rowReorderEnabled, rowReorderRole: rowReorderRole, rowReorderPhase: reorderingInfo?.phase, rowReorderDirection: rowReorderDirection, rowReorderOffset: rowReorderOffset, reorder: reorder, reorderingInfo: reorderingInfo, searchMatchTokens: searchMatchTokens, currentSearchToken: currentSearchToken, isRowEditing: isRowEditing, cellInteractionSession: isRowEditing ? cellInteractionSession : undefined, handleClick: handleClick, setEditItem: setEditItem, setItemValue: setItemValue, handleMoveEditFocus: handleMoveEditFocus, handleChangeChecked: handleChangeChecked, handleChangeCheckedRadio: handleChangeCheckedRadio, getRowSpan: getRowSpan, onRowReorderPointerDown: onRowReorderPointerDown, onRowReorderKeyDown: onRowReorderKeyDown }),
|
|
232
|
+
detailHeight > 0 && (React.createElement(MasterDetailRow, { item: item, sourceIndex: sourceIndex, visibleIndex: ri, detailHeight: detailHeight, isLeftRegion: isLeftRegion, viewportWidth: viewportWidth ?? Math.max(width - (frozenColumnsWidth ?? 0), 0), frozenColumnsWidth: frozenColumnsWidth ?? 0, colSpan: isLeftRegion ? Math.max(frozenColumnIndex, 1) : Math.max(columns.length - frozenColumnIndex, 1) }))));
|
|
229
233
|
}),
|
|
230
234
|
endNumber - startIdx < 1 &&
|
|
231
235
|
(isLeftRegion ? (React.createElement(NoDataTr, { itemHeight: itemHeight, itemPadding: itemPadding })) : (React.createElement(NoDataTr, { itemHeight: itemHeight, itemPadding: itemPadding }, msg?.emptyList ? (React.createElement(React.Fragment, null,
|
|
@@ -3,6 +3,7 @@ import { PluginCellEditor } from './PluginCellEditor';
|
|
|
3
3
|
import { CellEditorIcon } from './CellEditorIcon';
|
|
4
4
|
import { CheckboxCellEditor } from './CheckboxCellEditor';
|
|
5
5
|
import { TreeCell } from './TreeCell';
|
|
6
|
+
import { MasterDetailCell } from './MasterDetailCell';
|
|
6
7
|
function Cell({ index, hostIndex = index, columnIndex, column, item, valueByRowKey, handleSave, handleCancel, handleMove, editable, cellEditable, interactionEditing = false, editSession, }) {
|
|
7
8
|
const isPluginEditorActive = Boolean(editable && editSession && column.editor?.type === 'plugin');
|
|
8
9
|
let content;
|
|
@@ -37,7 +38,7 @@ function Cell({ index, hostIndex = index, columnIndex, column, item, valueByRowK
|
|
|
37
38
|
content = renderSafeCellValue(valueByRowKey);
|
|
38
39
|
}
|
|
39
40
|
return (React.createElement("div", { className: isPluginEditorActive ? 'bgrid-cell-content bgrid-cell-content-plugin-editor' : 'bgrid-cell-content' },
|
|
40
|
-
React.createElement("div", { className: 'bgrid-cell-value' }, column.treeCell ? (React.createElement(TreeCell, { column: column, item: item }, content)) : (content)),
|
|
41
|
+
React.createElement("div", { className: 'bgrid-cell-value' }, column.treeCell ? (React.createElement(TreeCell, { column: column, item: item }, content)) : column.masterDetailCell ? (React.createElement(MasterDetailCell, { column: column, item: item, sourceIndex: index }, content)) : (content)),
|
|
41
42
|
column.editorIcon && column.editor?.type !== 'checkbox' && cellEditable && (React.createElement(CellEditorIcon, { hostCell: { rowIndex: hostIndex, columnIndex }, index: index, columnIndex: columnIndex, column: column, item: item, value: valueByRowKey, editing: interactionEditing }))));
|
|
42
43
|
}
|
|
43
44
|
function renderSafeCellValue(value, preserveRenderableArrays = false) {
|