beautiful-grid 1.0.9 → 1.0.11
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 +48 -0
- package/cjs/BGrid.js +24 -20
- package/cjs/components/Table.js +153 -78
- package/cjs/components/TableBody.js +51 -173
- package/cjs/components/TableBodyFrozen.js +1 -1
- package/cjs/components/TableBodyRow.js +241 -0
- package/cjs/store/createAppStore.js +32 -47
- package/cjs/utils/cellSelectionGeometry.js +18 -7
- package/cjs/utils/checkedIndexes.js +45 -0
- package/cjs/utils/coordinate.js +15 -10
- package/cjs/utils/getVisibleScrollableRowRange.js +25 -6
- package/cjs/utils/gridSearch.js +1 -1
- package/cjs/utils/index.js +2 -0
- package/cjs/utils/rowHeightMetrics.js +61 -0
- package/cjs/utils/useBodyData.js +53 -21
- package/esm/BGrid.js +20 -15
- package/esm/components/Table.js +100 -27
- package/esm/components/TableBody.js +50 -106
- package/esm/components/TableBodyFrozen.js +1 -1
- package/esm/components/TableBodyRow.js +121 -0
- package/esm/store/createAppStore.js +13 -25
- package/esm/utils/cellSelectionGeometry.js +16 -7
- package/esm/utils/checkedIndexes.js +19 -0
- package/esm/utils/coordinate.js +8 -3
- package/esm/utils/getVisibleScrollableRowRange.js +24 -6
- package/esm/utils/gridSearch.js +1 -1
- package/esm/utils/index.js +2 -0
- package/esm/utils/rowHeightMetrics.js +56 -0
- package/esm/utils/useBodyData.js +26 -17
- package/package.json +1 -1
- package/style.css +4 -0
- package/types/BGrid.d.ts +1 -1
- package/types/components/Table.d.ts +2 -0
- package/types/components/TableBody.d.ts +12 -2
- package/types/components/TableBodyFrozen.d.ts +4 -1
- package/types/components/TableBodyRow.d.ts +56 -0
- package/types/types.d.ts +9 -4
- package/types/utils/cellSelectionGeometry.d.ts +2 -1
- package/types/utils/checkedIndexes.d.ts +1 -0
- package/types/utils/coordinate.d.ts +2 -1
- package/types/utils/getVisibleScrollableRowRange.d.ts +3 -1
- package/types/utils/gridSearch.d.ts +1 -1
- package/types/utils/index.d.ts +2 -0
- package/types/utils/rowHeightMetrics.d.ts +12 -0
package/README.md
CHANGED
|
@@ -18,14 +18,34 @@
|
|
|
18
18
|
[](https://github.com/axisj/beautiful-grid/pulls)
|
|
19
19
|
[](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> •
|
|
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
|
+
[](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,
|
|
@@ -387,31 +387,34 @@ function BGrid(_a) {
|
|
|
387
387
|
includeRows: false,
|
|
388
388
|
});
|
|
389
389
|
}
|
|
390
|
-
var sourceIndexByVisibleIndex = resolvedData.map(function (_, i) { return i; });
|
|
391
|
-
var visibleIndexBySourceIndex = new Map(resolvedData.map(function (_, i) { return [i, i]; }));
|
|
392
390
|
return {
|
|
393
391
|
rows: [],
|
|
394
392
|
data: resolvedData,
|
|
395
|
-
sourceIndexByVisibleIndex:
|
|
396
|
-
visibleIndexBySourceIndex:
|
|
393
|
+
sourceIndexByVisibleIndex: undefined,
|
|
394
|
+
visibleIndexBySourceIndex: undefined,
|
|
397
395
|
};
|
|
398
396
|
}, [queryColumns, resolvedData, resolvedDataControl === null || resolvedDataControl === void 0 ? void 0 : resolvedDataControl.mode, resolvedDataQuery, resolvedRowKey]);
|
|
399
397
|
var displayData = processedResult.data;
|
|
398
|
+
var rowHeightMetrics = React.useMemo(function () { return (0, utils_1.createRowHeightMetrics)(displayData, itemHeight + itemPadding * 2, getRowHeight); }, [displayData, getRowHeight, itemHeight, itemPadding]);
|
|
400
399
|
var resolvedFrozenRowCount = pivotEnabled
|
|
401
400
|
? 0
|
|
402
401
|
: Math.min(Math.max(Math.floor(frozenRowCount), 0), displayData.length);
|
|
403
402
|
var checkedIndexesMap = React.useMemo(function () {
|
|
404
403
|
if ((resolvedRowChecked === null || resolvedRowChecked === void 0 ? void 0 : resolvedRowChecked.checkedRowKeys) && resolvedRowKey) {
|
|
405
|
-
var
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
404
|
+
var remainingKeys = new Set(resolvedRowChecked.checkedRowKeys);
|
|
405
|
+
var map = new Map();
|
|
406
|
+
if (remainingKeys.size > 0 && resolvedData) {
|
|
407
|
+
for (var i = 0; i < resolvedData.length; i++) {
|
|
408
|
+
var itemKey = (0, utils_1.getCellValueByRowKey)(resolvedRowKey, resolvedData[i].values);
|
|
409
|
+
if (remainingKeys.has(itemKey)) {
|
|
410
|
+
map.set(i, true);
|
|
411
|
+
remainingKeys.delete(itemKey);
|
|
412
|
+
if (remainingKeys.size === 0)
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
412
415
|
}
|
|
413
|
-
}
|
|
414
|
-
return
|
|
416
|
+
}
|
|
417
|
+
return map;
|
|
415
418
|
}
|
|
416
419
|
if (resolvedRowChecked === null || resolvedRowChecked === void 0 ? void 0 : resolvedRowChecked.checkedIndexes) {
|
|
417
420
|
return new Map(resolvedRowChecked === null || resolvedRowChecked === void 0 ? void 0 : resolvedRowChecked.checkedIndexes.map(function (id) { return [id, true]; }));
|
|
@@ -455,7 +458,7 @@ function BGrid(_a) {
|
|
|
455
458
|
}
|
|
456
459
|
}, [bottomBarHeight, footerHeight]);
|
|
457
460
|
var initialStoreState = React.useMemo(function () {
|
|
458
|
-
var _a, _b;
|
|
461
|
+
var _a, _b, _c;
|
|
459
462
|
var initialWidth = width !== undefined ? Math.max(width, 100) : 0;
|
|
460
463
|
var initialHeight = height !== undefined ? Math.max(height, 100) : 0;
|
|
461
464
|
var containerBorderWidth = 1;
|
|
@@ -467,7 +470,7 @@ function BGrid(_a) {
|
|
|
467
470
|
containerBorderWidth * 2, 0)
|
|
468
471
|
: 0;
|
|
469
472
|
var displayItemCount = contentBodyHeight > 0 ? Math.ceil(contentBodyHeight / (itemHeight + itemPadding * 2)) : 0;
|
|
470
|
-
var visibleCheckedCount =
|
|
473
|
+
var visibleCheckedCount = (0, utils_1.countVisibleCheckedIndexes)(displayData.length, checkedIndexesMap, processedResult.sourceIndexByVisibleIndex);
|
|
471
474
|
var checkedAll = displayData.length === 0
|
|
472
475
|
? false
|
|
473
476
|
: visibleCheckedCount === displayData.length
|
|
@@ -489,7 +492,7 @@ function BGrid(_a) {
|
|
|
489
492
|
itemPadding: itemPadding,
|
|
490
493
|
frozenColumnIndex: resolvedFrozenColumnIndex,
|
|
491
494
|
frozenRowCount: resolvedFrozenRowCount,
|
|
492
|
-
frozenRowsHeight: resolvedFrozenRowCount * (itemHeight + itemPadding * 2),
|
|
495
|
+
frozenRowsHeight: (_a = rowHeightMetrics.offsets[resolvedFrozenRowCount]) !== null && _a !== void 0 ? _a : resolvedFrozenRowCount * (itemHeight + itemPadding * 2),
|
|
493
496
|
frozenColumnsWidth: (0, utils_1.getFrozenColumnsWidth)({
|
|
494
497
|
showLineNumber: resolvedShowLineNumber,
|
|
495
498
|
rowChecked: resolvedRowChecked,
|
|
@@ -497,7 +500,7 @@ function BGrid(_a) {
|
|
|
497
500
|
frozenColumnIndex: resolvedFrozenColumnIndex,
|
|
498
501
|
columns: computedColumns,
|
|
499
502
|
dataLength: displayData.length,
|
|
500
|
-
reorderable: (
|
|
503
|
+
reorderable: (_b = resolvedReorder === null || resolvedReorder === void 0 ? void 0 : resolvedReorder.enabled) !== null && _b !== void 0 ? _b : false,
|
|
501
504
|
}),
|
|
502
505
|
columns: computedColumns,
|
|
503
506
|
columnsGroup: visibilityProjection.columnsGroup,
|
|
@@ -520,7 +523,7 @@ function BGrid(_a) {
|
|
|
520
523
|
searchOptions: resolvedSearchOptions,
|
|
521
524
|
contextMenuOptions: resolvedContextMenuOptions,
|
|
522
525
|
page: resolvedPage,
|
|
523
|
-
displayPaginationLength: resolvedPage ? (
|
|
526
|
+
displayPaginationLength: resolvedPage ? (_c = resolvedPage.displayPaginationLength) !== null && _c !== void 0 ? _c : 5 : 0,
|
|
524
527
|
loading: loading,
|
|
525
528
|
disabled: resolvedDisabled,
|
|
526
529
|
spinning: spinning,
|
|
@@ -558,6 +561,7 @@ function BGrid(_a) {
|
|
|
558
561
|
summaryHeight,
|
|
559
562
|
itemHeight,
|
|
560
563
|
itemPadding,
|
|
564
|
+
rowHeightMetrics,
|
|
561
565
|
resolvedPage,
|
|
562
566
|
resolvedSummary,
|
|
563
567
|
checkedIndexesMap,
|
|
@@ -609,7 +613,7 @@ function BGrid(_a) {
|
|
|
609
613
|
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
614
|
scrollbar: resolvedScrollbar,
|
|
611
615
|
status: resolvedStatus,
|
|
612
|
-
pagination: resolvedPagination, summaryHeight: summaryHeight, itemHeight: itemHeight, itemPadding: itemPadding, frozenColumnIndex: resolvedFrozenColumnIndex,
|
|
616
|
+
pagination: resolvedPagination, summaryHeight: summaryHeight, itemHeight: itemHeight, itemPadding: itemPadding, rowHeightMetrics: rowHeightMetrics, frozenColumnIndex: resolvedFrozenColumnIndex,
|
|
613
617
|
frozenRowCount: resolvedFrozenRowCount,
|
|
614
618
|
rowChecked: resolvedRowChecked, checkedIndexesMap: checkedIndexesMap, sort: resolvedSort, sortParams: sortParams, dataQuery: resolvedDataQuery,
|
|
615
619
|
dataControl: resolvedDataControl, icons: icons, columnVisibilityState: columnVisibilityState, searchOptions: resolvedSearchOptions,
|