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.
Files changed (50) hide show
  1. package/README.md +121 -6
  2. package/cjs/BGrid.js +388 -44
  3. package/cjs/components/CellNavigationDomSync.js +8 -0
  4. package/cjs/components/CellTextEditorGateway.js +13 -9
  5. package/cjs/components/ColResizer.js +13 -7
  6. package/cjs/components/MasterDetailCell.js +145 -0
  7. package/cjs/components/MasterDetailContext.js +42 -0
  8. package/cjs/components/Table.js +162 -52
  9. package/cjs/components/TableBody.js +7 -3
  10. package/cjs/components/TableBodyCell.js +2 -1
  11. package/cjs/components/TableSummary.js +25 -34
  12. package/cjs/components/TableSummaryFronzen.js +36 -34
  13. package/cjs/store/createAppStore.js +2 -0
  14. package/cjs/utils/cellSelectionGeometry.js +32 -6
  15. package/cjs/utils/columnVisibility.js +17 -14
  16. package/cjs/utils/index.js +1 -0
  17. package/cjs/utils/rowHeightMetrics.js +47 -6
  18. package/cjs/utils/summary.js +55 -0
  19. package/cjs/utils/useRowReorderController.js +5 -1
  20. package/esm/BGrid.js +387 -72
  21. package/esm/components/CellNavigationDomSync.js +8 -0
  22. package/esm/components/CellTextEditorGateway.js +12 -9
  23. package/esm/components/ColResizer.js +8 -2
  24. package/esm/components/MasterDetailCell.js +101 -0
  25. package/esm/components/MasterDetailContext.js +5 -0
  26. package/esm/components/Table.js +151 -42
  27. package/esm/components/TableBody.js +6 -2
  28. package/esm/components/TableBodyCell.js +2 -1
  29. package/esm/components/TableSummary.js +26 -29
  30. package/esm/components/TableSummaryFronzen.js +26 -29
  31. package/esm/store/createAppStore.js +2 -0
  32. package/esm/utils/cellSelectionGeometry.js +31 -5
  33. package/esm/utils/columnVisibility.js +21 -18
  34. package/esm/utils/index.js +1 -0
  35. package/esm/utils/rowHeightMetrics.js +46 -6
  36. package/esm/utils/summary.js +35 -0
  37. package/esm/utils/useRowReorderController.js +5 -1
  38. package/package.json +1 -1
  39. package/style.css +164 -14
  40. package/types/BGrid.d.ts +1 -1
  41. package/types/components/MasterDetailCell.d.ts +21 -0
  42. package/types/components/MasterDetailContext.d.ts +20 -0
  43. package/types/components/Table.d.ts +1 -0
  44. package/types/components/TableBody.d.ts +2 -1
  45. package/types/store/createAppStore.d.ts +1 -1
  46. package/types/types.d.ts +70 -4
  47. package/types/utils/cellSelectionGeometry.d.ts +3 -1
  48. package/types/utils/index.d.ts +1 -0
  49. package/types/utils/rowHeightMetrics.d.ts +15 -1
  50. package/types/utils/summary.d.ts +13 -0
package/style.css CHANGED
@@ -467,7 +467,7 @@
467
467
  max-height: var(--bgrid-item-cell-height, 28px);
468
468
  }
469
469
 
470
- .bgrid-body-table > tbody > tr > td > * {
470
+ .bgrid-body-table > tbody > tr.bgrid-body-row > td > * {
471
471
  max-height: var(--bgrid-item-cell-height, 28px);
472
472
  }
473
473
 
@@ -497,7 +497,8 @@
497
497
  box-shadow: var(--bgrid-frozen-boundary-shadow);
498
498
  }
499
499
 
500
- .bgrid-body-table > tbody > tr > td[data-none] {
500
+ .bgrid-body-table > tbody > tr > td[data-none],
501
+ .bgrid-summary-table > tbody > tr > td[data-none] {
501
502
  border-right: none;
502
503
  }
503
504
 
@@ -768,11 +769,11 @@
768
769
  border: 0 !important;
769
770
  }
770
771
 
771
- .bgrid-body-vertical-bordered > tbody > tr > td {
772
+ .bgrid-body-vertical-bordered > tbody > tr > td:not([data-none]) {
772
773
  border-right: 1px solid var(--bgrid-border-color-light, var(--bgrid-border-color-base));
773
774
  }
774
775
 
775
- .bgrid-summary-vertical-bordered > tbody > tr > td {
776
+ .bgrid-summary-vertical-bordered > tbody > tr > td:not([data-none]) {
776
777
  border-right: 1px solid var(--bgrid-border-color-light, var(--bgrid-border-color-base));
777
778
  }
778
779
 
@@ -795,6 +796,10 @@
795
796
  padding: 0 6.5px;
796
797
  }
797
798
 
799
+ .bgrid-summary-table > tbody > tr > td[data-none] {
800
+ border-right: none !important;
801
+ }
802
+
798
803
  .bgrid-page-no {
799
804
  transition: all 0.3s;
800
805
  display: flex;
@@ -2115,7 +2120,7 @@
2115
2120
  padding-right: var(--bgrid-scrollbar-modern-gutter-size);
2116
2121
  }
2117
2122
 
2118
- [data-scroll-variant='classic'] .bgrid-vertical-scrollbar-area {
2123
+ [data-scroll-variant='classic'] > .bgrid-vertical-scrollbar-area {
2119
2124
  width: var(--bgrid-scrollbar-classic-gutter-size);
2120
2125
  border-left-color: var(--bgrid-scrollbar-classic-gutter-border-color);
2121
2126
  background: var(--bgrid-scrollbar-classic-gutter-bg);
@@ -2127,7 +2132,7 @@
2127
2132
  background: var(--bgrid-scrollbar-classic-gutter-bg);
2128
2133
  }
2129
2134
 
2130
- [data-scroll-variant='modern'] .bgrid-vertical-scrollbar-area {
2135
+ [data-scroll-variant='modern'] > .bgrid-vertical-scrollbar-area {
2131
2136
  width: var(--bgrid-scrollbar-modern-gutter-size);
2132
2137
  border-left-color: var(--bgrid-scrollbar-modern-gutter-border-color);
2133
2138
  background: var(--bgrid-scrollbar-modern-gutter-bg);
@@ -2327,19 +2332,15 @@
2327
2332
  }
2328
2333
 
2329
2334
  /* Hide native scrollbar when using custom scrollbars */
2330
- [data-scroll-variant='classic'] [role='rfdg-scroll-container']::-webkit-scrollbar,
2331
- [data-scroll-variant='modern'] [role='rfdg-scroll-container']::-webkit-scrollbar,
2332
- [data-scroll-variant='classic'] .bgrid-scroll-container::-webkit-scrollbar,
2333
- [data-scroll-variant='modern'] .bgrid-scroll-container::-webkit-scrollbar {
2335
+ [data-scroll-variant='classic'] > .bgrid-scroll-container::-webkit-scrollbar,
2336
+ [data-scroll-variant='modern'] > .bgrid-scroll-container::-webkit-scrollbar {
2334
2337
  display: none;
2335
2338
  width: 0 !important;
2336
2339
  height: 0 !important;
2337
2340
  }
2338
2341
 
2339
- [data-scroll-variant='classic'] [role='rfdg-scroll-container'],
2340
- [data-scroll-variant='modern'] [role='rfdg-scroll-container'],
2341
- [data-scroll-variant='classic'] .bgrid-scroll-container,
2342
- [data-scroll-variant='modern'] .bgrid-scroll-container {
2342
+ [data-scroll-variant='classic'] > .bgrid-scroll-container,
2343
+ [data-scroll-variant='modern'] > .bgrid-scroll-container {
2343
2344
  scrollbar-width: none; /* Firefox */
2344
2345
  -ms-overflow-style: none; /* IE/Edge */
2345
2346
  }
@@ -2445,6 +2446,155 @@
2445
2446
  white-space: nowrap;
2446
2447
  }
2447
2448
 
2449
+ .bgrid-master-detail-cell {
2450
+ display: inline-flex;
2451
+ align-items: center;
2452
+ box-sizing: border-box;
2453
+ width: 100%;
2454
+ min-width: 0;
2455
+ }
2456
+
2457
+ .bgrid-master-detail-toggle,
2458
+ .bgrid-master-detail-toggle-spacer {
2459
+ display: inline-flex;
2460
+ flex: 0 0 18px;
2461
+ align-items: center;
2462
+ justify-content: center;
2463
+ box-sizing: border-box;
2464
+ width: 18px;
2465
+ height: 18px;
2466
+ margin: 0 4px 0 0;
2467
+ }
2468
+
2469
+ .bgrid-master-detail-icon {
2470
+ display: inline-flex;
2471
+ align-items: center;
2472
+ justify-content: center;
2473
+ width: 100%;
2474
+ height: 100%;
2475
+ line-height: 1;
2476
+ font-size: 14px;
2477
+ }
2478
+
2479
+ .bgrid-master-detail-icon > svg {
2480
+ display: block;
2481
+ }
2482
+
2483
+ .bgrid-master-detail-toggle {
2484
+ padding: 0;
2485
+ color: inherit;
2486
+ font: inherit;
2487
+ line-height: 1;
2488
+ cursor: pointer;
2489
+ background: transparent;
2490
+ border: 0;
2491
+ border-radius: 2px;
2492
+ }
2493
+
2494
+ .bgrid-master-detail-toggle:hover:not(:disabled) {
2495
+ background: var(--bgrid-body-hover-bg);
2496
+ }
2497
+
2498
+ .bgrid-master-detail-toggle:focus-visible {
2499
+ outline: 2px solid var(--bgrid-active-cell-ring-color);
2500
+ outline-offset: -1px;
2501
+ }
2502
+
2503
+ .bgrid-master-detail-toggle:disabled {
2504
+ cursor: default;
2505
+ opacity: 0.5;
2506
+ }
2507
+
2508
+ .bgrid-master-detail-cell-content {
2509
+ flex: 1 1 auto;
2510
+ min-width: 0;
2511
+ overflow: hidden;
2512
+ text-overflow: ellipsis;
2513
+ white-space: nowrap;
2514
+ }
2515
+
2516
+ .bgrid-detail-row,
2517
+ .bgrid-detail-row:hover,
2518
+ .bgrid-detail-row.bgrid-row-hover,
2519
+ .bgrid-detail-frozen-row,
2520
+ .bgrid-detail-frozen-row:hover,
2521
+ .bgrid-detail-frozen-row.bgrid-row-hover,
2522
+ .bgrid-body-table > tbody > tr.bgrid-detail-row,
2523
+ .bgrid-body-table > tbody > tr.bgrid-detail-row:hover,
2524
+ .bgrid-body-table > tbody > tr.bgrid-detail-row.bgrid-row-hover,
2525
+ .bgrid-body-table > tbody > tr.bgrid-detail-frozen-row,
2526
+ .bgrid-body-table > tbody > tr.bgrid-detail-frozen-row:hover,
2527
+ .bgrid-body-table > tbody > tr.bgrid-detail-frozen-row.bgrid-row-hover {
2528
+ background-color: var(--bgrid-body-bg) !important;
2529
+ }
2530
+
2531
+ .bgrid-detail-row {
2532
+ box-sizing: border-box;
2533
+ max-height: none !important;
2534
+ }
2535
+
2536
+ .bgrid-body-table > tbody > tr.bgrid-detail-row > td.bgrid-detail-cell {
2537
+ padding: 0 !important;
2538
+ margin: 0 !important;
2539
+ border-top: none !important;
2540
+ border-left: none !important;
2541
+ border-right: none !important;
2542
+ border-bottom: 1px solid var(--bgrid-border-color-base) !important;
2543
+ background-color: var(--bgrid-body-bg) !important;
2544
+ vertical-align: top;
2545
+ max-height: none !important;
2546
+ height: auto !important;
2547
+ overflow: visible !important;
2548
+ white-space: normal !important;
2549
+ text-overflow: clip !important;
2550
+ line-height: normal !important;
2551
+ }
2552
+
2553
+ .bgrid-body-table > tbody > tr.bgrid-detail-row > td[data-none] {
2554
+ padding: 0 !important;
2555
+ margin: 0 !important;
2556
+ border-top: none !important;
2557
+ border-left: none !important;
2558
+ border-right: none !important;
2559
+ border-bottom: 1px solid var(--bgrid-border-color-base) !important;
2560
+ background-color: var(--bgrid-body-bg) !important;
2561
+ max-height: none !important;
2562
+ }
2563
+
2564
+ .bgrid-body-table > tbody > tr.bgrid-detail-row > td.bgrid-detail-cell > * {
2565
+ max-height: none !important;
2566
+ }
2567
+
2568
+ .bgrid-master-detail-panel {
2569
+ box-sizing: border-box;
2570
+ overflow: auto;
2571
+ pointer-events: auto;
2572
+ background-color: var(--bgrid-body-bg);
2573
+ height: calc(var(--bgrid-item-cell-height) - 1px);
2574
+ min-height: calc(var(--bgrid-item-cell-height) - 1px);
2575
+ max-height: calc(var(--bgrid-item-cell-height) - 1px) !important;
2576
+ max-width: 100%;
2577
+ }
2578
+
2579
+ .bgrid-detail-frozen-row,
2580
+ .bgrid-detail-spacer-row {
2581
+ pointer-events: none;
2582
+ max-height: none !important;
2583
+ }
2584
+
2585
+ .bgrid-body-table > tbody > tr.bgrid-detail-frozen-row > td,
2586
+ .bgrid-body-table > tbody > tr.bgrid-detail-spacer-row > td {
2587
+ padding: 0 !important;
2588
+ margin: 0 !important;
2589
+ border-top: none !important;
2590
+ border-left: none !important;
2591
+ border-right: none !important;
2592
+ border-bottom: 1px solid var(--bgrid-border-color-base) !important;
2593
+ background-color: var(--bgrid-body-bg) !important;
2594
+ max-height: none !important;
2595
+ height: inherit !important;
2596
+ }
2597
+
2448
2598
  .bgrid-editor-icon {
2449
2599
  position: relative;
2450
2600
  z-index: 31;
package/types/BGrid.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import * as React from 'react';
2
2
  import { BGridProps } from './types';
3
- export declare function BGrid<T = Record<string, any>>({ ref, width, height, headerHeight, footerHeight, summaryHeight, itemHeight, itemPadding, getRowHeight, columns, columnsGroup, columnGroups, onChangeColumns, frozenColumnIndex, frozenRowCount, data, page, scrollbar, status, pagination, bottomBarHeight, scrollTop, scrollLeft, className, style, rowChecked, sort, onClick, loading, spinning, disabled, rowKey, selectedRowKey, editable, onChangeData, showLineNumber, msg, getRowClassName, editTrigger, cellMergeOptions, cellSelectionOptions, cellNavigationOptions, variant, summary, columnSortable, reorder, pivot, dataControl, icons, columnVisibility, searchOptions, contextMenuOptions, tree, }: BGridProps<T>): React.JSX.Element;
3
+ export declare function BGrid<T = Record<string, any>>({ ref, width, height, headerHeight, footerHeight, summaryHeight: explicitSummaryHeight, summaryRowHeight, itemHeight, itemPadding, getRowHeight, columns, columnsGroup, columnGroups, onChangeColumns, frozenColumnIndex, frozenRowCount, data, page, scrollbar, status, pagination, bottomBarHeight, scrollTop, scrollLeft, className, style, rowChecked, sort, onClick, loading, spinning, disabled, rowKey, selectedRowKey, editable, onChangeData, showLineNumber, msg, getRowClassName, editTrigger, cellMergeOptions, cellSelectionOptions, cellNavigationOptions, variant, summary, columnSortable, reorder, pivot, dataControl, icons, columnVisibility, searchOptions, contextMenuOptions, tree, masterDetail, }: BGridProps<T>): React.JSX.Element;
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ import type { BGridColumn, BGridDataItem } from '../types';
3
+ interface Props<T> {
4
+ column: BGridColumn<T>;
5
+ item: BGridDataItem<T>;
6
+ sourceIndex: number;
7
+ children: React.ReactNode;
8
+ }
9
+ export declare function MasterDetailCell<T>({ column, item, sourceIndex, children }: Props<T>): React.JSX.Element;
10
+ export interface MasterDetailRowProps<T> {
11
+ item: BGridDataItem<T>;
12
+ sourceIndex: number;
13
+ visibleIndex: number;
14
+ detailHeight: number;
15
+ isLeftRegion: boolean;
16
+ viewportWidth: number;
17
+ colSpan: number;
18
+ frozenColumnsWidth?: number;
19
+ }
20
+ export declare function MasterDetailRow<T>({ item, sourceIndex, visibleIndex, detailHeight, isLeftRegion, viewportWidth, colSpan, frozenColumnsWidth, }: MasterDetailRowProps<T>): React.JSX.Element | null;
21
+ export {};
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import type { BGridDataItem, BGridMasterDetailIcons, BGridMasterDetailOptions } from '../types';
3
+ export interface BGridMasterDetailContextValue {
4
+ gridId: string;
5
+ expandColumnId: string;
6
+ icons?: BGridMasterDetailIcons;
7
+ expandAriaLabel: string;
8
+ collapseAriaLabel: string;
9
+ disabled: boolean;
10
+ expandedKeysSet: ReadonlySet<React.Key>;
11
+ getRowKey: (values: unknown) => React.Key | undefined;
12
+ hasDetail: (item: BGridDataItem<any>, sourceIndex: number) => boolean;
13
+ detailRender: BGridMasterDetailOptions<any>['detailRender'];
14
+ toggle: (rowKey: React.Key, item: BGridDataItem<any>, sourceIndex: number) => void;
15
+ collapse: (rowKey: React.Key) => void;
16
+ getToggleElementId: (rowKey: React.Key) => string;
17
+ getDetailElementId: (rowKey: React.Key) => string;
18
+ }
19
+ export declare const MasterDetailContext: React.Context<BGridMasterDetailContextValue | undefined>;
20
+ export declare function useMasterDetailContext(): BGridMasterDetailContextValue | undefined;
@@ -13,6 +13,7 @@ interface Props<T> {
13
13
  status?: BGridResolvedStatusOptions;
14
14
  pagination?: BGridResolvedPaginationViewOptions;
15
15
  summaryHeight?: number;
16
+ summaryRowHeight?: number;
16
17
  itemHeight?: number;
17
18
  itemPadding?: number;
18
19
  rowHeightMetrics: BGridRowHeightMetrics;
@@ -29,8 +29,9 @@ interface Props {
29
29
  onRowReorderPointerDown?: (event: React.PointerEvent<HTMLButtonElement>, rowIndex: number) => void;
30
30
  onRowReorderKeyDown?: (event: React.KeyboardEvent<HTMLButtonElement>, rowIndex: number) => void;
31
31
  rowHeightMetrics?: BGridRowHeightMetrics;
32
+ viewportWidth?: number;
32
33
  }
33
- declare function TableBody({ rowKeyRegistry, region, rowRange, style, role, quadrant, allowRowReorder, onRowReorderPointerDown, onRowReorderKeyDown, rowHeightMetrics, }: Props): React.JSX.Element;
34
+ declare function TableBody({ rowKeyRegistry, region, rowRange, style, role, quadrant, allowRowReorder, onRowReorderPointerDown, onRowReorderKeyDown, rowHeightMetrics, viewportWidth, }: Props): React.JSX.Element;
34
35
  interface BodyTableProps extends React.TableHTMLAttributes<HTMLTableElement> {
35
36
  variant: BGridProps<any>['variant'];
36
37
  }
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { StoreApi } from 'zustand';
4
4
  import { AppModel, AppStore } from '../types';
5
- export type AppStoreInitialState<T = any> = Partial<Pick<AppModel<T>, 'width' | 'height' | 'headerHeight' | 'footerHeight' | 'bottomBarHeight' | 'scrollbar' | 'status' | 'pagination' | 'summaryHeight' | 'itemHeight' | 'itemPadding' | 'frozenColumnIndex' | 'frozenRowCount' | 'frozenRowsHeight' | 'frozenColumnsWidth' | 'columns' | 'columnsGroup' | 'columnGroups' | 'data' | 'sourceData' | 'sourceIndexByVisibleIndex' | 'visibleIndexBySourceIndex' | 'contentBodyHeight' | 'displayItemCount' | 'checkedIndexesMap' | 'rowChecked' | 'checkedAll' | 'sort' | 'sortParams' | 'dataQuery' | 'activeCell' | 'activeCellHost' | 'cellInteractionSession' | 'cellNavigationOptions' | 'dataControl' | 'filterDrafts' | 'activeToolboxColumnId' | 'columnVisibilityState' | 'searchOptions' | 'contextMenuOptions' | 'searchOpen' | 'searchQuery' | 'searchStatus' | 'searchMatches' | 'activeSearchMatchIndex' | 'contextMenuState' | 'icons' | 'page' | 'displayPaginationLength' | 'loading' | 'disabled' | 'spinning' | 'scrollTop' | 'scrollLeft' | 'rowKey' | 'selectedRowKey' | 'editable' | 'editTrigger' | 'showLineNumber' | 'msg' | 'getRowClassName' | 'cellMergeOptions' | 'variant' | 'summary' | 'columnSortable' | 'reorder' | 'className' | 'style' | 'onClick' | 'onChangeColumns' | 'onChangeData' | 'onLoadMore'>>;
5
+ export type AppStoreInitialState<T = any> = Partial<Pick<AppModel<T>, 'width' | 'height' | 'headerHeight' | 'footerHeight' | 'bottomBarHeight' | 'scrollbar' | 'status' | 'pagination' | 'summaryHeight' | 'summaryRowHeight' | 'itemHeight' | 'itemPadding' | 'frozenColumnIndex' | 'frozenRowCount' | 'frozenRowsHeight' | 'frozenColumnsWidth' | 'columns' | 'columnsGroup' | 'columnGroups' | 'data' | 'sourceData' | 'sourceIndexByVisibleIndex' | 'visibleIndexBySourceIndex' | 'contentBodyHeight' | 'displayItemCount' | 'checkedIndexesMap' | 'rowChecked' | 'checkedAll' | 'sort' | 'sortParams' | 'dataQuery' | 'activeCell' | 'activeCellHost' | 'cellInteractionSession' | 'cellNavigationOptions' | 'dataControl' | 'filterDrafts' | 'activeToolboxColumnId' | 'columnVisibilityState' | 'searchOptions' | 'contextMenuOptions' | 'searchOpen' | 'searchQuery' | 'searchStatus' | 'searchMatches' | 'activeSearchMatchIndex' | 'contextMenuState' | 'icons' | 'page' | 'displayPaginationLength' | 'loading' | 'disabled' | 'spinning' | 'scrollTop' | 'scrollLeft' | 'rowKey' | 'selectedRowKey' | 'editable' | 'editTrigger' | 'showLineNumber' | 'msg' | 'getRowClassName' | 'cellMergeOptions' | 'variant' | 'summary' | 'columnSortable' | 'reorder' | 'className' | 'style' | 'onClick' | 'onChangeColumns' | 'onChangeData' | 'onLoadMore'>>;
6
6
  interface AppStoreProviderProps<T = any> {
7
7
  children: ReactNode;
8
8
  initialState?: AppStoreInitialState<T>;
package/types/types.d.ts CHANGED
@@ -219,6 +219,7 @@ export interface BGridCellMergeColumn {
219
219
  export interface BGridSummaryItemRenderProps<T> {
220
220
  column: BGridColumn<T>;
221
221
  columnIndex: number;
222
+ rowIndex?: number;
222
223
  data: BGridDataItem<T>[];
223
224
  }
224
225
  export interface BGridSummaryColumn<T> {
@@ -226,9 +227,22 @@ export interface BGridSummaryColumn<T> {
226
227
  align?: AlignDirection;
227
228
  colSpan?: number;
228
229
  className?: string;
230
+ style?: React.CSSProperties;
229
231
  getClassName?: (key: string | string[]) => string;
230
232
  itemRender?: (props: BGridSummaryItemRenderProps<T>) => React.ReactNode;
231
233
  }
234
+ export interface BGridSummaryRow<T> {
235
+ id?: string | number;
236
+ className?: string;
237
+ style?: React.CSSProperties;
238
+ height?: number;
239
+ columns: BGridSummaryColumn<T>[];
240
+ }
241
+ export interface BGridSummaryOptions<T> {
242
+ columns?: BGridSummaryColumn<T>[];
243
+ rows?: (BGridSummaryRow<T> | BGridSummaryColumn<T>[])[];
244
+ position: 'top' | 'bottom';
245
+ }
232
246
  export declare enum BGridDataItemStatus {
233
247
  new = 0,
234
248
  edit = 1,
@@ -791,6 +805,7 @@ export interface BGridProps<T> {
791
805
  footerHeight?: number;
792
806
  bottomBarHeight?: number;
793
807
  summaryHeight?: number;
808
+ summaryRowHeight?: number;
794
809
  itemHeight?: number;
795
810
  itemPadding?: number;
796
811
  /**
@@ -897,10 +912,7 @@ export interface BGridProps<T> {
897
912
  };
898
913
  cellNavigationOptions?: BGridCellNavigationOptions;
899
914
  variant?: 'default' | 'vertical-bordered';
900
- summary?: {
901
- columns: BGridSummaryColumn<T>[];
902
- position: 'top' | 'bottom';
903
- };
915
+ summary?: BGridSummaryOptions<T>;
904
916
  columnSortable?: boolean;
905
917
  reorder?: BGridReorderInfo<T>;
906
918
  reorderingInfo?: BGridReorderingInfo;
@@ -913,6 +925,8 @@ export interface BGridProps<T> {
913
925
  contextMenuOptions?: BGridContextMenuOptions<T>;
914
926
  /** Enables hierarchical rows from flat data related by rowKey and parentRowKey. */
915
927
  tree?: BGridTreeOptions<T>;
928
+ /** Enables master-detail expandable rows with full-width detail panels or nested grids. */
929
+ masterDetail?: BGridMasterDetailOptions<T>;
916
930
  }
917
931
  export interface BGridTreeIcons {
918
932
  expanded?: React.ReactNode;
@@ -949,6 +963,54 @@ export interface BGridTreeOptions<T> {
949
963
  expandAriaLabel?: string;
950
964
  collapseAriaLabel?: string;
951
965
  }
966
+ export type BGridMasterDetailExpandMode = 'multiple' | 'single';
967
+ export interface BGridMasterDetailRenderProps<T> {
968
+ item: BGridDataItem<T>;
969
+ rowKey: React.Key;
970
+ sourceIndex: number;
971
+ visibleIndex: number;
972
+ expanded: true;
973
+ collapse: () => void;
974
+ }
975
+ export interface BGridMasterDetailIcons {
976
+ expanded?: React.ReactNode;
977
+ collapsed?: React.ReactNode;
978
+ }
979
+ export interface BGridMasterDetailChangeEvent<T> {
980
+ rowKey: React.Key;
981
+ expanded: boolean;
982
+ item: BGridDataItem<T>;
983
+ sourceIndex: number;
984
+ }
985
+ export interface BGridMasterDetailOptions<T> {
986
+ /** Enables or disables master-detail row expansion. Defaults to true when masterDetail is provided. */
987
+ enabled?: boolean;
988
+ /** Custom renderer for the expanded detail region. */
989
+ detailRender: (props: BGridMasterDetailRenderProps<T>) => React.ReactNode;
990
+ /**
991
+ * Detail area total height in pixels, including padding and borders.
992
+ * Accepts a fixed number or a function that returns the height for a given row. Defaults to 200.
993
+ */
994
+ detailRowHeight?: number | ((item: BGridDataItem<T>, sourceIndex: number) => number);
995
+ /** Column ID that renders the toggle button. Defaults to the first visible column. */
996
+ expandColumnId?: string;
997
+ /** Determines whether a given row provides an expandable detail area. Defaults to true for all rows. */
998
+ hasDetail?: (item: BGridDataItem<T>, sourceIndex: number) => boolean;
999
+ /** 'single' allows only one row expanded at a time (accordion). Defaults to 'multiple'. */
1000
+ expandMode?: BGridMasterDetailExpandMode;
1001
+ /** Controlled expanded row keys. */
1002
+ expandedRowKeys?: readonly React.Key[];
1003
+ /** Initial expanded row keys for uncontrolled usage. */
1004
+ defaultExpandedRowKeys?: readonly React.Key[];
1005
+ /** Callback triggered when the expanded row keys change through user interaction. */
1006
+ onExpandedRowKeysChange?: (keys: React.Key[], event: BGridMasterDetailChangeEvent<T>) => void;
1007
+ /** Custom expand/collapse icons. */
1008
+ icons?: BGridMasterDetailIcons;
1009
+ /** Accessibility label for the expand button. */
1010
+ expandAriaLabel?: string;
1011
+ /** Accessibility label for the collapse button. */
1012
+ collapseAriaLabel?: string;
1013
+ }
952
1014
  export interface BGridTreeChangeDataMeta {
953
1015
  rowKey: React.Key;
954
1016
  parentRowKey?: React.Key;
@@ -982,6 +1044,8 @@ export interface AppModelColumn<T> extends BGridColumn<T> {
982
1044
  left: number;
983
1045
  /** @internal Marks the single column that hosts tree indentation and folding controls. */
984
1046
  treeCell?: boolean;
1047
+ /** @internal Marks the single column that hosts master-detail expand/collapse toggle controls. */
1048
+ masterDetailCell?: boolean;
985
1049
  }
986
1050
  export interface AppModel<T> extends BGridProps<T> {
987
1051
  initialized: boolean;
@@ -989,6 +1053,7 @@ export interface AppModel<T> extends BGridProps<T> {
989
1053
  footerHeight: number;
990
1054
  bottomBarHeight: number;
991
1055
  summaryHeight: number;
1056
+ summaryRowHeight?: number;
992
1057
  itemHeight: number;
993
1058
  itemPadding: number;
994
1059
  frozenColumnIndex: number;
@@ -1099,6 +1164,7 @@ export interface AppActions<T> {
1099
1164
  setFooterHeight: (footerHeight: number) => void;
1100
1165
  setBottomBarHeight: (bottomBarHeight: number) => void;
1101
1166
  setSummaryHeight: (summaryHeight: number) => void;
1167
+ setSummaryRowHeight: (summaryRowHeight?: number) => void;
1102
1168
  setItemHeight: (itemHeight: number) => void;
1103
1169
  setItemPadding: (itemPadding: number) => void;
1104
1170
  setFrozenColumnIndex: (frozenColumnIndex: number) => void;
@@ -24,8 +24,10 @@ export interface BGridSelectionGeometryParams {
24
24
  frozenRowCount: number;
25
25
  frozenColumnsWidth: number;
26
26
  rowOffsets?: ArrayLike<number>;
27
+ rowHeights?: ArrayLike<number>;
28
+ detailHeights?: ArrayLike<number>;
27
29
  }
28
- export declare function getCellSelectionFragments({ ranges, columns, rowCount, rowHeight, frozenColumnCount, frozenRowCount, frozenColumnsWidth, rowOffsets, }: BGridSelectionGeometryParams): BGridSelectionFragment[];
30
+ export declare function getCellSelectionFragments({ ranges, columns, rowCount, rowHeight, frozenColumnCount, frozenRowCount, frozenColumnsWidth, rowOffsets, rowHeights, detailHeights, }: BGridSelectionGeometryParams): BGridSelectionFragment[];
29
31
  export declare function clipCellSelectionFragment(fragment: BGridSelectionFragment, viewport: {
30
32
  left: number;
31
33
  top: number;
@@ -30,3 +30,4 @@ export * from './checkedIndexes';
30
30
  export * from './exportData';
31
31
  export * from './exportCsv';
32
32
  export * from './exportExcel';
33
+ export * from './summary';
@@ -1,11 +1,25 @@
1
+ import * as React from 'react';
1
2
  import { BGridDataItem, BGridProps } from '../types';
3
+ export interface MasterDetailHeightOptions<T> {
4
+ expandedKeysSet: ReadonlySet<React.Key>;
5
+ getRowKey: (values: unknown, index: number) => React.Key | undefined;
6
+ getDetailHeight: (item: BGridDataItem<T>, sourceIndex: number) => number;
7
+ hasDetail?: (item: BGridDataItem<T>, sourceIndex: number) => boolean;
8
+ sourceIndexByVisibleIndex?: readonly number[];
9
+ }
2
10
  export interface BGridRowHeightMetrics {
11
+ /** Master row heights (for <tr> and cell rendering). */
3
12
  heights: Float64Array;
13
+ /** Layout offsets including detail heights (for virtual scrolling, paddingTop, selection overlays, total height). */
4
14
  offsets: Float64Array;
15
+ /** Total layout height including all rows and expanded details. */
5
16
  totalHeight: number;
17
+ /** Whether layout heights are variable. */
6
18
  variable: boolean;
19
+ /** Detail panel heights for each visible row (0 if row has no detail or is not expanded). */
20
+ detailHeights?: Float64Array;
7
21
  }
8
- export declare function createRowHeightMetrics<T>(data: readonly BGridDataItem<T>[], fallbackHeight: number, getRowHeight?: BGridProps<T>['getRowHeight']): BGridRowHeightMetrics;
22
+ export declare function createRowHeightMetrics<T>(data: readonly BGridDataItem<T>[], fallbackHeight: number, getRowHeight?: BGridProps<T>['getRowHeight'], masterDetail?: MasterDetailHeightOptions<T>): BGridRowHeightMetrics;
9
23
  /** Returns the row containing offset, or rowCount when offset is at/after the end. */
10
24
  export declare function getRowIndexAtOffset(offsets: ArrayLike<number>, offset: number): number;
11
25
  /** Returns the first offset index whose value is greater than or equal to target. */
@@ -0,0 +1,13 @@
1
+ import { BGridColumn, BGridSummaryColumn, BGridSummaryOptions, BGridSummaryRow } from '../types';
2
+ export declare const DEFAULT_SUMMARY_ROW_HEIGHT = 30;
3
+ export declare function normalizeSummaryRows<T>(summary?: BGridSummaryOptions<T>): BGridSummaryRow<T>[];
4
+ export declare function computeSummaryHeight<T>(options: {
5
+ summary?: BGridSummaryOptions<T>;
6
+ summaryHeight?: number;
7
+ summaryRowHeight?: number;
8
+ }): number;
9
+ export declare function buildSummaryRowCells<T>(columns: BGridColumn<T>[], summaryColumns?: BGridSummaryColumn<T>[], startIndex?: number): ({
10
+ column: BGridColumn<T>;
11
+ columnIndex: number;
12
+ summaryColumn?: BGridSummaryColumn<T>;
13
+ } | null)[];