@opencorestack/opengridx 2.1.0 → 3.0.1

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 (225) hide show
  1. package/CHANGELOG.md +399 -0
  2. package/README.md +95 -72
  3. package/dist/index.d.ts +590 -131
  4. package/dist/opengridx.css +1 -1
  5. package/dist/opengridx.es.js +7891 -5631
  6. package/dist/opengridx.es.js.map +1 -1
  7. package/dist/opengridx.umd.js +17 -23
  8. package/dist/opengridx.umd.js.map +1 -1
  9. package/docs/API_REFERENCE.md +348 -166
  10. package/docs/README.md +6 -1
  11. package/docs/architecture/datagrid-orchestration.md +81 -0
  12. package/docs/architecture/grid-row-meta.md +102 -0
  13. package/docs/architecture/use-grid-columns.md +128 -0
  14. package/docs/architecture/use-grid-controlled-state.md +157 -0
  15. package/docs/architecture/use-grid-row-pipeline.md +120 -0
  16. package/docs/architecture/use-grid-scroll-sync.md +111 -0
  17. package/docs/architecture/use-grid-state-snapshot.md +90 -0
  18. package/docs/architecture/use-grid-virtualization.md +115 -0
  19. package/docs/architecture/use-grid-visible-rows.md +85 -0
  20. package/docs/assets/banner-alt.png +0 -0
  21. package/docs/assets/banner.png +0 -0
  22. package/docs/assets/hero.png +0 -0
  23. package/docs/assets/logo.png +0 -0
  24. package/docs/components/aggregation-footer.md +15 -10
  25. package/docs/components/cell.md +16 -6
  26. package/docs/components/column-group-header.md +55 -28
  27. package/docs/components/column-resize.md +17 -13
  28. package/docs/components/column-visibility.md +6 -7
  29. package/docs/components/datagrid.md +15 -13
  30. package/docs/components/empty-state.md +2 -1
  31. package/docs/components/error-overlay.md +12 -7
  32. package/docs/components/filter-panel.md +28 -8
  33. package/docs/components/header.md +28 -9
  34. package/docs/components/pagination.md +14 -8
  35. package/docs/components/row.md +21 -5
  36. package/docs/components/toolbar.md +27 -9
  37. package/docs/components/tooltip.md +16 -7
  38. package/docs/customization/slots-api.md +90 -38
  39. package/docs/customization/theming.md +66 -18
  40. package/docs/features/aggregation-pivot.md +75 -9
  41. package/docs/features/cell-spanning.md +80 -125
  42. package/docs/features/clipboard.md +41 -16
  43. package/docs/features/custom-pagination.md +38 -18
  44. package/docs/features/data-source.md +36 -13
  45. package/docs/features/editing-reordering.md +125 -16
  46. package/docs/features/export-guide.md +126 -39
  47. package/docs/features/filtering.md +44 -6
  48. package/docs/features/infinite-scroll.md +54 -46
  49. package/docs/features/keyboard-navigation.md +83 -0
  50. package/docs/features/list-view.md +58 -5
  51. package/docs/features/loading-states.md +18 -20
  52. package/docs/features/master-detail.md +18 -5
  53. package/docs/features/pdf-export.md +72 -19
  54. package/docs/features/pinning.md +24 -5
  55. package/docs/features/selection.md +50 -10
  56. package/docs/features/sorting-pagination.md +64 -14
  57. package/docs/features/state-persistence.md +78 -10
  58. package/docs/features/toolbar-customization.md +26 -17
  59. package/docs/features/tree-data-grouping.md +36 -8
  60. package/docs/features/virtualization.md +37 -14
  61. package/docs/migration/v1-to-v2.md +115 -0
  62. package/docs/migration/v2-to-v3.md +1233 -0
  63. package/docs/performance.md +124 -0
  64. package/docs/roadmap.md +5 -5
  65. package/lib/components/Cell/Cell.css +17 -1
  66. package/lib/components/Cell/Cell.tsx +129 -57
  67. package/lib/components/Cell/CellErrorBoundary.tsx +12 -6
  68. package/lib/components/Cell/GridEditInputCell.tsx +114 -41
  69. package/lib/components/ColumnGroupHeader/ColumnGroupHeader.css +7 -1
  70. package/lib/components/ColumnResizeHandle/ColumnResizeHandle.css +15 -2
  71. package/lib/components/ColumnResizeHandle/ColumnResizeHandle.tsx +104 -38
  72. package/lib/components/ColumnResizeHandle/clampResizeWidth.ts +13 -0
  73. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +6 -0
  74. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +21 -13
  75. package/lib/components/DataGrid/DataGrid.css +85 -12
  76. package/lib/components/DataGrid/DataGrid.tsx +582 -876
  77. package/lib/components/DataGrid/GridAggregationFooter.tsx +53 -17
  78. package/lib/components/DataGrid/GridErrorOverlay.tsx +15 -12
  79. package/lib/components/DataGrid/GridListView.tsx +165 -24
  80. package/lib/components/DataGrid/GridLiveRegion.tsx +31 -0
  81. package/lib/components/DataGrid/GridLoadingOverlay.tsx +27 -0
  82. package/lib/components/DataGrid/GridPaginationArea.tsx +44 -0
  83. package/lib/components/DataGrid/GridPinnedRows.tsx +62 -11
  84. package/lib/components/DataGrid/GridStandaloneColumnPanel.tsx +40 -38
  85. package/lib/components/DataGrid/GridToolbarSlot.tsx +51 -0
  86. package/lib/components/DataGrid/GridVirtualRows.tsx +40 -24
  87. package/lib/components/DetailPanel/DetailPanel.css +0 -6
  88. package/lib/components/DetailPanel/DetailPanel.tsx +34 -5
  89. package/lib/components/DetailPanel/DetailPanelContent.tsx +17 -0
  90. package/lib/components/FilterPanel/FilterPanel.css +13 -2
  91. package/lib/components/FilterPanel/FilterPanel.tsx +272 -99
  92. package/lib/components/Header/ColumnMenu.tsx +91 -39
  93. package/lib/components/Header/Header.css +6 -3
  94. package/lib/components/Header/Header.tsx +181 -160
  95. package/lib/components/ListView/ListView.css +25 -0
  96. package/lib/components/ListView/ListViewRow.tsx +76 -10
  97. package/lib/components/Pagination/Pagination.tsx +15 -7
  98. package/lib/components/Row/Row.tsx +177 -77
  99. package/lib/components/Toolbar/GlobalSearch.css +6 -3
  100. package/lib/components/Toolbar/GlobalSearch.tsx +26 -27
  101. package/lib/components/Toolbar/GridToolbar.css +12 -11
  102. package/lib/components/Toolbar/GridToolbar.tsx +133 -89
  103. package/lib/components/Toolbar/PivotPanel.tsx +89 -49
  104. package/lib/components/Tooltip/Tooltip.css +20 -0
  105. package/lib/components/Tooltip/Tooltip.tsx +68 -35
  106. package/lib/components/ui/Button.tsx +3 -0
  107. package/lib/components/ui/Checkbox.tsx +2 -1
  108. package/lib/components/ui/ExpandIcon.css +0 -9
  109. package/lib/components/ui/ExpandIcon.tsx +4 -1
  110. package/lib/hooks/core/gridApiPlaceholder.ts +34 -0
  111. package/lib/hooks/core/gridToolbarHostContext.ts +14 -0
  112. package/lib/hooks/core/useDataGrid.ts +115 -173
  113. package/lib/hooks/core/useGridAggregationApi.ts +72 -0
  114. package/lib/hooks/core/useGridApiMethods.ts +115 -0
  115. package/lib/hooks/core/useGridApiRef.ts +19 -4
  116. package/lib/hooks/core/useGridApiRefBinding.ts +18 -0
  117. package/lib/hooks/core/useGridAriaRows.ts +38 -0
  118. package/lib/hooks/core/useGridClipboardApi.ts +38 -0
  119. package/lib/hooks/core/useGridColumnLookup.ts +30 -0
  120. package/lib/hooks/core/useGridColumns.tsx +279 -76
  121. package/lib/hooks/core/useGridColumnsPanel.ts +77 -0
  122. package/lib/hooks/core/useGridControlledState.ts +99 -6
  123. package/lib/hooks/core/useGridDetailPanel.ts +51 -0
  124. package/lib/hooks/core/useGridDevWarnings.ts +104 -5
  125. package/lib/hooks/core/useGridFocusHandlers.ts +50 -0
  126. package/lib/hooks/core/useGridGroupingColumn.ts +62 -0
  127. package/lib/hooks/core/useGridHeaderHandlers.ts +92 -0
  128. package/lib/hooks/core/useGridHierarchy.ts +81 -0
  129. package/lib/hooks/core/useGridKeyboardNavigation.ts +447 -243
  130. package/lib/hooks/core/useGridLiveRowSelection.ts +67 -0
  131. package/lib/hooks/core/useGridPageCorrection.ts +55 -0
  132. package/lib/hooks/core/useGridRowIdOf.ts +32 -0
  133. package/lib/hooks/core/useGridRowInteractions.ts +81 -0
  134. package/lib/hooks/core/useGridRowPipeline.ts +69 -39
  135. package/lib/hooks/core/useGridRowSelection.ts +91 -0
  136. package/lib/hooks/core/useGridScrollSync.ts +80 -32
  137. package/lib/hooks/core/useGridScrollToIndexesApi.ts +45 -0
  138. package/lib/hooks/core/useGridStateSnapshot.ts +40 -5
  139. package/lib/hooks/core/useGridThemeDimensions.ts +49 -0
  140. package/lib/hooks/core/useGridToolbarProps.ts +97 -0
  141. package/lib/hooks/core/useGridViewport.ts +38 -0
  142. package/lib/hooks/core/useGridViewportSize.ts +26 -0
  143. package/lib/hooks/core/useGridVisibleRows.ts +17 -5
  144. package/lib/hooks/core/useLayout.ts +215 -195
  145. package/lib/hooks/core/useRowsScrollEndLatch.ts +41 -0
  146. package/lib/hooks/core/useStableColumns.ts +34 -0
  147. package/lib/hooks/features/useAggregation.ts +82 -51
  148. package/lib/hooks/features/useColumnGroupReorderGuard.ts +34 -0
  149. package/lib/hooks/features/useDetailPanelHeights.ts +29 -0
  150. package/lib/hooks/features/useGridClipboard.ts +133 -73
  151. package/lib/hooks/features/useGridDataSource.ts +354 -128
  152. package/lib/hooks/features/useGridEditing.ts +211 -51
  153. package/lib/hooks/features/useGridPivot.ts +92 -0
  154. package/lib/hooks/features/useGridSpanRenderWindow.ts +104 -0
  155. package/lib/hooks/features/useGridSpanning.ts +410 -306
  156. package/lib/hooks/features/usePivot.ts +0 -0
  157. package/lib/hooks/features/useServerTreeChildren.ts +50 -0
  158. package/lib/hooks/useColumnReorder.ts +38 -44
  159. package/lib/hooks/useRowGrouping.ts +298 -160
  160. package/lib/hooks/useRowReorder.ts +62 -31
  161. package/lib/hooks/useTreeData.ts +287 -220
  162. package/lib/index.ts +28 -2
  163. package/lib/state/index.ts +1 -0
  164. package/lib/state/types.ts +7 -1
  165. package/lib/state/useGridStateStorage.ts +88 -29
  166. package/lib/theme/DataGridThemeProvider.tsx +143 -38
  167. package/lib/theme/gridThemeContext.ts +5 -0
  168. package/lib/theme/index.ts +5 -0
  169. package/lib/theme/presets.ts +5 -4
  170. package/lib/theme/types.ts +40 -2
  171. package/lib/types/index.ts +313 -116
  172. package/lib/utils/aggregation/index.ts +119 -24
  173. package/lib/utils/aria/index.ts +40 -0
  174. package/lib/utils/columnGroups.ts +110 -0
  175. package/lib/utils/columnLookup.ts +33 -0
  176. package/lib/utils/columnWidth.ts +22 -0
  177. package/lib/utils/dataSource/index.ts +46 -0
  178. package/lib/utils/detailPanel.ts +66 -0
  179. package/lib/utils/dragData.ts +44 -0
  180. package/lib/utils/editing/index.ts +30 -0
  181. package/lib/utils/export/exportShared.ts +197 -0
  182. package/lib/utils/export/exportToExcelAdvanced.ts +278 -139
  183. package/lib/utils/export/exportToPdf.ts +143 -92
  184. package/lib/utils/export/groupLabel.ts +14 -0
  185. package/lib/utils/export/index.ts +278 -272
  186. package/lib/utils/export/pdfText.ts +50 -0
  187. package/lib/utils/filtering/index.ts +277 -148
  188. package/lib/utils/focus/index.ts +115 -0
  189. package/lib/utils/gridApiRows.ts +35 -0
  190. package/lib/utils/gridModes.ts +77 -0
  191. package/lib/utils/grouping/groupedExportRows.ts +91 -0
  192. package/lib/utils/pagination/index.ts +56 -0
  193. package/lib/utils/pinning/index.ts +77 -33
  194. package/lib/utils/pivot/index.ts +368 -0
  195. package/lib/utils/scroll/index.ts +55 -5
  196. package/lib/utils/scroll/scrollEnd.ts +18 -0
  197. package/lib/utils/sorting/index.ts +154 -30
  198. package/lib/utils/syntheticRows.ts +12 -0
  199. package/lib/utils/values.ts +206 -0
  200. package/lib/utils/viewport.ts +14 -0
  201. package/llms.txt +261 -164
  202. package/package.json +13 -5
  203. package/lib/components/ColumnGroupHeader/ColumnGroupHeader.tsx +0 -220
  204. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.test.tsx +0 -85
  205. package/lib/components/DataGrid/DataGrid.defects.test.tsx +0 -103
  206. package/lib/components/DataGrid/DataGrid.regression.test.tsx +0 -132
  207. package/lib/components/DataGrid/DataGrid.smoke.test.tsx +0 -58
  208. package/lib/components/DataGrid/DataGrid.v2.test.tsx +0 -127
  209. package/lib/components/DataGrid/DataGrid.virtualization.browser.test.tsx +0 -183
  210. package/lib/components/Header/Header.test.tsx +0 -135
  211. package/lib/components/Pagination/Pagination.test.tsx +0 -64
  212. package/lib/hooks/core/useDataGrid.regression.test.ts +0 -66
  213. package/lib/hooks/core/useGridControlledState.test.ts +0 -86
  214. package/lib/hooks/core/useGridKeyboardNavigation.test.ts +0 -176
  215. package/lib/hooks/core/useGridRowPipeline.test.ts +0 -117
  216. package/lib/hooks/features/useAggregation.test.ts +0 -175
  217. package/lib/hooks/features/usePivot.test.ts +0 -202
  218. package/lib/hooks/useRowGrouping.test.ts +0 -298
  219. package/lib/hooks/useTreeData.test.ts +0 -83
  220. package/lib/utils/aggregation/aggregation.test.ts +0 -16
  221. package/lib/utils/export/exportToExcelAdvanced.test.ts +0 -109
  222. package/lib/utils/export/exportToPdf.test.ts +0 -120
  223. package/lib/utils/export/groupedExport.test.ts +0 -144
  224. package/lib/utils/filtering/filtering.test.ts +0 -178
  225. package/lib/utils/sorting/sorting.test.ts +0 -88
Binary file
@@ -0,0 +1,50 @@
1
+ import { useEffect, useLayoutEffect, useRef } from 'react';
2
+ import type { GridRowId, GridTreeNode } from '../../types';
3
+
4
+ export interface UseServerTreeChildrenParams {
5
+ /** Tree data with a dataSource: children of lazy nodes come from getRows. */
6
+ enabled: boolean;
7
+ treeNodes: Map<GridRowId, GridTreeNode>;
8
+ isGroupExpanded: (id: GridRowId) => boolean;
9
+ getNodePath: (id: GridRowId) => string[];
10
+ toggleExpansion: (id: GridRowId) => void;
11
+ /** Deduplicates: a path already loading or loaded for the current rows is not requested again. */
12
+ fetchChildren: (parentId: GridRowId, groupKeys: string[], onError?: (error: unknown) => void) => Promise<void>;
13
+ }
14
+
15
+ /** A node the server says has children, none of which are loaded. */
16
+ function needsChildren(node: GridTreeNode): boolean {
17
+ return (node.serverChildrenCount ?? 0) > 0 && (node.children?.length ?? 0) === 0;
18
+ }
19
+
20
+ /**
21
+ * Server-side tree data: every expanded node whose children are not loaded gets them from the
22
+ * dataSource. That covers the user expanding a node and a refetch (sort, filter, page) replacing
23
+ * the rows while nodes stay expanded. A node whose children fail to load is collapsed again, so
24
+ * expanding it retries.
25
+ */
26
+ export function useServerTreeChildren({
27
+ enabled,
28
+ treeNodes,
29
+ isGroupExpanded,
30
+ getNodePath,
31
+ toggleExpansion,
32
+ fetchChildren,
33
+ }: UseServerTreeChildrenParams): void {
34
+ // The failure callback runs after the request, so it reads the expansion state of that moment.
35
+ const expansionRef = useRef({ isGroupExpanded, toggleExpansion });
36
+ useLayoutEffect(() => {
37
+ expansionRef.current = { isGroupExpanded, toggleExpansion };
38
+ });
39
+
40
+ useEffect(() => {
41
+ if (!enabled) return;
42
+ treeNodes.forEach((node, id) => {
43
+ if (!needsChildren(node) || !isGroupExpanded(id)) return;
44
+ void fetchChildren(id, getNodePath(id), () => {
45
+ const { isGroupExpanded: isExpanded, toggleExpansion: toggle } = expansionRef.current;
46
+ if (isExpanded(id)) toggle(id);
47
+ });
48
+ });
49
+ }, [enabled, treeNodes, isGroupExpanded, getNodePath, fetchChildren]);
50
+ }
@@ -1,8 +1,9 @@
1
-
2
- import { useState, useCallback, useRef } from 'react';
1
+ import { useState, useCallback, useRef, useEffect } from 'react';
3
2
  import type { GridColDef, GridRowModel, GridColumnOrderChangeParams } from '../types';
3
+ import { COLUMN_DRAG_MIME, hasDragToken, onNativeDragEnd, setDragToken } from '../utils/dragData';
4
4
 
5
5
  export interface UseColumnReorderProps<R extends GridRowModel = GridRowModel> {
6
+ /** Every current column, in the grid's column order. Reported indices are positions in it. */
6
7
  columns: GridColDef<R>[];
7
8
  onColumnOrderChange?: (params: GridColumnOrderChangeParams) => void;
8
9
  disableColumnReorder?: boolean;
@@ -24,85 +25,78 @@ export function useColumnReorder<R extends GridRowModel = GridRowModel>(
24
25
 
25
26
  const [draggedColumn, setDraggedColumn] = useState<string | null>(null);
26
27
  const [dragOverColumn, setDragOverColumn] = useState<string | null>(null);
27
- const draggedIndexRef = useRef<number>(-1);
28
+ const detachDragEndRef = useRef<() => void>(() => {});
29
+
30
+ const handleDragEnd = useCallback(() => {
31
+ detachDragEndRef.current();
32
+ detachDragEndRef.current = () => {};
33
+ setDraggedColumn(null);
34
+ setDragOverColumn(null);
35
+ }, []);
36
+
37
+ useEffect(() => () => detachDragEndRef.current(), []);
28
38
 
29
39
  const handleDragStart = useCallback(
30
40
  (field: string) => (event: React.DragEvent) => {
31
41
  if (disableColumnReorder) return;
32
-
33
- const columnIndex = columns.findIndex(col => col.field === field);
34
- const column = columns[columnIndex];
35
-
36
- if (column?.pinnable === false) {
42
+ if (!columns.some(col => col.field === field)) {
37
43
  event.preventDefault();
38
44
  return;
39
45
  }
40
46
 
47
+ detachDragEndRef.current();
48
+ // Ends the drag even if the header unmounts (column virtualization) before dragend.
49
+ detachDragEndRef.current = onNativeDragEnd(event.currentTarget, handleDragEnd);
41
50
  setDraggedColumn(field);
42
- draggedIndexRef.current = columnIndex;
43
51
 
44
52
  if (event.dataTransfer) {
45
53
  event.dataTransfer.effectAllowed = 'move';
46
- event.dataTransfer.setData('text/plain', field);
54
+ setDragToken(event, COLUMN_DRAG_MIME, field);
47
55
  }
48
56
  },
49
- [columns, disableColumnReorder]
57
+ [columns, disableColumnReorder, handleDragEnd]
50
58
  );
51
59
 
52
60
  const handleDragOver = useCallback(
53
61
  (field: string) => (event: React.DragEvent) => {
54
- if (disableColumnReorder || !draggedColumn) return;
62
+ if (disableColumnReorder || draggedColumn === null) return;
63
+ if (!hasDragToken(event, COLUMN_DRAG_MIME)) {
64
+ // Some other drag (a file, text, a row): any column drag we remember is over.
65
+ handleDragEnd();
66
+ return;
67
+ }
55
68
 
56
- event.preventDefault();
57
- event.dataTransfer.dropEffect = 'move';
69
+ event.preventDefault();
70
+ if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';
58
71
 
59
72
  setDragOverColumn(field);
60
73
  },
61
- [draggedColumn, disableColumnReorder]
74
+ [draggedColumn, disableColumnReorder, handleDragEnd]
62
75
  );
63
76
 
64
77
  const handleDrop = useCallback(
65
78
  (targetField: string) => (event: React.DragEvent) => {
66
79
  event.preventDefault();
67
-
68
- if (disableColumnReorder || !draggedColumn || draggedColumn === targetField) {
69
- setDraggedColumn(null);
70
- setDragOverColumn(null);
80
+ if (disableColumnReorder || draggedColumn === null || !hasDragToken(event, COLUMN_DRAG_MIME)) {
81
+ handleDragEnd();
71
82
  return;
72
83
  }
73
84
 
74
85
  const oldIndex = columns.findIndex(col => col.field === draggedColumn);
75
86
  const targetIndex = columns.findIndex(col => col.field === targetField);
87
+ handleDragEnd();
76
88
 
77
- if (oldIndex === -1 || targetIndex === -1) {
78
- setDraggedColumn(null);
79
- setDragOverColumn(null);
80
- return;
81
- }
82
-
83
- const column = columns[oldIndex];
84
-
85
- if (onColumnOrderChange) {
86
- onColumnOrderChange({
87
- column: column as unknown as GridColDef,
88
- oldIndex,
89
- targetIndex,
90
- });
91
- }
89
+ if (oldIndex === -1 || targetIndex === -1 || oldIndex === targetIndex) return;
92
90
 
93
- setDraggedColumn(null);
94
- setDragOverColumn(null);
95
- draggedIndexRef.current = -1;
91
+ onColumnOrderChange?.({
92
+ column: columns[oldIndex] as unknown as GridColDef,
93
+ oldIndex,
94
+ targetIndex,
95
+ });
96
96
  },
97
- [columns, draggedColumn, disableColumnReorder, onColumnOrderChange]
97
+ [columns, draggedColumn, disableColumnReorder, onColumnOrderChange, handleDragEnd]
98
98
  );
99
99
 
100
- const handleDragEnd = useCallback(() => {
101
- setDraggedColumn(null);
102
- setDragOverColumn(null);
103
- draggedIndexRef.current = -1;
104
- }, []);
105
-
106
100
  return {
107
101
  draggedColumn,
108
102
  dragOverColumn,