beautiful-grid 1.0.8 → 1.0.10

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 (45) hide show
  1. package/README.md +48 -0
  2. package/cjs/BGrid.js +8 -6
  3. package/cjs/components/Table.js +85 -22
  4. package/cjs/components/TableBody.js +10 -9
  5. package/cjs/components/TableBodyFrozen.js +1 -1
  6. package/cjs/components/TableHeadColumn.js +12 -11
  7. package/cjs/components/toolbox/ToolboxColumnVisibilitySection.js +8 -10
  8. package/cjs/components/toolbox/ToolboxCustomSection.js +4 -1
  9. package/cjs/components/toolbox/ToolboxNumberFilterSection.js +20 -18
  10. package/cjs/components/toolbox/ToolboxSortSection.js +6 -5
  11. package/cjs/components/toolbox/ToolboxTextFilterSection.js +11 -9
  12. package/cjs/components/toolbox/ToolboxValueFilterSection.js +20 -20
  13. package/cjs/utils/cellSelectionGeometry.js +18 -7
  14. package/cjs/utils/coordinate.js +15 -10
  15. package/cjs/utils/getVisibleScrollableRowRange.js +25 -6
  16. package/cjs/utils/index.js +1 -0
  17. package/cjs/utils/rowHeightMetrics.js +61 -0
  18. package/esm/BGrid.js +6 -3
  19. package/esm/components/Table.js +82 -21
  20. package/esm/components/TableBody.js +5 -4
  21. package/esm/components/TableBodyFrozen.js +1 -1
  22. package/esm/components/TableHeadColumn.js +5 -4
  23. package/esm/components/toolbox/ToolboxColumnVisibilitySection.js +7 -9
  24. package/esm/components/toolbox/ToolboxCustomSection.js +3 -1
  25. package/esm/components/toolbox/ToolboxNumberFilterSection.js +15 -14
  26. package/esm/components/toolbox/ToolboxSortSection.js +5 -4
  27. package/esm/components/toolbox/ToolboxTextFilterSection.js +8 -7
  28. package/esm/components/toolbox/ToolboxValueFilterSection.js +13 -15
  29. package/esm/utils/cellSelectionGeometry.js +16 -7
  30. package/esm/utils/coordinate.js +8 -3
  31. package/esm/utils/getVisibleScrollableRowRange.js +24 -6
  32. package/esm/utils/index.js +1 -0
  33. package/esm/utils/rowHeightMetrics.js +56 -0
  34. package/package.json +1 -1
  35. package/style.css +4 -0
  36. package/types/BGrid.d.ts +1 -1
  37. package/types/components/Table.d.ts +2 -0
  38. package/types/components/TableBody.d.ts +5 -2
  39. package/types/components/TableBodyFrozen.d.ts +2 -0
  40. package/types/types.d.ts +93 -0
  41. package/types/utils/cellSelectionGeometry.d.ts +2 -1
  42. package/types/utils/coordinate.d.ts +2 -1
  43. package/types/utils/getVisibleScrollableRowRange.d.ts +3 -1
  44. package/types/utils/index.d.ts +1 -0
  45. package/types/utils/rowHeightMetrics.d.ts +12 -0
package/README.md CHANGED
@@ -18,14 +18,34 @@
18
18
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/axisj/beautiful-grid/pulls)
19
19
  [![Docs](https://img.shields.io/badge/docs-bgrid.axisj.com-blue?logo=googlechrome&logoColor=white)](https://bgrid.axisj.com)
20
20
 
21
+ <p align="center">
22
+ <a href="https://bgrid.axisj.com">
23
+ <img src="https://raw.githubusercontent.com/axisj/beautiful-grid/main/site/public/og-image-en.png" alt="BeautifulGrid — Beautiful, Powerful Open-Source React Data Grid" width="100%" />
24
+ </a>
25
+ </p>
26
+
27
+ <p align="center">
28
+ <a href="https://bgrid.axisj.com"><strong>🌐 Interactive Docs & Live Demos</strong></a>&nbsp;&nbsp;•&nbsp;&nbsp;
29
+ <a href="https://youtu.be/BBq4hPsNDNI"><strong>▶️ Watch 1-Min Walkthrough (YouTube)</strong></a>
30
+ </p>
31
+
21
32
  BeautifulGrid is a high-performance, feature-packed, and beautifully designed open-source React Data Grid for data-heavy business applications. It combines zero-runtime-CSS styling with virtual scrolling, spreadsheet-like cell selection and clipboard operations, built-in and plugin cell editing, multi-level grouped headers, filtering & sorting toolboxes, recoverable column visibility, server/client pagination, pivot table transforms, row reordering, and flexible theming.
22
33
 
23
34
  Explore live interactive examples and in-depth documentation at [bgrid.axisj.com](https://bgrid.axisj.com).
24
35
 
25
36
  ---
26
37
 
38
+ ## Video Walkthrough
39
+
40
+ Watch 1-million row virtual scrolling, keyboard navigation, and interactive cell editing in action (1 min):
41
+
42
+ [![BeautifulGrid 1-Minute Walkthrough](https://img.youtube.com/vi/BBq4hPsNDNI/maxresdefault.jpg)](https://youtu.be/BBq4hPsNDNI)
43
+
44
+ ---
45
+
27
46
  ## Table of Contents
28
47
 
48
+ - [Video Walkthrough](#video-walkthrough)
29
49
  - [Install](#install)
30
50
  - [Quick Start](#quick-start)
31
51
  - [Core Concepts](#core-concepts)
@@ -180,6 +200,33 @@ export default function OrderGridPage() {
180
200
  5. **No Runtime CSS-in-JS**:
181
201
  - High performance and zero runtime overhead using static `.bgrid-*` classes and `--bgrid-*` CSS custom properties.
182
202
 
203
+ ### Variable Row Heights
204
+
205
+ Use `getRowHeight(row, index)` when rows need explicit, data-driven heights. The callback receives the row's
206
+ `values` object and its current displayed index (after client-side sorting or filtering), and returns the complete
207
+ row height in pixels:
208
+
209
+ ```tsx
210
+ <BGrid
211
+ itemHeight={20}
212
+ itemPadding={5}
213
+ getRowHeight={(row, index) => {
214
+ if (row.type === 'group') return 48;
215
+ if (index === 0) return 40;
216
+ return 30;
217
+ }}
218
+ {...props}
219
+ />
220
+ ```
221
+
222
+ BeautifulGrid caches all returned heights and cumulative offsets when the displayed data, callback, or fixed-height
223
+ fallback changes. Scrolling then finds rows with binary search and does not call `getRowHeight` again. Keep the
224
+ callback reference stable (for example with `useCallback`) to avoid rebuilding the cache on parent renders.
225
+
226
+ Automatic content-based row height measurement is intentionally not supported, because DOM measurement would make
227
+ large virtualized datasets less predictable. When `getRowHeight` is omitted—or returns a non-finite or non-positive
228
+ value—the existing `itemHeight + itemPadding * 2` fixed height is used.
229
+
183
230
  ---
184
231
 
185
232
  ## Styling & Theming
@@ -920,6 +967,7 @@ Below is a categorized reference of `<BGrid>` props. For exact TypeScript types,
920
967
  | `summaryHeight` | `number` | `30` | Summary row height in pixels. |
921
968
  | `itemHeight` | `number` | `15` | Body row content height. |
922
969
  | `itemPadding` | `number` | `7` | Body row top/bottom padding (total row height = `itemHeight + itemPadding * 2`). |
970
+ | `getRowHeight` | `(row: T, index: number) => number` | — | Complete rendered height for each displayed row. Invalid values fall back to `itemHeight + itemPadding * 2`. |
923
971
  | `frozenColumnIndex` | `number` | `0` | Pinned column boundary index (columns `< frozenColumnIndex` are fixed). |
924
972
  | `frozenRowCount` | `number` | `0` | Number of leading rows pinned below the top summary row. |
925
973
  | `showLineNumber` | `boolean` | `false` | Shows row index numbers and reorder handles on the left. |
package/cjs/BGrid.js CHANGED
@@ -92,7 +92,7 @@ function computeModelColumns(columns, frozenColumnIndex, duplicateToolboxColumnI
92
92
  }
93
93
  function BGrid(_a) {
94
94
  var _b, _c, _d;
95
- var ref = _a.ref, width = _a.width, height = _a.height, _e = _a.headerHeight, headerHeight = _e === void 0 ? 30 : _e, footerHeight = _a.footerHeight, _f = _a.summaryHeight, summaryHeight = _f === void 0 ? 30 : _f, _g = _a.itemHeight, itemHeight = _g === void 0 ? 15 : _g, _h = _a.itemPadding, itemPadding = _h === void 0 ? 7 : _h, columns = _a.columns, columnsGroup = _a.columnsGroup, columnGroups = _a.columnGroups, onChangeColumns = _a.onChangeColumns, _j = _a.frozenColumnIndex, frozenColumnIndex = _j === void 0 ? 0 : _j, _k = _a.frozenRowCount, frozenRowCount = _k === void 0 ? 0 : _k, _l = _a.data, data = _l === void 0 ? [] : _l, page = _a.page, scrollbar = _a.scrollbar, status = _a.status, pagination = _a.pagination, bottomBarHeight = _a.bottomBarHeight, _m = _a.scrollTop, scrollTop = _m === void 0 ? 0 : _m, _o = _a.scrollLeft, scrollLeft = _o === void 0 ? 0 : _o, className = _a.className, style = _a.style, rowChecked = _a.rowChecked, sort = _a.sort, onClick = _a.onClick, _p = _a.loading, loading = _p === void 0 ? false : _p, spinning = _a.spinning, disabled = _a.disabled, rowKey = _a.rowKey, selectedRowKey = _a.selectedRowKey, editable = _a.editable, onChangeData = _a.onChangeData, showLineNumber = _a.showLineNumber, msg = _a.msg, getRowClassName = _a.getRowClassName, _q = _a.editTrigger, editTrigger = _q === void 0 ? 'dblclick' : _q, cellMergeOptions = _a.cellMergeOptions, cellSelectionOptions = _a.cellSelectionOptions, cellNavigationOptions = _a.cellNavigationOptions, variant = _a.variant, summary = _a.summary, columnSortable = _a.columnSortable, reorder = _a.reorder, pivot = _a.pivot, dataControl = _a.dataControl, icons = _a.icons, columnVisibility = _a.columnVisibility, searchOptions = _a.searchOptions, contextMenuOptions = _a.contextMenuOptions;
95
+ var ref = _a.ref, width = _a.width, height = _a.height, _e = _a.headerHeight, headerHeight = _e === void 0 ? 30 : _e, footerHeight = _a.footerHeight, _f = _a.summaryHeight, summaryHeight = _f === void 0 ? 30 : _f, _g = _a.itemHeight, itemHeight = _g === void 0 ? 15 : _g, _h = _a.itemPadding, itemPadding = _h === void 0 ? 7 : _h, getRowHeight = _a.getRowHeight, columns = _a.columns, columnsGroup = _a.columnsGroup, columnGroups = _a.columnGroups, onChangeColumns = _a.onChangeColumns, _j = _a.frozenColumnIndex, frozenColumnIndex = _j === void 0 ? 0 : _j, _k = _a.frozenRowCount, frozenRowCount = _k === void 0 ? 0 : _k, _l = _a.data, data = _l === void 0 ? [] : _l, page = _a.page, scrollbar = _a.scrollbar, status = _a.status, pagination = _a.pagination, bottomBarHeight = _a.bottomBarHeight, _m = _a.scrollTop, scrollTop = _m === void 0 ? 0 : _m, _o = _a.scrollLeft, scrollLeft = _o === void 0 ? 0 : _o, className = _a.className, style = _a.style, rowChecked = _a.rowChecked, sort = _a.sort, onClick = _a.onClick, _p = _a.loading, loading = _p === void 0 ? false : _p, spinning = _a.spinning, disabled = _a.disabled, rowKey = _a.rowKey, selectedRowKey = _a.selectedRowKey, editable = _a.editable, onChangeData = _a.onChangeData, showLineNumber = _a.showLineNumber, msg = _a.msg, getRowClassName = _a.getRowClassName, _q = _a.editTrigger, editTrigger = _q === void 0 ? 'dblclick' : _q, cellMergeOptions = _a.cellMergeOptions, cellSelectionOptions = _a.cellSelectionOptions, cellNavigationOptions = _a.cellNavigationOptions, variant = _a.variant, summary = _a.summary, columnSortable = _a.columnSortable, reorder = _a.reorder, pivot = _a.pivot, dataControl = _a.dataControl, icons = _a.icons, columnVisibility = _a.columnVisibility, searchOptions = _a.searchOptions, contextMenuOptions = _a.contextMenuOptions;
96
96
  var warnedSearchControlledRef = React.useRef({
97
97
  open: false,
98
98
  query: false,
@@ -397,6 +397,7 @@ function BGrid(_a) {
397
397
  };
398
398
  }, [queryColumns, resolvedData, resolvedDataControl === null || resolvedDataControl === void 0 ? void 0 : resolvedDataControl.mode, resolvedDataQuery, resolvedRowKey]);
399
399
  var displayData = processedResult.data;
400
+ var rowHeightMetrics = React.useMemo(function () { return (0, utils_1.createRowHeightMetrics)(displayData, itemHeight + itemPadding * 2, getRowHeight); }, [displayData, getRowHeight, itemHeight, itemPadding]);
400
401
  var resolvedFrozenRowCount = pivotEnabled
401
402
  ? 0
402
403
  : Math.min(Math.max(Math.floor(frozenRowCount), 0), displayData.length);
@@ -455,7 +456,7 @@ function BGrid(_a) {
455
456
  }
456
457
  }, [bottomBarHeight, footerHeight]);
457
458
  var initialStoreState = React.useMemo(function () {
458
- var _a, _b;
459
+ var _a, _b, _c;
459
460
  var initialWidth = width !== undefined ? Math.max(width, 100) : 0;
460
461
  var initialHeight = height !== undefined ? Math.max(height, 100) : 0;
461
462
  var containerBorderWidth = 1;
@@ -489,7 +490,7 @@ function BGrid(_a) {
489
490
  itemPadding: itemPadding,
490
491
  frozenColumnIndex: resolvedFrozenColumnIndex,
491
492
  frozenRowCount: resolvedFrozenRowCount,
492
- frozenRowsHeight: resolvedFrozenRowCount * (itemHeight + itemPadding * 2),
493
+ frozenRowsHeight: (_a = rowHeightMetrics.offsets[resolvedFrozenRowCount]) !== null && _a !== void 0 ? _a : resolvedFrozenRowCount * (itemHeight + itemPadding * 2),
493
494
  frozenColumnsWidth: (0, utils_1.getFrozenColumnsWidth)({
494
495
  showLineNumber: resolvedShowLineNumber,
495
496
  rowChecked: resolvedRowChecked,
@@ -497,7 +498,7 @@ function BGrid(_a) {
497
498
  frozenColumnIndex: resolvedFrozenColumnIndex,
498
499
  columns: computedColumns,
499
500
  dataLength: displayData.length,
500
- reorderable: (_a = resolvedReorder === null || resolvedReorder === void 0 ? void 0 : resolvedReorder.enabled) !== null && _a !== void 0 ? _a : false,
501
+ reorderable: (_b = resolvedReorder === null || resolvedReorder === void 0 ? void 0 : resolvedReorder.enabled) !== null && _b !== void 0 ? _b : false,
501
502
  }),
502
503
  columns: computedColumns,
503
504
  columnsGroup: visibilityProjection.columnsGroup,
@@ -520,7 +521,7 @@ function BGrid(_a) {
520
521
  searchOptions: resolvedSearchOptions,
521
522
  contextMenuOptions: resolvedContextMenuOptions,
522
523
  page: resolvedPage,
523
- displayPaginationLength: resolvedPage ? (_b = resolvedPage.displayPaginationLength) !== null && _b !== void 0 ? _b : 5 : 0,
524
+ displayPaginationLength: resolvedPage ? (_c = resolvedPage.displayPaginationLength) !== null && _c !== void 0 ? _c : 5 : 0,
524
525
  loading: loading,
525
526
  disabled: resolvedDisabled,
526
527
  spinning: spinning,
@@ -558,6 +559,7 @@ function BGrid(_a) {
558
559
  summaryHeight,
559
560
  itemHeight,
560
561
  itemPadding,
562
+ rowHeightMetrics,
561
563
  resolvedPage,
562
564
  resolvedSummary,
563
565
  checkedIndexesMap,
@@ -609,7 +611,7 @@ function BGrid(_a) {
609
611
  onChangeColumns: resolvedOnChangeColumns, width: width, height: height, className: className, style: style, loading: loading, disabled: resolvedDisabled, spinning: spinning, scrollLeft: scrollLeft, scrollTop: scrollTop, headerHeight: headerHeight, footerHeight: footerHeight, bottomBarHeight: resolvedBottomBarHeight,
610
612
  scrollbar: resolvedScrollbar,
611
613
  status: resolvedStatus,
612
- pagination: resolvedPagination, summaryHeight: summaryHeight, itemHeight: itemHeight, itemPadding: itemPadding, frozenColumnIndex: resolvedFrozenColumnIndex,
614
+ pagination: resolvedPagination, summaryHeight: summaryHeight, itemHeight: itemHeight, itemPadding: itemPadding, rowHeightMetrics: rowHeightMetrics, frozenColumnIndex: resolvedFrozenColumnIndex,
613
615
  frozenRowCount: resolvedFrozenRowCount,
614
616
  rowChecked: resolvedRowChecked, checkedIndexesMap: checkedIndexesMap, sort: resolvedSort, sortParams: sortParams, dataQuery: resolvedDataQuery,
615
617
  dataControl: resolvedDataControl, icons: icons, columnVisibilityState: columnVisibilityState, searchOptions: resolvedSearchOptions,
@@ -321,10 +321,12 @@ function Table(props) {
321
321
  syncActiveCellToBounds: s.syncActiveCellToBounds,
322
322
  }); })), setCellSelectionRanges = _19.setCellSelectionRanges, setCellSelecting = _19.setCellSelecting, clearCellSelection = _19.clearCellSelection, setActiveCell = _19.setActiveCell, moveActiveCell = _19.moveActiveCell, setCellNavigationOptions = _19.setCellNavigationOptions, syncActiveCellToBounds = _19.syncActiveCellToBounds;
323
323
  var trHeight = itemHeight + itemPadding * 2;
324
+ var rowHeightMetrics = props.rowHeightMetrics;
325
+ var variableRowOffsets = rowHeightMetrics.variable ? rowHeightMetrics.offsets : undefined;
324
326
  var scrollableBodyHeight = Math.max(contentBodyHeight - frozenRowsHeight, 0);
325
327
  var scrollOverscanRows = Math.max(KEYBOARD_NAVIGATION_ROW_WINDOW_SIZE, Math.ceil(scrollableBodyHeight / Math.max(trHeight, 1)));
326
328
  var mainViewportWidth = Math.max(width - (frozenColumnsWidth !== null && frozenColumnsWidth !== void 0 ? frozenColumnsWidth : 0), 0);
327
- var logicalBodyContentHeight = data.length * trHeight;
329
+ var logicalBodyContentHeight = rowHeightMetrics.totalHeight;
328
330
  var virtualScrollWindowMetrics = React.useMemo(function () {
329
331
  return (0, utils_1.getVirtualScrollWindowMetrics)({
330
332
  logicalContentHeight: logicalBodyContentHeight,
@@ -400,11 +402,21 @@ function Table(props) {
400
402
  columns: columns,
401
403
  rowCount: data.length,
402
404
  rowHeight: trHeight,
405
+ rowOffsets: variableRowOffsets,
403
406
  frozenColumnCount: (_a = props.frozenColumnIndex) !== null && _a !== void 0 ? _a : 0,
404
407
  frozenRowCount: frozenRowCount,
405
408
  frozenColumnsWidth: frozenColumnsWidth !== null && frozenColumnsWidth !== void 0 ? frozenColumnsWidth : 0,
406
409
  });
407
- }, [cellSelectionRanges, columns, data.length, frozenColumnsWidth, frozenRowCount, props.frozenColumnIndex, trHeight]);
410
+ }, [
411
+ cellSelectionRanges,
412
+ columns,
413
+ data.length,
414
+ frozenColumnsWidth,
415
+ frozenRowCount,
416
+ props.frozenColumnIndex,
417
+ trHeight,
418
+ variableRowOffsets,
419
+ ]);
408
420
  var activeFragments = React.useMemo(function () {
409
421
  var _a;
410
422
  return (0, cellSelectionGeometry_1.getCellSelectionFragments)({
@@ -412,11 +424,21 @@ function Table(props) {
412
424
  columns: columns,
413
425
  rowCount: data.length,
414
426
  rowHeight: trHeight,
427
+ rowOffsets: variableRowOffsets,
415
428
  frozenColumnCount: (_a = props.frozenColumnIndex) !== null && _a !== void 0 ? _a : 0,
416
429
  frozenRowCount: frozenRowCount,
417
430
  frozenColumnsWidth: frozenColumnsWidth !== null && frozenColumnsWidth !== void 0 ? frozenColumnsWidth : 0,
418
431
  });
419
- }, [activeCellRanges, columns, data.length, frozenColumnsWidth, frozenRowCount, props.frozenColumnIndex, trHeight]);
432
+ }, [
433
+ activeCellRanges,
434
+ columns,
435
+ data.length,
436
+ frozenColumnsWidth,
437
+ frozenRowCount,
438
+ props.frozenColumnIndex,
439
+ trHeight,
440
+ variableRowOffsets,
441
+ ]);
420
442
  var activeOverlayFill = activeCellSelected;
421
443
  var activeOverlayRing = !!activeCell && !hasMultiCellSelection;
422
444
  var renderSelectionOverlay = function (quadrant) {
@@ -440,6 +462,7 @@ function Table(props) {
440
462
  overscan: ((_a = props.reorder) === null || _a === void 0 ? void 0 : _a.enabled) ? 1 : scrollOverscanRows,
441
463
  leadingOverscan: ((_b = props.reorder) === null || _b === void 0 ? void 0 : _b.enabled) ? 0 : scrollOverscanRows,
442
464
  windowSize: ((_c = props.reorder) === null || _c === void 0 ? void 0 : _c.enabled) ? 1 : KEYBOARD_NAVIGATION_ROW_WINDOW_SIZE,
465
+ rowOffsets: variableRowOffsets,
443
466
  });
444
467
  }, [
445
468
  data.length,
@@ -449,6 +472,7 @@ function Table(props) {
449
472
  scrollTop,
450
473
  scrollableBodyHeight,
451
474
  trHeight,
475
+ variableRowOffsets,
452
476
  ]);
453
477
  var frozenRowRange = React.useMemo(function () { return ({ startRowIndex: 0, endRowIndex: frozenRowCount }); }, [frozenRowCount]);
454
478
  var scrollableRowRange = React.useMemo(function () { return ({
@@ -640,6 +664,7 @@ function Table(props) {
640
664
  frozenRowsHeight: frozenRowsHeight,
641
665
  scrollTop: scrollTop,
642
666
  trHeight: trHeight,
667
+ rowOffsets: variableRowOffsets,
643
668
  });
644
669
  (0, react_1.useEffect)(function () {
645
670
  var _a;
@@ -652,6 +677,7 @@ function Table(props) {
652
677
  frozenRowsHeight: frozenRowsHeight,
653
678
  scrollTop: scrollTop,
654
679
  trHeight: trHeight,
680
+ rowOffsets: variableRowOffsets,
655
681
  };
656
682
  }, [
657
683
  columns,
@@ -662,6 +688,7 @@ function Table(props) {
662
688
  frozenRowsHeight,
663
689
  scrollTop,
664
690
  trHeight,
691
+ variableRowOffsets,
665
692
  ]);
666
693
  var markScrollActive = (0, react_1.useCallback)(function () {
667
694
  var _a;
@@ -765,6 +792,7 @@ function Table(props) {
765
792
  frozenRowCount: frozenRowCount,
766
793
  columns: columns,
767
794
  rowHeight: trHeight,
795
+ rowOffsets: variableRowOffsets,
768
796
  verticalScrollState: logicalVerticalScrollState,
769
797
  viewportInsets: viewportInsets,
770
798
  });
@@ -782,6 +810,7 @@ function Table(props) {
782
810
  stickyFixedHeight,
783
811
  frozenRowsHeight,
784
812
  trHeight,
813
+ variableRowOffsets,
785
814
  ]);
786
815
  var clearHoveredRow = (0, react_1.useCallback)(function () {
787
816
  if (!containerRef.current || hoveredRowIndexesRef.current.length === 0)
@@ -1525,12 +1554,20 @@ function Table(props) {
1525
1554
  ]);
1526
1555
  // [Group 4-1] Frozen rows. A top summary remains a separate band above this body area.
1527
1556
  (0, react_1.useEffect)(function () {
1528
- var _a, _b, _c;
1557
+ var _a, _b, _c, _d;
1529
1558
  var rowCount = (_b = (_a = props.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : data.length;
1530
1559
  var nextFrozenRowCount = Math.min(Math.max(Math.floor((_c = props.frozenRowCount) !== null && _c !== void 0 ? _c : 0), 0), rowCount);
1531
1560
  setFrozenRowCount(nextFrozenRowCount);
1532
- setFrozenRowsHeight(nextFrozenRowCount * trHeight);
1533
- }, [data.length, (_f = props.data) === null || _f === void 0 ? void 0 : _f.length, props.frozenRowCount, setFrozenRowCount, setFrozenRowsHeight, trHeight]);
1561
+ setFrozenRowsHeight((_d = rowHeightMetrics.offsets[nextFrozenRowCount]) !== null && _d !== void 0 ? _d : nextFrozenRowCount * trHeight);
1562
+ }, [
1563
+ data.length,
1564
+ (_f = props.data) === null || _f === void 0 ? void 0 : _f.length,
1565
+ props.frozenRowCount,
1566
+ rowHeightMetrics,
1567
+ setFrozenRowCount,
1568
+ setFrozenRowsHeight,
1569
+ trHeight,
1570
+ ]);
1534
1571
  // [Group 5] Data & columns
1535
1572
  (0, react_1.useEffect)(function () {
1536
1573
  if (props.data !== undefined &&
@@ -1763,6 +1800,7 @@ function Table(props) {
1763
1800
  commitScroll(nextTop, nextLeft);
1764
1801
  }, [commitScroll, data, props.data, props.scrollLeft, props.scrollTop]);
1765
1802
  React.useLayoutEffect(function () {
1803
+ var _a, _b, _c;
1766
1804
  if (!rowScrollRequest)
1767
1805
  return;
1768
1806
  // Prop data reaches the per-grid store in an effect. Wait for that render
@@ -1775,14 +1813,16 @@ function Table(props) {
1775
1813
  return;
1776
1814
  if (scrollableBodyHeight <= 0)
1777
1815
  return;
1778
- var rowTop = (rowIndex - frozenRowCount) * trHeight;
1779
- var rowBottom = rowTop + trHeight;
1780
- var _a = latestScrollRef.current, top = _a.top, left = _a.left;
1816
+ var frozenOffset = (_a = rowHeightMetrics.offsets[frozenRowCount]) !== null && _a !== void 0 ? _a : frozenRowCount * trHeight;
1817
+ var rowTop = ((_b = rowHeightMetrics.offsets[rowIndex]) !== null && _b !== void 0 ? _b : rowIndex * trHeight) - frozenOffset;
1818
+ var rowHeight = (_c = rowHeightMetrics.heights[rowIndex]) !== null && _c !== void 0 ? _c : trHeight;
1819
+ var rowBottom = rowTop + rowHeight;
1820
+ var _d = latestScrollRef.current, top = _d.top, left = _d.left;
1781
1821
  var nextTop = top;
1782
1822
  if (align === 'start')
1783
1823
  nextTop = rowTop;
1784
1824
  else if (align === 'center')
1785
- nextTop = rowTop - (scrollableBodyHeight - trHeight) / 2;
1825
+ nextTop = rowTop - (scrollableBodyHeight - rowHeight) / 2;
1786
1826
  else if (align === 'end')
1787
1827
  nextTop = rowBottom - scrollableBodyHeight;
1788
1828
  else if (rowTop < top)
@@ -1790,7 +1830,16 @@ function Table(props) {
1790
1830
  else if (rowBottom > top + scrollableBodyHeight)
1791
1831
  nextTop = rowBottom - scrollableBodyHeight;
1792
1832
  commitScroll(nextTop, left);
1793
- }, [commitScroll, data, frozenRowCount, props.data, rowScrollRequest, scrollableBodyHeight, trHeight]);
1833
+ }, [
1834
+ commitScroll,
1835
+ data,
1836
+ frozenRowCount,
1837
+ props.data,
1838
+ rowHeightMetrics,
1839
+ rowScrollRequest,
1840
+ scrollableBodyHeight,
1841
+ trHeight,
1842
+ ]);
1794
1843
  (0, react_1.useEffect)(function () {
1795
1844
  latestScrollRef.current = { top: scrollTop, left: scrollLeft };
1796
1845
  latestCommittedScrollRef.current = { top: scrollTop, left: scrollLeft };
@@ -1875,6 +1924,7 @@ function Table(props) {
1875
1924
  searchOpen: searchOpen,
1876
1925
  searchOptions: searchOptions,
1877
1926
  trHeight: trHeight,
1927
+ rowOffsets: variableRowOffsets,
1878
1928
  verticalScrollState: logicalVerticalScrollState,
1879
1929
  viewportInsets: keyboardViewportInsets,
1880
1930
  });
@@ -1909,6 +1959,7 @@ function Table(props) {
1909
1959
  searchOpen: searchOpen,
1910
1960
  searchOptions: searchOptions,
1911
1961
  trHeight: trHeight,
1962
+ rowOffsets: variableRowOffsets,
1912
1963
  verticalScrollState: logicalVerticalScrollState,
1913
1964
  viewportInsets: keyboardViewportInsets,
1914
1965
  };
@@ -1926,7 +1977,7 @@ function Table(props) {
1926
1977
  };
1927
1978
  var moveWithArrowKey = function (key, extendSelection, toBoundary) {
1928
1979
  if (toBoundary === void 0) { toBoundary = false; }
1929
- var _a = keyboardRuntimeRef.current, activeCell = _a.activeCell, cellInteractionSession = _a.cellInteractionSession, cellNavigationOptions = _a.cellNavigationOptions, cellSelectionEnabled = _a.cellSelectionEnabled, columns = _a.columns, commitScroll = _a.commitScroll, dataLength = _a.dataLength, frozenColumnIndex = _a.frozenColumnIndex, frozenRowCount = _a.frozenRowCount, moveActiveCell = _a.moveActiveCell, trHeight = _a.trHeight, verticalScrollState = _a.verticalScrollState, viewportInsets = _a.viewportInsets;
1980
+ var _a = keyboardRuntimeRef.current, activeCell = _a.activeCell, cellInteractionSession = _a.cellInteractionSession, cellNavigationOptions = _a.cellNavigationOptions, cellSelectionEnabled = _a.cellSelectionEnabled, columns = _a.columns, commitScroll = _a.commitScroll, dataLength = _a.dataLength, frozenColumnIndex = _a.frozenColumnIndex, frozenRowCount = _a.frozenRowCount, moveActiveCell = _a.moveActiveCell, trHeight = _a.trHeight, rowOffsets = _a.rowOffsets, verticalScrollState = _a.verticalScrollState, viewportInsets = _a.viewportInsets;
1930
1981
  var container = containerRef.current;
1931
1982
  var activeElement = document.activeElement;
1932
1983
  if (!container ||
@@ -1960,6 +2011,7 @@ function Table(props) {
1960
2011
  frozenRowCount: frozenRowCount,
1961
2012
  columns: columns,
1962
2013
  rowHeight: trHeight,
2014
+ rowOffsets: rowOffsets,
1963
2015
  verticalScrollState: verticalScrollState,
1964
2016
  viewportInsets: viewportInsets,
1965
2017
  });
@@ -1994,7 +2046,7 @@ function Table(props) {
1994
2046
  };
1995
2047
  var handleKeyDown = function (evt) {
1996
2048
  var _a, _b, _c, _d, _e;
1997
- var _f = keyboardRuntimeRef.current, activeCell = _f.activeCell, cellInteractionSession = _f.cellInteractionSession, cellNavigationOptions = _f.cellNavigationOptions, cellSelectionEnabled = _f.cellSelectionEnabled, clearCellSelection = _f.clearCellSelection, clearCellSelectionOnEscape = _f.clearCellSelectionOnEscape, columns = _f.columns, commitCheckboxCell = _f.commitCheckboxCell, commitScroll = _f.commitScroll, copySelectedCells = _f.copySelectedCells, data = _f.data, dataLength = _f.dataLength, disabled = _f.disabled, editable = _f.editable, editItemIndex = _f.editItemIndex, endCellSelectionDrag = _f.endCellSelectionDrag, frozenColumnIndex = _f.frozenColumnIndex, frozenRowCount = _f.frozenRowCount, height = _f.height, handleClick = _f.handleClick, moveActiveCell = _f.moveActiveCell, openCellContextMenu = _f.openCellContextMenu, selectAllCells = _f.selectAllCells, setEditItem = _f.setEditItem, requestSearchOpen = _f.requestSearchOpen, searchOpen = _f.searchOpen, searchOptions = _f.searchOptions, trHeight = _f.trHeight, verticalScrollState = _f.verticalScrollState, viewportInsets = _f.viewportInsets;
2049
+ var _f = keyboardRuntimeRef.current, activeCell = _f.activeCell, cellInteractionSession = _f.cellInteractionSession, cellNavigationOptions = _f.cellNavigationOptions, cellSelectionEnabled = _f.cellSelectionEnabled, clearCellSelection = _f.clearCellSelection, clearCellSelectionOnEscape = _f.clearCellSelectionOnEscape, columns = _f.columns, commitCheckboxCell = _f.commitCheckboxCell, commitScroll = _f.commitScroll, copySelectedCells = _f.copySelectedCells, data = _f.data, dataLength = _f.dataLength, disabled = _f.disabled, editable = _f.editable, editItemIndex = _f.editItemIndex, endCellSelectionDrag = _f.endCellSelectionDrag, frozenColumnIndex = _f.frozenColumnIndex, frozenRowCount = _f.frozenRowCount, height = _f.height, handleClick = _f.handleClick, moveActiveCell = _f.moveActiveCell, openCellContextMenu = _f.openCellContextMenu, selectAllCells = _f.selectAllCells, setEditItem = _f.setEditItem, requestSearchOpen = _f.requestSearchOpen, searchOpen = _f.searchOpen, searchOptions = _f.searchOptions, trHeight = _f.trHeight, rowOffsets = _f.rowOffsets, verticalScrollState = _f.verticalScrollState, viewportInsets = _f.viewportInsets;
1998
2050
  var container = containerRef.current;
1999
2051
  var activeElement = document.activeElement;
2000
2052
  if (!container || (activeElement !== container && !container.contains(activeElement)))
@@ -2127,6 +2179,7 @@ function Table(props) {
2127
2179
  frozenRowCount: frozenRowCount,
2128
2180
  columns: columns,
2129
2181
  rowHeight: trHeight,
2182
+ rowOffsets: rowOffsets,
2130
2183
  verticalScrollState: verticalScrollState,
2131
2184
  viewportInsets: viewportInsets,
2132
2185
  });
@@ -2171,6 +2224,7 @@ function Table(props) {
2171
2224
  frozenRowCount: frozenRowCount,
2172
2225
  columns: columns,
2173
2226
  rowHeight: trHeight,
2227
+ rowOffsets: rowOffsets,
2174
2228
  verticalScrollState: verticalScrollState,
2175
2229
  viewportInsets: viewportInsets,
2176
2230
  });
@@ -2199,6 +2253,7 @@ function Table(props) {
2199
2253
  frozenRowCount: frozenRowCount,
2200
2254
  columns: columns,
2201
2255
  rowHeight: trHeight,
2256
+ rowOffsets: rowOffsets,
2202
2257
  verticalScrollState: verticalScrollState,
2203
2258
  viewportInsets: viewportInsets,
2204
2259
  });
@@ -2293,7 +2348,7 @@ function Table(props) {
2293
2348
  if (gateway instanceof HTMLInputElement) {
2294
2349
  gateway.focus({ preventScroll: true });
2295
2350
  }
2296
- }, "data-scroll-variant": scrollbar.variant, "data-vertical-scrollbar": scrollbar.variant !== 'native' && scrollbar.vertical.visible ? 'visible' : 'hidden', "data-bgrid-cell-selection-enabled": cellSelectionEnabled ? 'true' : 'false', "data-bgrid-frozen-columns": ((_5 = props.frozenColumnIndex) !== null && _5 !== void 0 ? _5 : 0) > 0 ? 'true' : 'false', "data-bgrid-disabled": disabled ? 'true' : undefined },
2351
+ }, "data-scroll-variant": scrollbar.variant, "data-vertical-scrollbar": scrollbar.variant !== 'native' && scrollbar.vertical.visible ? 'visible' : 'hidden', "data-bgrid-cell-selection-enabled": cellSelectionEnabled ? 'true' : 'false', "data-bgrid-frozen-columns": ((_5 = props.frozenColumnIndex) !== null && _5 !== void 0 ? _5 : 0) > 0 ? 'true' : 'false', "data-bgrid-disabled": disabled ? 'true' : undefined, "data-bgrid-variable-row-height": rowHeightMetrics.variable ? 'true' : undefined },
2297
2352
  scrollbar.variant !== 'native' && scrollbar.vertical.visible && (React.createElement("div", { className: 'bgrid-vertical-scrollbar-gutter', "aria-hidden": 'true' })),
2298
2353
  scrollbar.variant !== 'native' && scrollbar.vertical.visible && (React.createElement("div", { className: 'bgrid-vertical-scrollbar-area', style: {
2299
2354
  top: 0,
@@ -2332,17 +2387,17 @@ function Table(props) {
2332
2387
  React.createElement("div", { className: 'bgrid-body-scroll-content', style: { height: virtualScrollWindowMetrics.physicalContentHeight } },
2333
2388
  frozenRowCount > 0 && (React.createElement("div", { className: 'bgrid-frozen-rows-layer', style: { height: frozenRowsHeight, top: stickyTopHeight }, "data-bgrid-row-band": 'frozen' },
2334
2389
  (frozenColumnsWidth !== null && frozenColumnsWidth !== void 0 ? frozenColumnsWidth : 0) > 0 && (React.createElement("div", { className: 'bgrid-frozen-rows-left bgrid-frozen-column-boundary', style: { width: frozenColumnsWidth }, role: 'rfdg-frozen-rows-left' },
2335
- React.createElement(TableBodyFrozen_1.default, { scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top-frozen', quadrant: 'top-left', allowRowReorder: false }),
2390
+ React.createElement(TableBodyFrozen_1.default, { rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top-frozen', quadrant: 'top-left', allowRowReorder: false }),
2336
2391
  renderSelectionOverlay('top-left'))),
2337
2392
  React.createElement("div", { className: 'bgrid-frozen-rows-main', style: { left: frozenColumnsWidth }, role: 'rfdg-frozen-rows-main' },
2338
- React.createElement(TableBody_1.default, { scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top', quadrant: 'top-main', allowRowReorder: false }),
2393
+ React.createElement(TableBody_1.default, { rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top', quadrant: 'top-main', allowRowReorder: false }),
2339
2394
  renderSelectionOverlay('top-main')))),
2340
2395
  React.createElement("div", { className: 'bgrid-scrollable-rows-layer', style: { height: physicalScrollableRowsHeight }, "data-bgrid-row-band": 'scrollable' },
2341
2396
  (frozenColumnsWidth !== null && frozenColumnsWidth !== void 0 ? frozenColumnsWidth : 0) > 0 && (React.createElement(FrozenScrollContent, { style: {
2342
2397
  width: frozenColumnsWidth,
2343
2398
  height: physicalScrollableRowsHeight,
2344
2399
  }, role: 'rfdg-frozen-scroll-container' },
2345
- React.createElement(TableBodyFrozen_1.default, { scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, style: frozenScrollableBodyStyle, quadrant: 'body-left', onRowReorderPointerDown: rowReorderController.onPointerDown, onRowReorderKeyDown: rowReorderController.onKeyDown }),
2400
+ React.createElement(TableBodyFrozen_1.default, { rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, style: frozenScrollableBodyStyle, quadrant: 'body-left', onRowReorderPointerDown: rowReorderController.onPointerDown, onRowReorderKeyDown: rowReorderController.onKeyDown }),
2346
2401
  renderSelectionOverlay('body-left'))),
2347
2402
  React.createElement(ScrollContent, { style: {
2348
2403
  left: frozenColumnsWidth,
@@ -2351,7 +2406,7 @@ function Table(props) {
2351
2406
  : visibleScrollableRows.paddingTop,
2352
2407
  height: physicalScrollableRowsHeight,
2353
2408
  } },
2354
- React.createElement(TableBody_1.default, { scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, quadrant: 'body-main' }),
2409
+ React.createElement(TableBody_1.default, { rowHeightMetrics: rowHeightMetrics, scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, quadrant: 'body-main' }),
2355
2410
  renderSelectionOverlay('body-main')))),
2356
2411
  summary && summary.position === 'bottom' && (React.createElement(SummaryContainer, { position: 'bottom', style: { height: summaryHeight, bottom: 0 }, role: 'rfdg-summary-container' },
2357
2412
  (frozenColumnsWidth !== null && frozenColumnsWidth !== void 0 ? frozenColumnsWidth : 0) > 0 && (React.createElement(FrozenSummary, { style: { width: frozenColumnsWidth }, role: 'rfdg-frozen-summary' },
@@ -2432,6 +2487,7 @@ function getCellPosition(target, container) {
2432
2487
  return { rowIndex: rowIndex, columnIndex: columnIndex, rowSpan: rowSpan };
2433
2488
  }
2434
2489
  function getCellPositionFromPointer(_a) {
2490
+ var _b;
2435
2491
  var clientX = _a.clientX, clientY = _a.clientY, bodyContainer = _a.bodyContainer, scrollContainer = _a.scrollContainer, metrics = _a.metrics;
2436
2492
  if (!bodyContainer || !scrollContainer || metrics.columns.length === 0 || metrics.dataLength === 0)
2437
2493
  return undefined;
@@ -2439,10 +2495,17 @@ function getCellPositionFromPointer(_a) {
2439
2495
  var bodyRect = bodyContainer.getBoundingClientRect();
2440
2496
  var frozenRowsBottom = bodyRect.top + metrics.frozenRowsHeight;
2441
2497
  var rowIndex = metrics.frozenRowCount > 0 && clientY < frozenRowsBottom
2442
- ? (0, coordinate_1.clamp)(Math.floor((clientY - bodyRect.top) / metrics.trHeight), 0, metrics.frozenRowCount - 1)
2443
- : (0, coordinate_1.clamp)(metrics.frozenRowCount +
2444
- Math.floor((metrics.scrollTop + (0, coordinate_1.clamp)(clientY - scrollRect.top, 0, Math.max(scrollContainer.clientHeight - 1, 0))) /
2445
- metrics.trHeight), 0, metrics.dataLength - 1);
2498
+ ? (0, coordinate_1.clamp)(metrics.rowOffsets
2499
+ ? (0, utils_1.getRowIndexAtOffset)(metrics.rowOffsets, clientY - bodyRect.top)
2500
+ : Math.floor((clientY - bodyRect.top) / metrics.trHeight), 0, metrics.frozenRowCount - 1)
2501
+ : (0, coordinate_1.clamp)(metrics.rowOffsets
2502
+ ? (0, utils_1.getRowIndexAtOffset)(metrics.rowOffsets, ((_b = metrics.rowOffsets[metrics.frozenRowCount]) !== null && _b !== void 0 ? _b : 0) +
2503
+ metrics.scrollTop +
2504
+ (0, coordinate_1.clamp)(clientY - scrollRect.top, 0, Math.max(scrollContainer.clientHeight - 1, 0)))
2505
+ : metrics.frozenRowCount +
2506
+ Math.floor((metrics.scrollTop +
2507
+ (0, coordinate_1.clamp)(clientY - scrollRect.top, 0, Math.max(scrollContainer.clientHeight - 1, 0))) /
2508
+ metrics.trHeight), 0, metrics.dataLength - 1);
2446
2509
  var columnIndex = getColumnIndexFromPointer({
2447
2510
  clientX: clientX,
2448
2511
  bodyContainer: bodyContainer,
@@ -171,7 +171,7 @@ function getSearchMatchTokens(matches) {
171
171
  function TableBody(_a) {
172
172
  var _this = this;
173
173
  var _b, _c;
174
- var _d = _a.region, region = _d === void 0 ? 'main' : _d, rowRange = _a.rowRange, style = _a.style, role = _a.role, quadrant = _a.quadrant, _e = _a.allowRowReorder, allowRowReorder = _e === void 0 ? true : _e, onRowReorderPointerDown = _a.onRowReorderPointerDown, onRowReorderKeyDown = _a.onRowReorderKeyDown;
174
+ var _d = _a.region, region = _d === void 0 ? 'main' : _d, rowRange = _a.rowRange, style = _a.style, role = _a.role, quadrant = _a.quadrant, _e = _a.allowRowReorder, allowRowReorder = _e === void 0 ? true : _e, onRowReorderPointerDown = _a.onRowReorderPointerDown, onRowReorderKeyDown = _a.onRowReorderKeyDown, rowHeightMetrics = _a.rowHeightMetrics;
175
175
  var isLeftRegion = region === 'left';
176
176
  // [Selector Group 1] Scroll & Dimensions - 스크롤 및 차원
177
177
  var _f = (0, store_1.useAppStore)((0, shallow_1.useShallow)(function (s) { return ({
@@ -262,10 +262,11 @@ function TableBody(_a) {
262
262
  React.createElement("tbody", { role: role !== null && role !== void 0 ? role : (isLeftRegion ? 'rfdg-body-frozen' : 'rfdg-body') },
263
263
  dataSet.map(function (item, i) {
264
264
  var _a;
265
- var _b, _c, _d, _e;
265
+ var _b, _c, _d, _e, _f;
266
266
  var ri = startIdx + i;
267
+ var resolvedRowHeight = (_b = rowHeightMetrics === null || rowHeightMetrics === void 0 ? void 0 : rowHeightMetrics.heights[ri]) !== null && _b !== void 0 ? _b : trHeight;
267
268
  var rowStatus = getRowStatusLabel(item.status);
268
- var sourceIndex = (_b = sourceIndexByVisibleIndex === null || sourceIndexByVisibleIndex === void 0 ? void 0 : sourceIndexByVisibleIndex[ri]) !== null && _b !== void 0 ? _b : ri;
269
+ var sourceIndex = (_c = sourceIndexByVisibleIndex === null || sourceIndexByVisibleIndex === void 0 ? void 0 : sourceIndexByVisibleIndex[ri]) !== null && _c !== void 0 ? _c : ri;
269
270
  var trProps = {
270
271
  editable: editable,
271
272
  };
@@ -275,7 +276,7 @@ function TableBody(_a) {
275
276
  var active = rowKey !== undefined && selectedRowKey !== undefined
276
277
  ? (0, utils_1.getCellValueByRowKey)(rowKey, item.values) === selectedRowKey
277
278
  : false;
278
- var className = (_c = getRowClassName === null || getRowClassName === void 0 ? void 0 : getRowClassName(sourceIndex, item)) !== null && _c !== void 0 ? _c : '';
279
+ var className = (_d = getRowClassName === null || getRowClassName === void 0 ? void 0 : getRowClassName(sourceIndex, item)) !== null && _d !== void 0 ? _d : '';
279
280
  var rowReorderRole = (reorderingInfo === null || reorderingInfo === void 0 ? void 0 : reorderingInfo.fromIndex) === undefined || reorderingInfo.toIndex === undefined
280
281
  ? undefined
281
282
  : (0, utils_1.getRowReorderRole)({
@@ -298,16 +299,16 @@ function TableBody(_a) {
298
299
  : reorderingInfo.toIndex > reorderingInfo.fromIndex
299
300
  ? 'down'
300
301
  : undefined;
301
- return (React.createElement(TableBodyTr, __assign({ key: ri, itemHeight: itemHeight, itemPadding: itemPadding, active: active, hasOnClick: hasOnClick, className: className + (active ? ' active' : ''), "data-ri": ri, "data-bgrid-row-reorder-role": rowReorderRole, "data-bgrid-row-reorder-phase": rowReorderRole ? reorderingInfo === null || reorderingInfo === void 0 ? void 0 : reorderingInfo.phase : undefined, "data-bgrid-row-reorder-direction": rowReorderRole ? rowReorderDirection : undefined, style: rowReorderRole && rowReorderRole !== 'source'
302
+ return (React.createElement(TableBodyTr, __assign({ key: ri, itemHeight: itemHeight, itemPadding: itemPadding, rowHeight: resolvedRowHeight, active: active, hasOnClick: hasOnClick, className: className + (active ? ' active' : ''), "data-ri": ri, "data-bgrid-row-reorder-role": rowReorderRole, "data-bgrid-row-reorder-phase": rowReorderRole ? reorderingInfo === null || reorderingInfo === void 0 ? void 0 : reorderingInfo.phase : undefined, "data-bgrid-row-reorder-direction": rowReorderRole ? rowReorderDirection : undefined, style: rowReorderRole && rowReorderRole !== 'source'
302
303
  ? (_a = {}, _a['--bgrid-row-reorder-offset-y'] = "".concat(rowReorderOffset, "px"), _a)
303
304
  : undefined }, trProps),
304
305
  isLeftRegion &&
305
306
  showLineNumber &&
306
307
  (rowReorderEnabled ? (React.createElement(LineNumberTd, { bordered: !hasRowChecked && frozenColumnIndex > 0 && variant !== 'vertical-bordered', className: 'bgrid-line-number-drag', rowStatus: rowStatus, rowIndex: ri },
307
- React.createElement("button", { type: 'button', className: 'bgrid-row-reorder-handle drag-handle', "data-row-reorder-index": ri, "data-dragging": (reorderingInfo === null || reorderingInfo === void 0 ? void 0 : reorderingInfo.fromIndex) === ri ? 'true' : undefined, "aria-label": "Move row ".concat(ri + 1), disabled: !!disabled || !!cellInteractionSession, onPointerDown: function (event) { return onRowReorderPointerDown === null || onRowReorderPointerDown === void 0 ? void 0 : onRowReorderPointerDown(event, ri); }, onKeyDown: function (event) { return onRowReorderKeyDown === null || onRowReorderKeyDown === void 0 ? void 0 : onRowReorderKeyDown(event, ri); } }, (_d = reorder === null || reorder === void 0 ? void 0 : reorder.handleIcon) !== null && _d !== void 0 ? _d : React.createElement(GripVertical_1.GripVertical, null)),
308
+ React.createElement("button", { type: 'button', className: 'bgrid-row-reorder-handle drag-handle', "data-row-reorder-index": ri, "data-dragging": (reorderingInfo === null || reorderingInfo === void 0 ? void 0 : reorderingInfo.fromIndex) === ri ? 'true' : undefined, "aria-label": "Move row ".concat(ri + 1), disabled: !!disabled || !!cellInteractionSession, onPointerDown: function (event) { return onRowReorderPointerDown === null || onRowReorderPointerDown === void 0 ? void 0 : onRowReorderPointerDown(event, ri); }, onKeyDown: function (event) { return onRowReorderKeyDown === null || onRowReorderKeyDown === void 0 ? void 0 : onRowReorderKeyDown(event, ri); } }, (_e = reorder === null || reorder === void 0 ? void 0 : reorder.handleIcon) !== null && _e !== void 0 ? _e : React.createElement(GripVertical_1.GripVertical, null)),
308
309
  React.createElement("span", { className: 'bgrid-line-number-value' }, rowStatus !== null && rowStatus !== void 0 ? rowStatus : ri + 1))) : (React.createElement(LineNumberTd, { bordered: !hasRowChecked && frozenColumnIndex > 0 && variant !== 'vertical-bordered', rowStatus: rowStatus, rowIndex: ri }, rowStatus !== null && rowStatus !== void 0 ? rowStatus : ri + 1))),
309
310
  isLeftRegion && hasRowChecked && (React.createElement("td", { className: frozenColumnIndex > 0 ? 'bordered' : '' },
310
- React.createElement(RowSelector_1.default, { disabled: !!disabled || ((_e = rowChecked.disabled) === null || _e === void 0 ? void 0 : _e.call(rowChecked, sourceIndex, item)), checked: checkedAll === true || checkedIndexesMap.get(sourceIndex), handleChange: function (checked) { return __awaiter(_this, void 0, void 0, function () {
311
+ React.createElement(RowSelector_1.default, { disabled: !!disabled || ((_f = rowChecked.disabled) === null || _f === void 0 ? void 0 : _f.call(rowChecked, sourceIndex, item)), checked: checkedAll === true || checkedIndexesMap.get(sourceIndex), handleChange: function (checked) { return __awaiter(_this, void 0, void 0, function () {
311
312
  return __generator(this, function (_a) {
312
313
  switch (_a.label) {
313
314
  case 0:
@@ -455,10 +456,10 @@ function BodyTable(_a) {
455
456
  }
456
457
  function TableBodyTr(_a) {
457
458
  var _b;
458
- var itemHeight = _a.itemHeight, itemPadding = _a.itemPadding, active = _a.active, editable = _a.editable, odd = _a.odd, hasOnClick = _a.hasOnClick, className = _a.className, children = _a.children, style = _a.style, rest = __rest(_a, ["itemHeight", "itemPadding", "active", "editable", "odd", "hasOnClick", "className", "children", "style"]);
459
+ var itemHeight = _a.itemHeight, itemPadding = _a.itemPadding, rowHeight = _a.rowHeight, active = _a.active, editable = _a.editable, odd = _a.odd, hasOnClick = _a.hasOnClick, className = _a.className, children = _a.children, style = _a.style, rest = __rest(_a, ["itemHeight", "itemPadding", "rowHeight", "active", "editable", "odd", "hasOnClick", "className", "children", "style"]);
459
460
  var clickable = !editable && hasOnClick;
460
461
  var rowClassName = ['bgrid-body-row', active ? 'bgrid-row-active' : '', className !== null && className !== void 0 ? className : ''].filter(Boolean).join(' ');
461
- return (React.createElement("tr", __assign({ className: rowClassName, "data-odd": odd ? 'true' : undefined, "data-clickable": clickable ? 'true' : undefined, style: __assign((_b = {}, _b['--bgrid-item-line-height'] = "".concat(itemHeight, "px"), _b['--bgrid-item-cell-height'] = "".concat(itemHeight + itemPadding * 2, "px"), _b), style) }, rest), children));
462
+ return (React.createElement("tr", __assign({ className: rowClassName, "data-odd": odd ? 'true' : undefined, "data-clickable": clickable ? 'true' : undefined, style: __assign((_b = {}, _b['--bgrid-item-line-height'] = "".concat(itemHeight, "px"), _b['--bgrid-item-cell-height'] = "".concat(rowHeight !== null && rowHeight !== void 0 ? rowHeight : itemHeight + itemPadding * 2, "px"), _b), style) }, rest), children));
462
463
  }
463
464
  function NoDataTr(_a) {
464
465
  var _b;
@@ -39,6 +39,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  var React = __importStar(require("react"));
40
40
  var TableBody_1 = __importDefault(require("./TableBody"));
41
41
  function TableBodyFrozen(props) {
42
- return (React.createElement(TableBody_1.default, { scrollContainerRef: props.scrollContainerRef, region: 'left', style: props.style, rowRange: props.rowRange, role: props.role, quadrant: props.quadrant, allowRowReorder: props.allowRowReorder, onRowReorderPointerDown: props.onRowReorderPointerDown, onRowReorderKeyDown: props.onRowReorderKeyDown }));
42
+ return (React.createElement(TableBody_1.default, { scrollContainerRef: props.scrollContainerRef, region: 'left', style: props.style, rowRange: props.rowRange, role: props.role, quadrant: props.quadrant, allowRowReorder: props.allowRowReorder, onRowReorderPointerDown: props.onRowReorderPointerDown, onRowReorderKeyDown: props.onRowReorderKeyDown, rowHeightMetrics: props.rowHeightMetrics }));
43
43
  }
44
44
  exports.default = React.memo(TableBodyFrozen);
@@ -49,8 +49,9 @@ var LazyTableHeadToolbox = React.lazy(function () {
49
49
  }); });
50
50
  });
51
51
  function TableHeadColumn(_a) {
52
- var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
53
- var column = _a.column, _q = _a.columnIndex, columnIndex = _q === void 0 ? 0 : _q;
52
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
53
+ var column = _a.column, _u = _a.columnIndex, columnIndex = _u === void 0 ? 0 : _u;
54
+ var toolboxMsg = (0, store_1.useAppStore)(function (s) { var _a; return (_a = s.msg) === null || _a === void 0 ? void 0 : _a.toolbox; });
54
55
  var sort = (0, store_1.useAppStore)(function (s) { return s.sort; });
55
56
  var sortParams = (0, store_1.useAppStore)(function (s) { return s.sortParams; });
56
57
  var dataQuery = (0, store_1.useAppStore)(function (s) { return s.dataQuery; });
@@ -89,22 +90,22 @@ function TableHeadColumn(_a) {
89
90
  // Tooltip
90
91
  var tooltipParts = [];
91
92
  if (isAsc)
92
- tooltipParts.push('오름차순 정렬');
93
+ tooltipParts.push((_e = toolboxMsg === null || toolboxMsg === void 0 ? void 0 : toolboxMsg.sortAscending) !== null && _e !== void 0 ? _e : '오름차순 정렬');
93
94
  if (isDesc)
94
- tooltipParts.push('내림차순 정렬');
95
+ tooltipParts.push((_f = toolboxMsg === null || toolboxMsg === void 0 ? void 0 : toolboxMsg.sortDescending) !== null && _f !== void 0 ? _f : '내림차순 정렬');
95
96
  if (isFiltered)
96
- tooltipParts.push('필터 적용됨');
97
- var tooltip = tooltipParts.length > 0 ? tooltipParts.join(', ') : '컬럼 옵션 열기';
97
+ tooltipParts.push((_g = toolboxMsg === null || toolboxMsg === void 0 ? void 0 : toolboxMsg.filterApplied) !== null && _g !== void 0 ? _g : '필터 적용됨');
98
+ var tooltip = tooltipParts.length > 0 ? tooltipParts.join(', ') : ((_h = toolboxMsg === null || toolboxMsg === void 0 ? void 0 : toolboxMsg.openColumnOptions) !== null && _h !== void 0 ? _h : '컬럼 옵션 열기');
98
99
  // Resolve icons with hierarchy (column -> global -> default)
99
- var sortAscIcon = (_f = (_e = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.sortAsc) !== null && _e !== void 0 ? _e : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.sortAsc) !== null && _f !== void 0 ? _f : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor' },
100
+ var sortAscIcon = (_k = (_j = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.sortAsc) !== null && _j !== void 0 ? _j : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.sortAsc) !== null && _k !== void 0 ? _k : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor' },
100
101
  React.createElement("path", { d: 'M3 11.5L8 4l5 7.5H3z' })));
101
- var sortDescIcon = (_h = (_g = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.sortDesc) !== null && _g !== void 0 ? _g : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.sortDesc) !== null && _h !== void 0 ? _h : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor' },
102
+ var sortDescIcon = (_m = (_l = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.sortDesc) !== null && _l !== void 0 ? _l : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.sortDesc) !== null && _m !== void 0 ? _m : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor' },
102
103
  React.createElement("path", { d: 'M3 4.5L8 12l5-7.5H3z' })));
103
- var filterIcon = (_k = (_j = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.filter) !== null && _j !== void 0 ? _j : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.filter) !== null && _k !== void 0 ? _k : (React.createElement("svg", { viewBox: '0 0 16 16', width: '12', height: '12', fill: 'currentColor', className: 'bgrid-filter-icon' },
104
+ var filterIcon = (_p = (_o = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.filter) !== null && _o !== void 0 ? _o : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.filter) !== null && _p !== void 0 ? _p : (React.createElement("svg", { viewBox: '0 0 16 16', width: '12', height: '12', fill: 'currentColor', className: 'bgrid-filter-icon' },
104
105
  React.createElement("path", { d: 'M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.293V13.5a.5.5 0 0 1-.74.439l-2.5-1.5A.5.5 0 0 1 6.5 12V8.293L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2z' })));
105
- var filterBadgeIcon = (_m = (_l = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.filterBadge) !== null && _l !== void 0 ? _l : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.filterBadge) !== null && _m !== void 0 ? _m : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor', className: 'bgrid-filter-badge-icon' },
106
+ var filterBadgeIcon = (_r = (_q = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.filterBadge) !== null && _q !== void 0 ? _q : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.filterBadge) !== null && _r !== void 0 ? _r : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor', className: 'bgrid-filter-badge-icon' },
106
107
  React.createElement("path", { d: 'M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.293V13.5a.5.5 0 0 1-.74.439l-2.5-1.5A.5.5 0 0 1 6.5 12V8.293L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2z' })));
107
- var dropdownIcon = (_p = (_o = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.dropdown) !== null && _o !== void 0 ? _o : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.dropdown) !== null && _p !== void 0 ? _p : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor', className: 'bgrid-dropdown-arrow' },
108
+ var dropdownIcon = (_t = (_s = columnIcons === null || columnIcons === void 0 ? void 0 : columnIcons.dropdown) !== null && _s !== void 0 ? _s : globalIcons === null || globalIcons === void 0 ? void 0 : globalIcons.dropdown) !== null && _t !== void 0 ? _t : (React.createElement("svg", { viewBox: '0 0 16 16', width: '10', height: '10', fill: 'currentColor', className: 'bgrid-dropdown-arrow' },
108
109
  React.createElement("path", { d: 'M3 6l5 5 5-5H3z' })));
109
110
  if (isToolboxEnabled) {
110
111
  return (React.createElement("div", { className: 'bgrid-head-cell-wrapper' },