@opencorestack/opengridx 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/index.d.ts +30 -0
- package/dist/opengridx.css +1 -1
- package/dist/opengridx.es.js +8566 -8130
- package/dist/opengridx.es.js.map +1 -1
- package/dist/opengridx.umd.js +15 -15
- package/dist/opengridx.umd.js.map +1 -1
- package/docs/API_REFERENCE.md +3 -2
- package/docs/architecture/datagrid-orchestration.md +46 -29
- package/docs/architecture/grid-row-meta.md +1 -1
- package/docs/customization/slots-api.md +1 -1
- package/docs/customization/theming.md +43 -0
- package/docs/features/virtualization.md +16 -2
- package/docs/performance.md +3 -1
- package/lib/components/AiAssistant/GridAiAssistantPanel.css +3 -1
- package/lib/components/Cell/Cell.css +4 -2
- package/lib/components/ColumnGroupHeader/ColumnGroupHeader.css +2 -2
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +3 -1
- package/lib/components/DataGrid/DataGrid.css +9 -9
- package/lib/components/DataGrid/DataGrid.tsx +163 -671
- package/lib/components/DataGrid/GridRoot.tsx +239 -0
- package/lib/components/DataGrid/GridViewport.tsx +314 -0
- package/lib/components/FilterPanel/FilterPanel.css +9 -8
- package/lib/components/Header/ColumnMenu.css +4 -3
- package/lib/components/Header/Header.css +5 -4
- package/lib/components/HeaderFilter/HeaderFilter.css +1 -1
- package/lib/components/Pagination/Pagination.css +1 -1
- package/lib/components/Row/Row.css +2 -2
- package/lib/components/Toolbar/GridToolbar.css +8 -7
- package/lib/components/Toolbar/PivotPanel.css +3 -3
- package/lib/hooks/core/useGridDevWarnings.ts +3 -1
- package/lib/hooks/core/useGridEditPipeline.ts +55 -0
- package/lib/hooks/core/useGridRangeEditing.ts +129 -0
- package/lib/hooks/core/useGridRenderWindow.ts +66 -0
- package/lib/hooks/core/useGridScrollViewport.ts +42 -0
- package/lib/hooks/core/useGridSelectionAndStateApi.ts +61 -0
- package/lib/hooks/core/useGridToolbarStack.ts +49 -0
- package/lib/hooks/core/useGridViewApis.ts +46 -0
- package/lib/styles/base/variables.css +12 -0
- package/lib/theme/DataGridThemeProvider.tsx +15 -0
- package/lib/theme/__baseline__/default-theme.darwin.chromium.json +1503 -0
- package/lib/theme/__baseline__/default-theme.darwin.firefox.json +1503 -0
- package/lib/theme/__baseline__/default-theme.darwin.webkit.json +1503 -0
- package/lib/theme/types.ts +31 -0
- package/lib/types/ai.ts +109 -0
- package/lib/types/api.ts +169 -0
- package/lib/types/columns.ts +341 -0
- package/lib/types/dataSource.ts +40 -0
- package/lib/types/editing.ts +77 -0
- package/lib/types/export.ts +164 -0
- package/lib/types/filtering.ts +52 -0
- package/lib/types/grouping.ts +27 -0
- package/lib/types/index.ts +18 -1702
- package/lib/types/locale.ts +51 -0
- package/lib/types/props.ts +405 -0
- package/lib/types/rows.ts +132 -0
- package/lib/types/selection.ts +66 -0
- package/lib/types/slots.ts +56 -0
- package/lib/types/sorting.ts +25 -0
- package/lib/types/state.ts +35 -0
- package/llms.txt +1 -1
- package/package.json +4 -2
package/docs/API_REFERENCE.md
CHANGED
|
@@ -648,8 +648,9 @@ Context provider for overriding the grid's visual system.
|
|
|
648
648
|
- **`colors`**: `primary`, `primaryDark`, `primaryLight`, `primaryFocus`, `secondary*`, `success`, `warning`, `error`, `info`, `white`, `black`, `gray` (`{ 50 … 900 }`). Toolbar, menu, selection and focus accents derive from `primary*` unless set directly.
|
|
649
649
|
- **`typography`**: `fontFamily`, `fontFamilyMono`, `fontSizeXs` … `fontSizeXl`.
|
|
650
650
|
- **`spacing`**: `xs` … `xxl`. **`borders`**: `widthThin/Medium/Thick`, `radiusSm` … `radiusXl`, `color`, `colorHover`. **`shadows`**: `sm` … `xl`.
|
|
651
|
-
- **`grid`**: surfaces (`background`, `borderColor`, `headerBackground`, `headerText`, `headerHoverBackground`, `headerSortedBackground`, `rowText`, `rowHoverBackground`, `rowAlternateBackground`, `rowSelectedBackground`, `rowSelectedHoverBackground`, `cellFocusBorder`, `rangeBackground`, `rangeBorder` (v3.3), `pinnedLeftShadow`, `pinnedRightShadow`, `checkboxBg`, `checkboxBorder`), sizing (`rowHeightCompact`, `rowHeightStandard`, `rowHeightComfortable`, `headerHeight` in px, read by the grid's layout; the `rowHeight` / `headerHeight` props win), `cellPaddingX`, `cellPaddingY`, `cellFontSize`, `headerFontSize
|
|
652
|
-
- **`
|
|
651
|
+
- **`grid`**: surfaces (`background`, `borderColor`, `headerBackground`, `headerText`, `headerHoverBackground`, `headerSortedBackground`, `rowText`, `rowHoverBackground`, `rowAlternateBackground`, `rowSelectedBackground`, `rowSelectedHoverBackground`, `cellFocusBorder`, `rangeBackground`, `rangeBorder` (v3.3), `pinnedLeftShadow`, `pinnedRightShadow`, `checkboxBg`, `checkboxBorder`), sizing (`rowHeightCompact`, `rowHeightStandard`, `rowHeightComfortable`, `headerHeight` in px, read by the grid's layout; the `rowHeight` / `headerHeight` props win), `cellPaddingX`, `cellPaddingY`, `cellFontSize`, `headerFontSize`; v3.7: fonts (`headerFontFamily`, `headerFontWeight`, `cellFontFamily`, `cellFontWeight`), `headerPaddingX`, outer `borderWidth` and `borderRadius`, dividers (`columnDividerWidth`, `headerColumnDividerWidth`, `rowDividerWidth`, `columnDividerColor`, `rowDividerColor`; `0` hides a divider).
|
|
652
|
+
- **`overlays`**: colours (`background`, `text`, `border`, `shadow`, `item*`) and, v3.7, `fontFamily`, `fontWeight`, `fontSize` for menus and panels.
|
|
653
|
+
- **`toolbar`**, **`scrollbar`** (`thumbColor`, `trackColor`, `size`), **`skeleton`** (`baseColor`, `highlightColor`), **`transitions`**.
|
|
653
654
|
|
|
654
655
|
Presets: `darkTheme`, `roseTheme`, `emeraldTheme`, `amberTheme`, `compactTheme`. See [Theming](customization/theming.md).
|
|
655
656
|
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
# DataGrid orchestration
|
|
2
2
|
|
|
3
3
|
`lib/components/DataGrid/DataGrid.tsx` is the orchestration layer: it destructures the props, calls
|
|
4
|
-
hooks and pure utils in a fixed order, and renders
|
|
5
|
-
listed here; add new logic there, not in the component.
|
|
4
|
+
hooks and pure utils in a fixed order, and renders `GridRoot` with one props object. Feature logic lives
|
|
5
|
+
in the hooks and utils listed here; add new logic there, not in the component.
|
|
6
|
+
|
|
7
|
+
Some contiguous runs of hooks are wrapped in a **composite hook** (`hooks/core/`) that calls its members in
|
|
8
|
+
the same order, so `DataGrid.tsx` calls one hook where the table below lists several (marked with the
|
|
9
|
+
composite's name). A composite only ever wraps consecutive steps: a hook that has to run between two of its
|
|
10
|
+
members goes inside it at that position, never before or after the composite.
|
|
11
|
+
|
|
12
|
+
| Composite | Steps |
|
|
13
|
+
| :--- | :--- |
|
|
14
|
+
| `useGridEditPipeline` | 12a–13 |
|
|
15
|
+
| `useGridSelectionAndStateApi` | 23–24 |
|
|
16
|
+
| `useGridViewApis` | 30–31a |
|
|
17
|
+
| `useGridScrollViewport` | 32–33 |
|
|
18
|
+
| `useGridRangeEditing` | 36a–36d |
|
|
19
|
+
| `useGridRenderWindow` | 38–41 |
|
|
20
|
+
| `useGridToolbarStack` | 44–46 |
|
|
6
21
|
|
|
7
22
|
## Why the order matters
|
|
8
23
|
|
|
@@ -47,9 +62,9 @@ in an effect, so **keep the call order when you move or add a hook**. In particu
|
|
|
47
62
|
| 10 | `useGridRowIdOf` | `hooks/core/useGridRowIdOf.ts` | `getRowIdOf` and its stable event-handler twin |
|
|
48
63
|
| 11 | `useGridApiRefBinding` | `hooks/core/useGridApiRefBinding.ts` | Binds the `apiRef` prop (layout effect) |
|
|
49
64
|
| 12 | `useGridHierarchy` | `hooks/core/useGridHierarchy.ts` | `useTreeData` + `useRowGrouping`, the active handlers and `rowMetaMap` |
|
|
50
|
-
| 12a | `useGridEditCommitChannel` | `hooks/core/useGridUndoRedo.ts` | Stable `emit` / `setListener` pair: the commit paths below report stored changes through `emit`, and `useGridUndoRedo` (36c) registers the listener (v3.4) |
|
|
51
|
-
| 12b | `useGridBatchEdit` | `hooks/features/useGridBatchEdit.ts` | Batch edits (v3.4): `applyEdits` runs `valueSetter` → `processRowUpdate` once per row (rows in parallel, failures isolated and sent to `onProcessRowUpdateError`) and stores every successful row in one `replaceRows` update; `getRow` sees rows stored since the last render; `storeRow` stores a single edit |
|
|
52
|
-
| 13 | `useGridEditing` | `hooks/features/useGridEditing.ts` | Cell editing state and handlers; stores through `useGridBatchEdit.storeRow` and reports the committed change to the channel |
|
|
65
|
+
| 12a | `useGridEditCommitChannel` (in `useGridEditPipeline`) | `hooks/core/useGridUndoRedo.ts` | Stable `emit` / `setListener` pair: the commit paths below report stored changes through `emit`, and `useGridUndoRedo` (36c) registers the listener (v3.4) |
|
|
66
|
+
| 12b | `useGridBatchEdit` (in `useGridEditPipeline`) | `hooks/features/useGridBatchEdit.ts` | Batch edits (v3.4): `applyEdits` runs `valueSetter` → `processRowUpdate` once per row (rows in parallel, failures isolated and sent to `onProcessRowUpdateError`) and stores every successful row in one `replaceRows` update; `getRow` sees rows stored since the last render; `storeRow` stores a single edit |
|
|
67
|
+
| 13 | `useGridEditing` (in `useGridEditPipeline`) | `hooks/features/useGridEditing.ts` | Cell editing state and handlers; stores through `useGridBatchEdit.storeRow` and reports the committed change to the channel |
|
|
53
68
|
| 14 | `useGridLiveRowSelection` | `hooks/core/useGridLiveRowSelection.ts` | Selection without removed rows |
|
|
54
69
|
| 15 | `useGridDataSource` | `hooks/features/useGridDataSource.ts` | Server fetching |
|
|
55
70
|
| 16 | `useServerTreeChildren` | `hooks/features/useServerTreeChildren.ts` | Lazy server tree children |
|
|
@@ -59,46 +74,48 @@ in an effect, so **keep the call order when you move or add a hook**. In particu
|
|
|
59
74
|
| 20 | `useGridRowPipeline` | `hooks/core/useGridRowPipeline.ts` | Filter → pin → sort → paginate |
|
|
60
75
|
| 21 | `useGridPageCorrection` | `hooks/core/useGridPageCorrection.ts` | Moves a page left past the end back to the last page |
|
|
61
76
|
| 22 | `getPaginationRowCount` (pure) | `utils/pagination/index.ts` | What the pager pages through |
|
|
62
|
-
| 23 | `useGridRowInteractions` | `hooks/core/useGridRowInteractions.ts` | Row selection, `handleRowClick`, `handleSelectionChange` |
|
|
63
|
-
| 24 | `useGridApiMethods` | `hooks/core/useGridApiMethods.ts` | State API methods (`getAllFilteredRows` via `utils/gridApiRows.ts`); since v3.5 also `setSortModel`, `setRowGroupingModel`, `setAggregationModel`, `setColumnVisibilityModel`, `setPivotModel` and `getGridAiState` |
|
|
77
|
+
| 23 | `useGridRowInteractions` (in `useGridSelectionAndStateApi`) | `hooks/core/useGridRowInteractions.ts` | Row selection, `handleRowClick`, `handleSelectionChange` |
|
|
78
|
+
| 24 | `useGridApiMethods` (in `useGridSelectionAndStateApi`) | `hooks/core/useGridApiMethods.ts` | State API methods (`getAllFilteredRows` via `utils/gridApiRows.ts`); since v3.5 also `setSortModel`, `setRowGroupingModel`, `setAggregationModel`, `setColumnVisibilityModel`, `setPivotModel` and `getGridAiState` |
|
|
64
79
|
| 25 | `useRowReorder` | `hooks/useRowReorder.ts` | Row drag-reorder |
|
|
65
80
|
| 26 | `useAggregation` | `hooks/features/useAggregation.ts` | Footer aggregation result |
|
|
66
81
|
| 27 | `useGridAggregationApi` | `hooks/core/useGridAggregationApi.ts` | `getAggregationResult`, `getAggregationModel`, `getGroupedExportRows` |
|
|
67
82
|
| 28 | `useLayout` | `hooks/core/useLayout.ts` | Row heights, pinned column split, widths |
|
|
68
83
|
| 29 | `useGridSpanning` | `hooks/features/useGridSpanning.ts` | Row/column spans |
|
|
69
84
|
| 29a | `useGridCellSelection` | `hooks/core/useGridCellSelection.ts` | Cell range (v3.3): the model's range resolved against `allRenderableRows` and the data columns of `navigationColumns` (grown over spans), the render rectangle, pointer drag with auto-scroll and Shift+click, the Shift-key handlers for the keyboard hook, copy text, status-bar totals and the debounced live-region text. Inert while `cellSelection` is off |
|
|
70
|
-
| 30 | `useGridClipboardApi` | `hooks/core/useGridClipboardApi.ts` | Ctrl/Cmd+C and `copySelectedRows`; with `cellSelection` the shortcut copies the range (`getCellRangeCopyText`) |
|
|
71
|
-
| 31 | `useGridScrollToIndexesApi` | `hooks/core/useGridScrollToIndexesApi.ts` | `scrollToIndexes` |
|
|
72
|
-
| 31a | `useGridColumnAutosize` | `hooks/core/useGridColumnAutosize.ts` | `autosizeColumn` / `autosizeColumns` on the API, and the resize handle's auto-size handler (v3.1) |
|
|
73
|
-
| 32 | `useGridViewport` | `hooks/core/useGridViewport.ts` | Scroll sync, viewport measurement, viewport callback ref |
|
|
74
|
-
| 32a | `useGridMaxContentHeight` | `hooks/core/useGridMaxContentHeight.ts` | The tallest element this browser lays out (`utils/maxElementHeight.ts`, measured once per document after mount; `undefined` until then, `Infinity` without a layout engine) |
|
|
75
|
-
| 33 | `useGridVirtualization` | `hooks/core/useGridVirtualization.ts` | Render window; `virtualContainerHeight` caps the rows' container to `maxContentHeight` (Firefox collapses taller elements) |
|
|
85
|
+
| 30 | `useGridClipboardApi` (in `useGridViewApis`) | `hooks/core/useGridClipboardApi.ts` | Ctrl/Cmd+C and `copySelectedRows`; with `cellSelection` the shortcut copies the range (`getCellRangeCopyText`) |
|
|
86
|
+
| 31 | `useGridScrollToIndexesApi` (in `useGridViewApis`) | `hooks/core/useGridScrollToIndexesApi.ts` | `scrollToIndexes` |
|
|
87
|
+
| 31a | `useGridColumnAutosize` (in `useGridViewApis`) | `hooks/core/useGridColumnAutosize.ts` | `autosizeColumn` / `autosizeColumns` on the API, and the resize handle's auto-size handler (v3.1) |
|
|
88
|
+
| 32 | `useGridViewport` (in `useGridScrollViewport`) | `hooks/core/useGridViewport.ts` | Scroll sync, viewport measurement, viewport callback ref |
|
|
89
|
+
| 32a | `useGridMaxContentHeight` (in `useGridScrollViewport`) | `hooks/core/useGridMaxContentHeight.ts` | The tallest element this browser lays out (`utils/maxElementHeight.ts`, measured once per document after mount; `undefined` until then, `Infinity` without a layout engine) |
|
|
90
|
+
| 33 | `useGridVirtualization` (in `useGridScrollViewport`) | `hooks/core/useGridVirtualization.ts` | Render window; `virtualContainerHeight` caps the rows' container to `maxContentHeight` (Firefox collapses taller elements) |
|
|
76
91
|
| 34 | `useGridSortHandlers` | `hooks/core/useGridHeaderHandlers.ts` | Header sort / shift-sort |
|
|
77
92
|
| 35 | `useGridKeyboardNavigation` | `hooks/core/useGridKeyboardNavigation.ts` | Focus and keyboard handling; takes `cellSelection.keyboard` (Shift+navigation, Escape, Ctrl/Cmd+A) |
|
|
78
93
|
| 36 | `useGridPointerFocusHandlers` | `hooks/core/useGridFocusHandlers.ts` | Cell and header click focus |
|
|
79
|
-
| 36a | `useGridCellSelectionApi` | `hooks/core/useGridCellSelectionApi.ts` | Keeps the range anchor and the focused cell together (layout effect: a new anchor moves focus; focus moved to another data cell collapses the range), clears a range whose corner is gone (`'dataChange'`), and installs `getCellSelectionModel`, `setCellSelectionModel`, `selectCellRange`, `clearCellSelection`, `getSelectedCells`, `copySelectedCells` (once per `apiRef`, reading the latest values from a ref) |
|
|
80
|
-
| 36b | `useGridClipboardPaste` | `hooks/core/useGridClipboardPaste.ts` | Paste and range clear (v3.4): `paste` and Delete/Backspace listeners on the grid root (only for cell targets, not editors or nested grids), TSV parsing (`utils/parsing.ts`), placement against the renderable rows and range columns (`utils/editing/targets.ts`), the batch edit, the new selection, `onBeforeClipboardPaste` / `onClipboardPaste`, and `apiRef.pasteText`. Inert without `cellSelection` except for `pasteText` |
|
|
81
|
-
| 36c | `useGridUndoRedo` | `hooks/core/useGridUndoRedo.ts` | History (v3.4, `undoRedo`): records the channel's changes, replays them as batch edits with an `expect` value per cell (stale cells skipped), queues undo/redo, selects and scrolls to the affected cells, Ctrl/Cmd+Z / Shift+Z / Ctrl+Y on the grid root, `onHistoryChange`, and `apiRef.undo` / `redo` / `canUndo` / `canRedo` / `clearHistory` |
|
|
82
|
-
| 36d | `useGridFillHandle` | `hooks/core/useGridFillHandle.ts` | Fill handle (v3.5, `cellSelection` without `disableFillHandle`): where the handle is drawn (`rowRenderProps.fillHandle`, the range's bottom-right cell or its span origin), a `pointerdown` listener on the viewport for `.ogx__cell-fill-handle` that runs `cellSelection.startTrackedDrag` (the range drag's hit testing, auto-scroll and slow-machine fallback, on pointer events so touch works), the fill itself (`utils/editing/fill.ts`: series detection, lines, `GridColDef.fillValue`) as one batch edit with source `'fill'`, the new selection, `onFill`, and Ctrl/Cmd+D / Ctrl/Cmd+R on the grid root |
|
|
94
|
+
| 36a | `useGridCellSelectionApi` (in `useGridRangeEditing`) | `hooks/core/useGridCellSelectionApi.ts` | Keeps the range anchor and the focused cell together (layout effect: a new anchor moves focus; focus moved to another data cell collapses the range), clears a range whose corner is gone (`'dataChange'`), and installs `getCellSelectionModel`, `setCellSelectionModel`, `selectCellRange`, `clearCellSelection`, `getSelectedCells`, `copySelectedCells` (once per `apiRef`, reading the latest values from a ref) |
|
|
95
|
+
| 36b | `useGridClipboardPaste` (in `useGridRangeEditing`) | `hooks/core/useGridClipboardPaste.ts` | Paste and range clear (v3.4): `paste` and Delete/Backspace listeners on the grid root (only for cell targets, not editors or nested grids), TSV parsing (`utils/parsing.ts`), placement against the renderable rows and range columns (`utils/editing/targets.ts`), the batch edit, the new selection, `onBeforeClipboardPaste` / `onClipboardPaste`, and `apiRef.pasteText`. Inert without `cellSelection` except for `pasteText` |
|
|
96
|
+
| 36c | `useGridUndoRedo` (in `useGridRangeEditing`) | `hooks/core/useGridUndoRedo.ts` | History (v3.4, `undoRedo`): records the channel's changes, replays them as batch edits with an `expect` value per cell (stale cells skipped), queues undo/redo, selects and scrolls to the affected cells, Ctrl/Cmd+Z / Shift+Z / Ctrl+Y on the grid root, `onHistoryChange`, and `apiRef.undo` / `redo` / `canUndo` / `canRedo` / `clearHistory` |
|
|
97
|
+
| 36d | `useGridFillHandle` (in `useGridRangeEditing`) | `hooks/core/useGridFillHandle.ts` | Fill handle (v3.5, `cellSelection` without `disableFillHandle`): where the handle is drawn (`rowRenderProps.fillHandle`, the range's bottom-right cell or its span origin), a `pointerdown` listener on the viewport for `.ogx__cell-fill-handle` that runs `cellSelection.startTrackedDrag` (the range drag's hit testing, auto-scroll and slow-machine fallback, on pointer events so touch works), the fill itself (`utils/editing/fill.ts`: series detection, lines, `GridColDef.fillValue`) as one batch edit with source `'fill'`, the new selection, `onFill`, and Ctrl/Cmd+D / Ctrl/Cmd+R on the grid root |
|
|
83
98
|
| 37 | `useGridColumnMenuHandlers` | `hooks/core/useGridHeaderHandlers.ts` | Column menu Hide / Pin (`pinColumnTo` in `utils/pinning`) |
|
|
84
|
-
| 38 | `useGridAriaRows` | `hooks/core/useGridAriaRows.ts` | `aria-rowcount` and `aria-rowindex` bases |
|
|
85
|
-
| 39 | `useGridSpanRowWindow` | `hooks/features/useGridSpanRenderWindow.ts` | Render window widened to whole row spans |
|
|
86
|
-
| 40 | `useGridVisibleRows` | `hooks/core/useGridVisibleRows.ts` | Pinned + virtual centre rows to render |
|
|
87
|
-
| 41 | `useGridSpanColumnWindow` | `hooks/features/useGridSpanRenderWindow.ts` | Columns to render, widened to whole column spans |
|
|
99
|
+
| 38 | `useGridAriaRows` (in `useGridRenderWindow`) | `hooks/core/useGridAriaRows.ts` | `aria-rowcount` and `aria-rowindex` bases |
|
|
100
|
+
| 39 | `useGridSpanRowWindow` (in `useGridRenderWindow`) | `hooks/features/useGridSpanRenderWindow.ts` | Render window widened to whole row spans |
|
|
101
|
+
| 40 | `useGridVisibleRows` (in `useGridRenderWindow`) | `hooks/core/useGridVisibleRows.ts` | Pinned + virtual centre rows to render |
|
|
102
|
+
| 41 | `useGridSpanColumnWindow` (in `useGridRenderWindow`) | `hooks/features/useGridSpanRenderWindow.ts` | Columns to render, widened to whole column spans |
|
|
88
103
|
| 42 | `useGridDevWarnings` | `hooks/core/useGridDevWarnings.ts` | Dev-only warnings |
|
|
89
104
|
| 43 | `useColumnGroupReorderGuard` | `hooks/features/useColumnGroupReorderGuard.ts` | Header drag-reorder kept inside column groups |
|
|
90
|
-
| 44 | `useGridColumnsPanel` | `hooks/core/useGridColumnsPanel.ts` | Columns panel (toolbar or standalone) |
|
|
91
|
-
| 45 | `useGridStylesheetWarning` | `hooks/core/useGridDevWarnings.ts` | Warns when the stylesheet is missing |
|
|
92
|
-
| 45a | `useGridAiAssistant` | `hooks/features/useGridAiAssistant.ts` | The `aiAssistant` panel (v3.5): open state, the request and its `AbortController` (Stop), applying a branded reply through the `apiRef` setters of step 24 (`utils/aiAssistant.ts`: allowed parts, the Undo snapshot, chips, chip removal), the live-region status, and `apiRef.openAiAssistant` / `closeAiAssistant`. Inert without `aiAssistant`; it runs before step 46 because the toolbar gets its Ask AI button from it |
|
|
93
|
-
| 46 | `useGridToolbarProps` | `hooks/core/useGridToolbarProps.ts` | Props for `slots.toolbar` |
|
|
105
|
+
| 44 | `useGridColumnsPanel` (in `useGridToolbarStack`) | `hooks/core/useGridColumnsPanel.ts` | Columns panel (toolbar or standalone) |
|
|
106
|
+
| 45 | `useGridStylesheetWarning` (in `useGridToolbarStack`) | `hooks/core/useGridDevWarnings.ts` | Warns when the stylesheet is missing |
|
|
107
|
+
| 45a | `useGridAiAssistant` (in `useGridToolbarStack`) | `hooks/features/useGridAiAssistant.ts` | The `aiAssistant` panel (v3.5): open state, the request and its `AbortController` (Stop), applying a branded reply through the `apiRef` setters of step 24 (`utils/aiAssistant.ts`: allowed parts, the Undo snapshot, chips, chip removal), the live-region status, and `apiRef.openAiAssistant` / `closeAiAssistant`. Inert without `aiAssistant`; it runs before step 46 because the toolbar gets its Ask AI button from it |
|
|
108
|
+
| 46 | `useGridToolbarProps` (in `useGridToolbarStack`) | `hooks/core/useGridToolbarProps.ts` | Props for `slots.toolbar` |
|
|
94
109
|
|
|
95
110
|
## Rendered components
|
|
96
111
|
|
|
97
|
-
`
|
|
98
|
-
|
|
112
|
+
`DataGrid.tsx` renders `GridRoot` (`components/DataGrid/GridRoot.tsx`): the root element with, in this order,
|
|
113
|
+
`GridToolbarSlot`, `GridAiAssistantArea` (the `aiAssistant` panel or `slots.aiAssistantPanel` while open, anchored under the toolbar), `GridStandaloneColumnPanel`, `GridListView` (list view) or `GridViewport` (`components/DataGrid/GridViewport.tsx`, the `role="grid"` viewport:
|
|
114
|
+
`Header`, `GridPinnedRows` top, `GridEmptyState`, `GridVirtualRows`, `GridPinnedRows` bottom,
|
|
99
115
|
`GridAggregationFooter`), `GridCellSelectionStatsArea` (`showCellSelectionStats` with `cellSelection`), then `slots.footer` or `GridPaginationArea`, `GridLiveRegion`,
|
|
100
|
-
`GridLoadingOverlay` and `GridErrorOverlay`.
|
|
101
|
-
|
|
116
|
+
`GridLoadingOverlay` and `GridErrorOverlay`. `GridRoot` builds the overlay slot elements and passes the
|
|
117
|
+
rest of its props on to `GridViewport`. The props all three row renderers take alike are built once in
|
|
118
|
+
`GridViewport` (`rowRenderProps`) and spread into each. `rowRenderProps.cellRange` is the cell range's
|
|
102
119
|
render rectangle; each row renderer turns it into a per-row `cellRange` (`getRowCellRange`), `null` for rows
|
|
103
120
|
outside it, and `Row` is memoised with a value comparison of that prop, so a drag only re-renders the rows the
|
|
104
121
|
range enters or leaves. `rowRenderProps.fillHandle` (v3.5) adds `fillHandleCol` to the one row that draws the fill
|
|
@@ -288,4 +288,4 @@ function CustomPagination(props: Record<string, unknown>) {
|
|
|
288
288
|
## See Also
|
|
289
289
|
|
|
290
290
|
- [Custom Pagination Guide](../features/custom-pagination.md) - Detailed examples with Ant Design and MUI
|
|
291
|
-
- [DataGrid Props](../../lib/types/
|
|
291
|
+
- [DataGrid Props](../../lib/types/props.ts) - Full TypeScript definitions
|
|
@@ -5,6 +5,8 @@ OpenGridX ships with a complete design-token system built on CSS custom properti
|
|
|
5
5
|
1. **`DataGridThemeProvider`** — the recommended React API (maps a typed `GridTheme` object → CSS variables)
|
|
6
6
|
2. **Raw CSS override** — set any `--ogx-*` variable yourself on a wrapper element or `:root`
|
|
7
7
|
|
|
8
|
+
To design a theme without writing code, use the **[Theme Builder](https://opencorestack.github.io/OpenGridX/theme-builder)** demo page: controls for colours, fonts, sizes, borders and dividers, buttons and menus, edited separately for light and dark mode on a live grid, with WCAG AA contrast hints. It copies or downloads the result as a `GridTheme` (only the values that differ from the defaults) and can share it as a link (`#theme=…`).
|
|
9
|
+
|
|
8
10
|
---
|
|
9
11
|
|
|
10
12
|
## Quick Start — `DataGridThemeProvider`
|
|
@@ -198,6 +200,47 @@ All sub-theme types (`GridThemeColors`, `GridThemeGrayScale`, `GridThemeTypograp
|
|
|
198
200
|
| `--ogx-grid-header-font-size` | `13px` | Header cell font size (`grid.headerFontSize`) |
|
|
199
201
|
| `--ogx-grid-line-height` | `var(--ogx-line-height-normal)` | Row line height |
|
|
200
202
|
|
|
203
|
+
### Fonts, dividers and corners (v3.7)
|
|
204
|
+
|
|
205
|
+
These keys were added for the [Theme Builder](https://opencorestack.github.io/OpenGridX/theme-builder). Each defaults to exactly what the grid drew before, so a theme that leaves them out looks unchanged. The variables without a stylesheet value are read with a fallback, so they follow the token in the Default column when only that one is set.
|
|
206
|
+
|
|
207
|
+
| Theme key | CSS variable | Default | Styles |
|
|
208
|
+
|---|---|---|---|
|
|
209
|
+
| `grid.headerFontFamily` | `--ogx-grid-header-font-family` | the grid font | Header cells |
|
|
210
|
+
| `grid.headerFontWeight` | `--ogx-grid-header-font-weight` | `600` | Header cells |
|
|
211
|
+
| `grid.cellFontFamily` | `--ogx-grid-cell-font-family` | the grid font | Body cells |
|
|
212
|
+
| `grid.cellFontWeight` | `--ogx-grid-cell-font-weight` | inherited (`400`) | Body cells |
|
|
213
|
+
| `grid.headerPaddingX` | `--ogx-grid-header-padding-x` | `--ogx-grid-cell-padding-x` | Horizontal padding of header cells |
|
|
214
|
+
| `grid.borderWidth` | `--ogx-grid-border-width` | `1px` | The grid's outer border |
|
|
215
|
+
| `grid.borderRadius` | `--ogx-grid-border-radius` | `--ogx-border-radius-lg` (`12px`) | The grid's corners (inner corners follow: radius minus border width) |
|
|
216
|
+
| `grid.columnDividerWidth` | `--ogx-grid-column-divider-width` | `1px` | Lines between body cells and aggregation footer cells, and the edge of the right-pinned section |
|
|
217
|
+
| `grid.headerColumnDividerWidth` | `--ogx-grid-header-column-divider-width` | `1px` | The short separators between header cells and column-group cells |
|
|
218
|
+
| `grid.rowDividerWidth` | `--ogx-grid-row-divider-width` | `1px` | Lines under rows, the header row, column-group rows and the header filter row |
|
|
219
|
+
| `grid.columnDividerColor` | `--ogx-grid-column-divider-color` | `--ogx-grid-border-color` | Colour of the column dividers |
|
|
220
|
+
| `grid.rowDividerColor` | `--ogx-grid-row-divider-color` | `--ogx-grid-border-color` | Colour of the row dividers |
|
|
221
|
+
| `overlays.fontFamily` | `--ogx-overlay-font-family` | the grid font | Column menu, header filter menu, toolbar panels (columns, filters, summaries, pivot), AI panel |
|
|
222
|
+
| `overlays.fontWeight` | `--ogx-overlay-font-weight` | each item's own (`400`, labels `500`) | Menu items and panel labels; section titles and active items stay bold |
|
|
223
|
+
| `overlays.fontSize` | `--ogx-overlay-font-size` | `--ogx-font-size-xs` (AI panel `--ogx-font-size-sm`) | Menu items and panel labels |
|
|
224
|
+
|
|
225
|
+
The header-cell separators keep their own colour (`--ogx-color-gray-300` at 50% opacity); only their width is themable.
|
|
226
|
+
|
|
227
|
+
#### Recipe: hide the dividers
|
|
228
|
+
|
|
229
|
+
A width of `0` removes a divider without changing any cell's size or position:
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
const borderless: GridTheme = {
|
|
233
|
+
grid: {
|
|
234
|
+
columnDividerWidth: '0', // body and footer cells
|
|
235
|
+
headerColumnDividerWidth: '0', // header and column-group cells
|
|
236
|
+
rowDividerWidth: '0', // under rows and header rows
|
|
237
|
+
rowAlternateBackground: '#f8fafc', // optional: zebra rows instead of lines
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
For visible gaps between cells instead of lines, set the divider colour to the grid background (`columnDividerColor: '#ffffff'`) and widen it. Cells have no margin setting: they are positioned to the pixel for virtualization, pinning and spanning, so use padding for room inside them.
|
|
243
|
+
|
|
201
244
|
### Grid Colors
|
|
202
245
|
|
|
203
246
|
| Token | Default (light) | Dark override | Description |
|
|
@@ -33,7 +33,7 @@ The grid calculates which rows are visible based on:
|
|
|
33
33
|
- ✅ About 19 row elements at rest in an 800 px page at 52 px rows, at most about 86 while scrolling fast, whatever the row count (10k to 1M)
|
|
34
34
|
- ✅ Scrolling keeps up with a 60 Hz display at 1M rows in Chromium (no missed frames) and Firefox; WebKit misses a frame or two on each long jump of the scroll position
|
|
35
35
|
- ✅ The grid itself adds about 10 MB of JS heap at 100k rows and 79 MB at 1M (Chromium), on top of your row data
|
|
36
|
-
- ⚠️ Not millions of rows at the default height
|
|
36
|
+
- ⚠️ Not millions of rows at the default height: browsers cap an element's height. See [The browser height limit](#the-browser-height-limit) for how many rows fit and what to use beyond that.
|
|
37
37
|
|
|
38
38
|
### Column Virtualization
|
|
39
39
|
|
|
@@ -89,6 +89,20 @@ In development builds the grid logs a `console.warn` when it is rendering every
|
|
|
89
89
|
|
|
90
90
|
Pagination can hide this problem, because a paginated grid only has one page of rows to render. Row grouping switches pagination off (see below), so an unbounded container that looked fine with pagination can freeze the tab once grouping is enabled.
|
|
91
91
|
|
|
92
|
+
### The browser height limit
|
|
93
|
+
|
|
94
|
+
**How many rows can one scrolling grid hold?**
|
|
95
|
+
|
|
96
|
+
| Rows (at the default 52 px) | Use |
|
|
97
|
+
| :--- | :--- |
|
|
98
|
+
| up to about 300,000 | client-side rows: they fit in every browser |
|
|
99
|
+
| up to about 600,000 | client-side rows in Chromium and WebKit only; Firefox users cannot scroll past about 344,000 |
|
|
100
|
+
| more | a [`dataSource`](data-source.md) (server-side pages or infinite scroll), or `pagination` |
|
|
101
|
+
|
|
102
|
+
`density="compact"` (32 px rows) stretches each limit by about 1.6×: about 559,000 rows in Firefox and 1,048,000 in Chromium and WebKit.
|
|
103
|
+
|
|
104
|
+
Why: the grid lays every row out at its real height (`rowCount × rowHeight` pixels) and does no scroll scaling, and browsers cap an element's height. Chromium and WebKit stop at 33,554,428 px, so rows past about `33,554,428 / rowHeight` cannot be scrolled to (645,277 at 52 px). Firefox's limit is about 17.9M px (about 344,000 rows at 52 px); since 3.5.1 the grid caps its content to the limit it measures, so Firefox scrolls normally up to there (on 3.5.0 and earlier, content past the limit collapsed and the grid did not scroll at all). In development the grid warns when rows are cut off, names how many can be scrolled to and points to `dataSource`. Measured reach per browser: [Performance → Reach](../performance.md#reach-the-browser-height-ceiling).
|
|
105
|
+
|
|
92
106
|
## Configuration
|
|
93
107
|
|
|
94
108
|
### Row Height
|
|
@@ -243,7 +257,7 @@ You should see console logs only for visible rows + overscan buffer.
|
|
|
243
257
|
## Known Limitations
|
|
244
258
|
|
|
245
259
|
1. **Unbounded containers** - Virtualization needs a bounded viewport height (see above)
|
|
246
|
-
2. **Browser height cap** - Rows past roughly `33,554,
|
|
260
|
+
2. **Browser height cap** - Rows past roughly `33,554,428 / rowHeight` (Chromium and WebKit; less in Firefox) cannot be scrolled to ([see above](#the-browser-height-limit))
|
|
247
261
|
3. **Uniform row heights** - Only detail panels vary the height; cumulative heights are recomputed over all rows when panels change
|
|
248
262
|
4. **Horizontal scrolling** - May show brief flicker with very wide grids
|
|
249
263
|
|
package/docs/performance.md
CHANGED
|
@@ -87,12 +87,14 @@ import '@opencorestack/opengridx/styles';
|
|
|
87
87
|
|
|
88
88
|
## Know the browser's height limit
|
|
89
89
|
|
|
90
|
+
In short: up to about 300,000 rows at 52 px fit in every browser, up to about 600,000 in Chromium and WebKit; beyond that load rows with a [`dataSource`](features/data-source.md) or use pagination. The decision guide is in [Virtualization → The browser height limit](features/virtualization.md#the-browser-height-limit).
|
|
91
|
+
|
|
90
92
|
The grid sizes its scroll content to `rowCount × rowHeight` pixels and does not scale scroll positions. Browsers cap an element's height, and the [benchmark](#reach-the-browser-height-ceiling) measures what happens past the cap:
|
|
91
93
|
|
|
92
94
|
- **Chromium and WebKit** clamp the content at 33,554,428 px. Rows below that cannot be scrolled to: at the default 52 px row height that is every row past 645,277.
|
|
93
95
|
- **Firefox** has a lower limit, about 17.9M px, and collapses a taller element instead of clamping it. Up to 3.5.0 that made a grid with more content unscrollable in Firefox (only the first screen of rows was reachable). **Since 3.5.1 the grid measures the browser's limit once and caps its scroll content to it**, so Firefox scrolls normally and reaches the rows above the cap: about 344,000 rows at 52 px, 559,000 at 32 px.
|
|
94
96
|
|
|
95
|
-
In development the grid warns when rows are cut off, naming how many can be scrolled to in that browser
|
|
97
|
+
In development the grid warns when rows are cut off, naming how many can be scrolled to in that browser and pointing to `dataSource`. For more rows, use a [`dataSource`](features/data-source.md) (`paginationMode="server"` or infinite scroll), `pagination`, or a smaller `rowHeight` (`density="compact"`, 32 px, keeps 1M rows under the Chromium and WebKit cap).
|
|
96
98
|
|
|
97
99
|
## Use server-side operations for very large datasets
|
|
98
100
|
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
border: 1px solid var(--ogx-overlay-border, var(--ogx-grid-border-color));
|
|
22
22
|
border-radius: var(--ogx-border-radius-lg, 8px);
|
|
23
23
|
box-shadow: var(--ogx-shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.15));
|
|
24
|
-
font-
|
|
24
|
+
font-family: var(--ogx-overlay-font-family, inherit);
|
|
25
|
+
font-size: var(--ogx-overlay-font-size, var(--ogx-font-size-sm));
|
|
26
|
+
font-weight: var(--ogx-overlay-font-weight, inherit);
|
|
25
27
|
}
|
|
26
28
|
.ogx-ai-panel__header {
|
|
27
29
|
display: flex;
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
display: flex;
|
|
4
4
|
align-items: center;
|
|
5
5
|
padding: var(--ogx-grid-cell-padding-y) var(--ogx-grid-cell-padding-x);
|
|
6
|
-
border-inline-end:
|
|
6
|
+
border-inline-end: var(--ogx-grid-column-divider-width) solid var(--ogx-grid-column-divider-color, var(--ogx-grid-border-color));
|
|
7
|
+
font-family: var(--ogx-grid-cell-font-family, inherit);
|
|
7
8
|
font-size: var(--ogx-grid-cell-font-size);
|
|
9
|
+
font-weight: var(--ogx-grid-cell-font-weight, inherit);
|
|
8
10
|
color: var(--ogx-grid-row-text);
|
|
9
11
|
line-height: var(--ogx-grid-line-height);
|
|
10
12
|
white-space: nowrap;
|
|
@@ -132,7 +134,7 @@
|
|
|
132
134
|
background-color: var(--ogx-grid-background);
|
|
133
135
|
}
|
|
134
136
|
.ogx__cell--pinned-right {
|
|
135
|
-
border-inline-start:
|
|
137
|
+
border-inline-start: var(--ogx-grid-column-divider-width) solid var(--ogx-grid-column-divider-color, var(--ogx-grid-border-color));
|
|
136
138
|
}
|
|
137
139
|
/* When the columns are narrower than the grid, the free space goes before the right-pinned section. */
|
|
138
140
|
.ogx__cell--pinned-right-first {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
display: flex;
|
|
9
9
|
align-items: stretch;
|
|
10
10
|
background: var(--ogx-grid-header-background);
|
|
11
|
-
border-bottom:
|
|
11
|
+
border-bottom: var(--ogx-grid-row-divider-width) solid var(--ogx-grid-row-divider-color, var(--ogx-grid-border-color));
|
|
12
12
|
/* No overflow clipping: it would make the row the scroll container of its sticky (pinned) cells. */
|
|
13
13
|
flex-shrink: 0;
|
|
14
14
|
min-height: var(--ogx-header-height, 48px);
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
inset-inline-end: 0;
|
|
32
32
|
top: 25%;
|
|
33
33
|
height: 50%;
|
|
34
|
-
width:
|
|
34
|
+
width: var(--ogx-grid-header-column-divider-width);
|
|
35
35
|
background-color: var(--ogx-color-gray-300, #cbd5e1);
|
|
36
36
|
opacity: 0.5;
|
|
37
37
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
background: var(--ogx-overlay-background, var(--ogx-color-white));
|
|
3
3
|
border: var(--ogx-border-width-thin) solid var(--ogx-overlay-border, var(--ogx-border-color));
|
|
4
4
|
border-radius: var(--ogx-border-radius-sm);
|
|
5
|
+
font-family: var(--ogx-overlay-font-family, inherit);
|
|
5
6
|
min-width: 250px;
|
|
6
7
|
max-width: 350px;
|
|
7
8
|
box-shadow: var(--ogx-shadow-lg);
|
|
@@ -120,7 +121,8 @@
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
.ogx-column-visibility-panel__label {
|
|
123
|
-
font-size: var(--ogx-font-size-xs);
|
|
124
|
+
font-size: var(--ogx-overlay-font-size, var(--ogx-font-size-xs));
|
|
125
|
+
font-weight: var(--ogx-overlay-font-weight, inherit);
|
|
124
126
|
color: var(--ogx-overlay-text, var(--ogx-color-gray-900));
|
|
125
127
|
user-select: none;
|
|
126
128
|
cursor: inherit;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
width: 100%;
|
|
5
5
|
background: var(--ogx-grid-background);
|
|
6
|
-
border:
|
|
7
|
-
border-radius: var(--ogx-border-radius-lg);
|
|
6
|
+
border: var(--ogx-grid-border-width) solid var(--ogx-grid-border-color);
|
|
7
|
+
border-radius: var(--ogx-grid-border-radius, var(--ogx-border-radius-lg));
|
|
8
8
|
font-family: var(--ogx-font-family);
|
|
9
9
|
position: relative;
|
|
10
10
|
box-shadow: var(--ogx-shadow-sm);
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
overflow: hidden;
|
|
13
13
|
}
|
|
14
14
|
.ogx > :first-child {
|
|
15
|
-
border-top-left-radius: calc(var(--ogx-border-radius-lg) -
|
|
16
|
-
border-top-right-radius: calc(var(--ogx-border-radius-lg) -
|
|
15
|
+
border-top-left-radius: max(0px, calc(var(--ogx-grid-border-radius, var(--ogx-border-radius-lg)) - var(--ogx-grid-border-width)));
|
|
16
|
+
border-top-right-radius: max(0px, calc(var(--ogx-grid-border-radius, var(--ogx-border-radius-lg)) - var(--ogx-grid-border-width)));
|
|
17
17
|
}
|
|
18
18
|
.ogx > :last-child {
|
|
19
|
-
border-bottom-left-radius: calc(var(--ogx-border-radius-lg) -
|
|
20
|
-
border-bottom-right-radius: calc(var(--ogx-border-radius-lg) -
|
|
19
|
+
border-bottom-left-radius: max(0px, calc(var(--ogx-grid-border-radius, var(--ogx-border-radius-lg)) - var(--ogx-grid-border-width)));
|
|
20
|
+
border-bottom-right-radius: max(0px, calc(var(--ogx-grid-border-radius, var(--ogx-border-radius-lg)) - var(--ogx-grid-border-width)));
|
|
21
21
|
}
|
|
22
22
|
.ogx:hover {
|
|
23
23
|
box-shadow: var(--ogx-shadow-md);
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
min-height: 0;
|
|
151
151
|
pointer-events: none;
|
|
152
152
|
z-index: var(--ogx-z-index-modal);
|
|
153
|
-
border-radius: var(--ogx-border-radius-lg);
|
|
153
|
+
border-radius: var(--ogx-grid-border-radius, var(--ogx-border-radius-lg));
|
|
154
154
|
overflow: hidden;
|
|
155
155
|
}
|
|
156
156
|
.ogx__loading-overlay--custom {
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
justify-content: center;
|
|
244
244
|
overflow: hidden;
|
|
245
245
|
box-sizing: border-box;
|
|
246
|
-
border-inline-end:
|
|
246
|
+
border-inline-end: var(--ogx-grid-column-divider-width) solid var(--ogx-grid-column-divider-color, var(--ogx-grid-border-color));
|
|
247
247
|
position: relative;
|
|
248
248
|
}
|
|
249
249
|
.ogx__aggregation-cell--pinned-left,
|
|
@@ -265,7 +265,7 @@
|
|
|
265
265
|
background: var(--ogx-grid-header-background);
|
|
266
266
|
}
|
|
267
267
|
.ogx__aggregation-cell--pinned-right {
|
|
268
|
-
border-inline-start:
|
|
268
|
+
border-inline-start: var(--ogx-grid-column-divider-width) solid var(--ogx-grid-column-divider-color, var(--ogx-grid-border-color));
|
|
269
269
|
}
|
|
270
270
|
.ogx__aggregation-cell--pinned-left-last {
|
|
271
271
|
overflow: visible;
|