@object-ui/plugin-aggrid 0.4.1 → 2.0.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.
Files changed (46) hide show
  1. package/.turbo/turbo-build.log +99 -0
  2. package/CHANGELOG.md +16 -0
  3. package/OBJECT_AGGRID_CN.md +483 -0
  4. package/QUICKSTART.md +186 -0
  5. package/README.md +221 -1
  6. package/dist/AddressField-Bntpynvd.js +95 -0
  7. package/dist/AgGridImpl-3Mmf2qrR.js +229 -0
  8. package/dist/AutoNumberField-C1kBJaxh.js +8 -0
  9. package/dist/FileField-BDwbJvor.js +101 -0
  10. package/dist/FormulaField-BXNiyGoh.js +9 -0
  11. package/dist/GeolocationField-Df3yYcM9.js +141 -0
  12. package/dist/GridField-CcjQp4WM.js +29 -0
  13. package/dist/LocationField-BIfN5QIq.js +33 -0
  14. package/dist/MasterDetailField-CAEmxbIT.js +117 -0
  15. package/dist/ObjectAgGridImpl-EjifM4aY.js +28727 -0
  16. package/dist/ObjectField-BpkQpIF-.js +51 -0
  17. package/dist/QRCodeField-VCBewTDG.js +96 -0
  18. package/dist/RichTextField-CyQwSi2C.js +37 -0
  19. package/dist/SignatureField-Cr4tsEbj.js +96 -0
  20. package/dist/SummaryField-CnEJ_GZI.js +9 -0
  21. package/dist/UserField-DJjaVyrV.js +49 -0
  22. package/dist/VectorField-cPYmcKnV.js +25 -0
  23. package/dist/{index-B6NPAFZx.js → index-B87wd1E0.js} +301 -143
  24. package/dist/index.css +1 -1
  25. package/dist/index.js +4 -3
  26. package/dist/index.umd.cjs +225 -2
  27. package/dist/src/AgGridImpl.d.ts +5 -2
  28. package/dist/src/ObjectAgGridImpl.d.ts +6 -0
  29. package/dist/src/VirtualScrolling.d.ts +72 -0
  30. package/dist/src/field-renderers.d.ts +67 -0
  31. package/dist/src/index.d.ts +47 -2
  32. package/dist/src/object-aggrid.types.d.ts +74 -0
  33. package/dist/src/types.d.ts +48 -1
  34. package/package.json +11 -9
  35. package/src/AgGridImpl.tsx +100 -11
  36. package/src/ObjectAgGridImpl.tsx +501 -0
  37. package/src/VirtualScrolling.ts +74 -0
  38. package/src/field-renderers.test.tsx +383 -0
  39. package/src/field-renderers.tsx +224 -0
  40. package/src/index.test.ts +1 -1
  41. package/src/index.tsx +211 -2
  42. package/src/object-aggrid.test.ts +99 -0
  43. package/src/object-aggrid.types.ts +123 -0
  44. package/src/types.ts +57 -1
  45. package/vite.config.ts +13 -0
  46. package/dist/AgGridImpl-DKkq6v1B.js +0 -171
@@ -1,5 +1,5 @@
1
1
  import { ColDef, GridOptions } from 'ag-grid-community';
2
- import { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig } from './types';
2
+ import { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig, TreeDataConfig, RowGroupingConfig, ExcelExportConfig } from './types';
3
3
  export interface AgGridImplProps {
4
4
  rowData?: any[];
5
5
  columnDefs?: ColDef[];
@@ -23,9 +23,12 @@ export interface AgGridImplProps {
23
23
  enableRangeSelection?: boolean;
24
24
  enableCharts?: boolean;
25
25
  contextMenu?: ContextMenuConfig;
26
+ treeData?: TreeDataConfig;
27
+ rowGrouping?: RowGroupingConfig;
28
+ excelExport?: ExcelExportConfig;
26
29
  }
27
30
  /**
28
31
  * AgGridImpl - The heavy implementation that imports AG Grid
29
32
  * This component is lazy-loaded to avoid including AG Grid in the initial bundle
30
33
  */
31
- export default function AgGridImpl({ rowData, columnDefs, gridOptions, pagination, paginationPageSize, domLayout, animateRows, rowSelection, theme, height, className, editable, editType, singleClickEdit, stopEditingWhenCellsLoseFocus, exportConfig, statusBar, callbacks, columnConfig, enableRangeSelection, enableCharts, contextMenu, }: AgGridImplProps): import("react/jsx-runtime").JSX.Element;
34
+ export default function AgGridImpl({ rowData, columnDefs, gridOptions, pagination, paginationPageSize, domLayout, animateRows, rowSelection, theme, height, className, editable, editType, singleClickEdit, stopEditingWhenCellsLoseFocus, exportConfig, statusBar, callbacks, columnConfig, enableRangeSelection, enableCharts, contextMenu, treeData, rowGrouping, excelExport, }: AgGridImplProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { ObjectAgGridImplProps } from './object-aggrid.types';
2
+ /**
3
+ * ObjectAgGridImpl - Metadata-driven AG Grid implementation
4
+ * Fetches object metadata and data from ObjectStack and renders the grid
5
+ */
6
+ export default function ObjectAgGridImpl({ objectName, dataSource, fields: providedFields, fieldNames, filters, sort, pageSize, pagination, domLayout, animateRows, rowSelection, theme, height, className, editable, editType, singleClickEdit, stopEditingWhenCellsLoseFocus, exportConfig, statusBar, callbacks, columnConfig, enableRangeSelection, enableCharts, contextMenu, }: ObjectAgGridImplProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Virtual Scrolling in AG Grid
10
+ *
11
+ * AG Grid provides built-in virtual scrolling by default, which renders only
12
+ * the visible rows in the viewport. This is a core feature of AG Grid and
13
+ * requires no additional configuration.
14
+ *
15
+ * ## How It Works
16
+ *
17
+ * - AG Grid automatically virtualizes rows by rendering only visible rows
18
+ * - As you scroll, rows are recycled and reused for new data
19
+ * - This provides excellent performance even with datasets of 100,000+ rows
20
+ *
21
+ * ## Performance Tips
22
+ *
23
+ * 1. **Row Buffer**: Adjust `rowBuffer` to control how many extra rows are rendered
24
+ * ```ts
25
+ * gridOptions: { rowBuffer: 10 } // Render 10 extra rows above/below viewport
26
+ * ```
27
+ *
28
+ * 2. **Suppress Animations**: Disable animations for very large datasets
29
+ * ```ts
30
+ * animateRows: false
31
+ * ```
32
+ *
33
+ * 3. **Debounce Vertical Scroll**: Add delay to vertical scroll updates
34
+ * ```ts
35
+ * gridOptions: { debounceVerticalScrollbar: true }
36
+ * ```
37
+ *
38
+ * 4. **Row Height**: Use fixed row heights for better performance
39
+ * ```ts
40
+ * gridOptions: { rowHeight: 40 }
41
+ * ```
42
+ *
43
+ * ## Example Usage
44
+ *
45
+ * ```tsx
46
+ * <AgGrid
47
+ * rowData={largeDataset} // 10,000+ items
48
+ * columnDefs={columns}
49
+ * gridOptions={{
50
+ * rowBuffer: 10,
51
+ * rowHeight: 40,
52
+ * debounceVerticalScrollbar: true,
53
+ * }}
54
+ * animateRows={false}
55
+ * />
56
+ * ```
57
+ *
58
+ * ## References
59
+ *
60
+ * - [AG Grid Row Virtualisation](https://www.ag-grid.com/javascript-data-grid/dom-virtualisation/)
61
+ * - [Performance Best Practices](https://www.ag-grid.com/javascript-data-grid/performance/)
62
+ */
63
+ export declare const VIRTUAL_SCROLLING_DOCS: {
64
+ enabled: boolean;
65
+ automatic: boolean;
66
+ recommendedSettings: {
67
+ rowBuffer: number;
68
+ rowHeight: number;
69
+ debounceVerticalScrollbar: boolean;
70
+ animateRows: boolean;
71
+ };
72
+ };
@@ -0,0 +1,67 @@
1
+ import { Root } from 'react-dom/client';
2
+ import { ICellRendererParams, ICellEditorParams } from 'ag-grid-community';
3
+ import { FieldMetadata } from '../../types/src';
4
+ /**
5
+ * AG Grid Cell Renderer using Field Widgets (Read-only mode)
6
+ */
7
+ export declare class FieldWidgetCellRenderer {
8
+ eGui: HTMLDivElement;
9
+ root: Root | null;
10
+ init(params: ICellRendererParams & {
11
+ field: FieldMetadata;
12
+ }): void;
13
+ getGui(): HTMLDivElement;
14
+ refresh(params: ICellRendererParams & {
15
+ field: FieldMetadata;
16
+ }): boolean;
17
+ destroy(): void;
18
+ }
19
+ /**
20
+ * AG Grid Cell Editor using Field Widgets (Edit mode)
21
+ */
22
+ export declare class FieldWidgetCellEditor {
23
+ eGui: HTMLDivElement;
24
+ root: Root | null;
25
+ currentValue: unknown;
26
+ params: ICellEditorParams & {
27
+ field: FieldMetadata;
28
+ };
29
+ init(params: ICellEditorParams & {
30
+ field: FieldMetadata;
31
+ }): void;
32
+ getGui(): HTMLDivElement;
33
+ getValue(): unknown;
34
+ destroy(): void;
35
+ isPopup(): boolean;
36
+ }
37
+ /**
38
+ * Factory function to create cell renderer with field metadata
39
+ */
40
+ export declare function createFieldCellRenderer(field: FieldMetadata): {
41
+ new (): {
42
+ init(params: ICellRendererParams): void;
43
+ refresh(params: ICellRendererParams): boolean;
44
+ eGui: HTMLDivElement;
45
+ root: Root | null;
46
+ getGui(): HTMLDivElement;
47
+ destroy(): void;
48
+ };
49
+ };
50
+ /**
51
+ * Factory function to create cell editor with field metadata
52
+ */
53
+ export declare function createFieldCellEditor(field: FieldMetadata): {
54
+ new (): {
55
+ init(params: ICellEditorParams): void;
56
+ eGui: HTMLDivElement;
57
+ root: Root | null;
58
+ currentValue: unknown;
59
+ params: ICellEditorParams & {
60
+ field: FieldMetadata;
61
+ };
62
+ getGui(): HTMLDivElement;
63
+ getValue(): unknown;
64
+ destroy(): void;
65
+ isPopup(): boolean;
66
+ };
67
+ };
@@ -1,6 +1,8 @@
1
1
  import { default as React } from 'react';
2
- import { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig } from './types';
3
- export type { AgGridSchema, SimpleColumnDef, AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig } from './types';
2
+ import { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig, TreeDataConfig, RowGroupingConfig, ExcelExportConfig } from './types';
3
+ import { DataSource } from '../../types/src';
4
+ export type { AgGridSchema, SimpleColumnDef, AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig, TreeDataConfig, RowGroupingConfig, ExcelExportConfig } from './types';
5
+ export type { ObjectAgGridSchema } from './object-aggrid.types';
4
6
  export interface AgGridRendererProps {
5
7
  schema: {
6
8
  type: string;
@@ -27,6 +29,9 @@ export interface AgGridRendererProps {
27
29
  enableRangeSelection?: boolean;
28
30
  enableCharts?: boolean;
29
31
  contextMenu?: ContextMenuConfig;
32
+ treeData?: TreeDataConfig;
33
+ rowGrouping?: RowGroupingConfig;
34
+ excelExport?: ExcelExportConfig;
30
35
  };
31
36
  }
32
37
  /**
@@ -34,6 +39,46 @@ export interface AgGridRendererProps {
34
39
  * This wrapper handles lazy loading internally using React.Suspense
35
40
  */
36
41
  export declare const AgGridRenderer: React.FC<AgGridRendererProps>;
42
+ /**
43
+ * ObjectAgGridRenderer - The public API for the metadata-driven AG Grid component
44
+ * This wrapper handles lazy loading internally using React.Suspense
45
+ */
46
+ export interface ObjectAgGridRendererProps {
47
+ schema: {
48
+ type: string;
49
+ id?: string;
50
+ className?: string;
51
+ objectName: string;
52
+ dataSource?: DataSource;
53
+ fields?: any[];
54
+ fieldNames?: string[];
55
+ filters?: Record<string, any>;
56
+ sort?: Record<string, 'asc' | 'desc'>;
57
+ pageSize?: number;
58
+ pagination?: boolean;
59
+ domLayout?: 'normal' | 'autoHeight' | 'print';
60
+ animateRows?: boolean;
61
+ rowSelection?: 'single' | 'multiple';
62
+ theme?: 'alpine' | 'balham' | 'material' | 'quartz';
63
+ height?: number | string;
64
+ editable?: boolean;
65
+ editType?: 'fullRow';
66
+ singleClickEdit?: boolean;
67
+ stopEditingWhenCellsLoseFocus?: boolean;
68
+ exportConfig?: ExportConfig;
69
+ statusBar?: StatusBarConfig;
70
+ callbacks?: AgGridCallbacks & {
71
+ onDataLoaded?: (data: any[]) => void;
72
+ onDataError?: (error: Error) => void;
73
+ };
74
+ columnConfig?: ColumnConfig;
75
+ enableRangeSelection?: boolean;
76
+ enableCharts?: boolean;
77
+ contextMenu?: ContextMenuConfig;
78
+ };
79
+ }
80
+ export declare const ObjectAgGridRenderer: React.FC<ObjectAgGridRendererProps>;
37
81
  export declare const aggridComponents: {
38
82
  aggrid: React.FC<AgGridRendererProps>;
83
+ 'object-aggrid': React.FC<ObjectAgGridRendererProps>;
39
84
  };
@@ -0,0 +1,74 @@
1
+ import { DataSource, FieldMetadata } from '../../types/src';
2
+ import { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig } from './types';
3
+ /**
4
+ * Object AgGrid schema for metadata-driven grid
5
+ */
6
+ export interface ObjectAgGridSchema {
7
+ type: 'object-aggrid';
8
+ id?: string;
9
+ className?: string;
10
+ objectName: string;
11
+ dataSource: DataSource;
12
+ fields?: FieldMetadata[];
13
+ fieldNames?: string[];
14
+ filters?: Record<string, any>;
15
+ sort?: Record<string, 'asc' | 'desc'>;
16
+ pageSize?: number;
17
+ pagination?: boolean;
18
+ domLayout?: 'normal' | 'autoHeight' | 'print';
19
+ animateRows?: boolean;
20
+ rowSelection?: 'single' | 'multiple';
21
+ editable?: boolean;
22
+ editType?: 'fullRow';
23
+ singleClickEdit?: boolean;
24
+ stopEditingWhenCellsLoseFocus?: boolean;
25
+ exportConfig?: ExportConfig;
26
+ statusBar?: StatusBarConfig;
27
+ columnConfig?: ColumnConfig;
28
+ enableRangeSelection?: boolean;
29
+ enableCharts?: boolean;
30
+ contextMenu?: ContextMenuConfig;
31
+ callbacks?: AgGridCallbacks & {
32
+ onDataLoaded?: (data: any[]) => void;
33
+ onDataError?: (error: Error) => void;
34
+ };
35
+ theme?: 'alpine' | 'balham' | 'material' | 'quartz';
36
+ height?: number | string;
37
+ }
38
+ /**
39
+ * Props for ObjectAgGridImpl component
40
+ */
41
+ export interface ObjectAgGridImplProps {
42
+ objectName: string;
43
+ dataSource?: DataSource;
44
+ fields?: FieldMetadata[];
45
+ fieldNames?: string[];
46
+ filters?: Record<string, any>;
47
+ sort?: Record<string, 'asc' | 'desc'>;
48
+ pageSize?: number;
49
+ pagination?: boolean;
50
+ domLayout?: 'normal' | 'autoHeight' | 'print';
51
+ animateRows?: boolean;
52
+ rowSelection?: 'single' | 'multiple';
53
+ theme?: 'alpine' | 'balham' | 'material' | 'quartz';
54
+ height?: number | string;
55
+ className?: string;
56
+ editable?: boolean;
57
+ editType?: 'fullRow';
58
+ singleClickEdit?: boolean;
59
+ stopEditingWhenCellsLoseFocus?: boolean;
60
+ exportConfig?: ExportConfig;
61
+ statusBar?: StatusBarConfig;
62
+ callbacks?: AgGridCallbacks & {
63
+ onDataLoaded?: (data: any[]) => void;
64
+ onDataError?: (error: Error) => void;
65
+ };
66
+ columnConfig?: ColumnConfig;
67
+ enableRangeSelection?: boolean;
68
+ enableCharts?: boolean;
69
+ contextMenu?: ContextMenuConfig;
70
+ }
71
+ /**
72
+ * Field type to AG Grid filter type mapping
73
+ */
74
+ export declare const FIELD_TYPE_TO_FILTER_TYPE: Record<string, string | boolean>;
@@ -7,7 +7,7 @@ export interface AgGridCallbacks {
7
7
  onRowClicked?: (event: RowClickedEvent) => void;
8
8
  onSelectionChanged?: (event: SelectionChangedEvent) => void;
9
9
  onCellValueChanged?: (event: CellValueChangedEvent) => void;
10
- onExport?: (data: any[], format: 'csv') => void;
10
+ onExport?: (data: any[], format: 'csv' | 'excel') => void;
11
11
  onContextMenuAction?: (action: string, rowData: any) => void;
12
12
  }
13
13
  /**
@@ -19,6 +19,50 @@ export interface ExportConfig {
19
19
  skipColumnHeaders?: boolean;
20
20
  allColumns?: boolean;
21
21
  onlySelected?: boolean;
22
+ format?: 'csv' | 'excel';
23
+ }
24
+ /**
25
+ * Tree data configuration
26
+ */
27
+ export interface TreeDataConfig {
28
+ enabled?: boolean;
29
+ /** Field that contains the hierarchy path (array of strings) */
30
+ pathField?: string;
31
+ /** Field that contains parent ID for parent-child relationships */
32
+ parentIdField?: string;
33
+ /** Field that contains the unique ID */
34
+ idField?: string;
35
+ /** Whether to expand all rows by default */
36
+ expandAll?: boolean;
37
+ /** Depth to expand to by default */
38
+ expandDepth?: number;
39
+ }
40
+ /**
41
+ * Row grouping configuration
42
+ */
43
+ export interface RowGroupingConfig {
44
+ enabled?: boolean;
45
+ /** Fields to group by */
46
+ groupByFields?: string[];
47
+ /** Whether to show group row count */
48
+ showRowCount?: boolean;
49
+ /** Whether to allow user to change grouping */
50
+ userGroupable?: boolean;
51
+ /** Aggregation functions for grouped columns */
52
+ aggregations?: Record<string, 'sum' | 'avg' | 'count' | 'min' | 'max' | 'first' | 'last'>;
53
+ }
54
+ /**
55
+ * Excel export configuration
56
+ */
57
+ export interface ExcelExportConfig {
58
+ enabled?: boolean;
59
+ fileName?: string;
60
+ sheetName?: string;
61
+ includeHeaders?: boolean;
62
+ includeGrouping?: boolean;
63
+ onlySelected?: boolean;
64
+ /** Custom column widths */
65
+ columnWidths?: Record<string, number>;
22
66
  }
23
67
  /**
24
68
  * Status bar configuration
@@ -72,6 +116,9 @@ export interface AgGridSchema {
72
116
  enableRangeSelection?: boolean;
73
117
  enableCharts?: boolean;
74
118
  contextMenu?: ContextMenuConfig;
119
+ treeData?: TreeDataConfig;
120
+ rowGrouping?: RowGroupingConfig;
121
+ excelExport?: ExcelExportConfig;
75
122
  callbacks?: AgGridCallbacks;
76
123
  theme?: 'alpine' | 'balham' | 'material' | 'quartz';
77
124
  height?: number | string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-aggrid",
3
- "version": "0.4.1",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "AG Grid data grid plugin for Object UI, powered by AG Grid Community",
@@ -25,10 +25,12 @@
25
25
  "./style.css": "./dist/index.css"
26
26
  },
27
27
  "dependencies": {
28
- "@object-ui/components": "0.3.1",
29
- "@object-ui/core": "0.3.1",
30
- "@object-ui/react": "0.3.1",
31
- "@object-ui/types": "0.3.1"
28
+ "@object-ui/components": "2.0.0",
29
+ "@object-ui/core": "2.0.0",
30
+ "@object-ui/fields": "2.0.0",
31
+ "@object-ui/react": "2.0.0",
32
+ "@object-ui/types": "2.0.0",
33
+ "@object-ui/data-objectstack": "2.0.0"
32
34
  },
33
35
  "peerDependencies": {
34
36
  "react": "^18.0.0 || ^19.0.0",
@@ -37,11 +39,11 @@
37
39
  "ag-grid-react": "^32.0.0"
38
40
  },
39
41
  "devDependencies": {
40
- "@types/react": "^19.2.9",
42
+ "@types/react": "^19.2.13",
41
43
  "@types/react-dom": "^19.2.3",
42
- "@vitejs/plugin-react": "^4.2.1",
43
- "ag-grid-community": "^35.0.1",
44
- "ag-grid-react": "^32.3.4",
44
+ "@vitejs/plugin-react": "^5.1.3",
45
+ "ag-grid-community": "^32.3.9",
46
+ "ag-grid-react": "^32.3.9",
45
47
  "typescript": "^5.9.3",
46
48
  "vite": "^7.3.1",
47
49
  "vite-plugin-dts": "^4.5.4"
@@ -9,7 +9,7 @@
9
9
  import React, { useMemo, useRef, useCallback } from 'react';
10
10
  import { AgGridReact } from 'ag-grid-react';
11
11
  import type { ColDef, GridOptions, GridReadyEvent, CellClickedEvent, RowClickedEvent, SelectionChangedEvent, CellValueChangedEvent, StatusPanelDef, GetContextMenuItemsParams, MenuItemDef } from 'ag-grid-community';
12
- import type { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig } from './types';
12
+ import type { AgGridCallbacks, ExportConfig, StatusBarConfig, ColumnConfig, ContextMenuConfig, TreeDataConfig, RowGroupingConfig, ExcelExportConfig } from './types';
13
13
 
14
14
  export interface AgGridImplProps {
15
15
  rowData?: any[];
@@ -34,6 +34,9 @@ export interface AgGridImplProps {
34
34
  enableRangeSelection?: boolean;
35
35
  enableCharts?: boolean;
36
36
  contextMenu?: ContextMenuConfig;
37
+ treeData?: TreeDataConfig;
38
+ rowGrouping?: RowGroupingConfig;
39
+ excelExport?: ExcelExportConfig;
37
40
  }
38
41
 
39
42
  /**
@@ -63,6 +66,9 @@ export default function AgGridImpl({
63
66
  enableRangeSelection = false,
64
67
  enableCharts = false,
65
68
  contextMenu,
69
+ treeData,
70
+ rowGrouping,
71
+ excelExport,
66
72
  }: AgGridImplProps) {
67
73
  const gridRef = useRef<any>(null);
68
74
 
@@ -113,6 +119,31 @@ export default function AgGridImpl({
113
119
  }
114
120
  }, [exportConfig, callbacks, rowData]);
115
121
 
122
+ // Excel-compatible CSV Export handler
123
+ // Exports CSV format which can be opened directly in Excel
124
+ const handleExportExcel = useCallback(() => {
125
+ if (!gridRef.current?.api) return;
126
+
127
+ const fileName = excelExport?.fileName || exportConfig?.fileName || 'export.csv';
128
+ const includeHeaders = excelExport?.includeHeaders !== false;
129
+
130
+ const params = {
131
+ fileName,
132
+ skipColumnHeaders: !includeHeaders,
133
+ allColumns: true,
134
+ onlySelected: excelExport?.onlySelected || false,
135
+ };
136
+
137
+ gridRef.current.api.exportDataAsCsv(params);
138
+
139
+ if (callbacks?.onExport) {
140
+ const data = excelExport?.onlySelected
141
+ ? gridRef.current.api.getSelectedRows()
142
+ : rowData;
143
+ callbacks.onExport(data || [], 'excel');
144
+ }
145
+ }, [excelExport, exportConfig, callbacks, rowData]);
146
+
116
147
  // Context Menu handler
117
148
  const getContextMenuItems = useCallback((params: GetContextMenuItemsParams): (string | MenuItemDef)[] => {
118
149
  if (!contextMenu?.enabled) return [];
@@ -127,6 +158,12 @@ export default function AgGridImpl({
127
158
  icon: '<span>📥</span>',
128
159
  action: () => handleExportCSV(),
129
160
  });
161
+ } else if (item === 'export-excel') {
162
+ items.push({
163
+ name: 'Export Excel (CSV)',
164
+ icon: '<span>📊</span>',
165
+ action: () => handleExportExcel(),
166
+ });
130
167
  } else if (item === 'autoSizeAll') {
131
168
  items.push({
132
169
  name: 'Auto-size All Columns',
@@ -170,7 +207,7 @@ export default function AgGridImpl({
170
207
  }
171
208
 
172
209
  return items;
173
- }, [contextMenu, handleExportCSV, callbacks]);
210
+ }, [contextMenu, handleExportCSV, handleExportExcel, callbacks]);
174
211
 
175
212
  // Event handlers
176
213
  const handleCellClicked = useCallback((event: CellClickedEvent) => {
@@ -218,12 +255,23 @@ export default function AgGridImpl({
218
255
  }
219
256
  }
220
257
 
258
+ // Apply grouping
259
+ if (rowGrouping?.enabled && rowGrouping.groupByFields?.includes(col.field || '')) {
260
+ processed.rowGroup = true;
261
+ processed.hide = true;
262
+ }
263
+
264
+ // Apply aggregation
265
+ if (rowGrouping?.aggregations && col.field && rowGrouping.aggregations[col.field]) {
266
+ processed.aggFunc = rowGrouping.aggregations[col.field];
267
+ }
268
+
221
269
  return processed;
222
270
  });
223
- }, [columnDefs, editable, columnConfig]);
271
+ }, [columnDefs, editable, columnConfig, rowGrouping]);
224
272
 
225
273
  // Merge grid options with props
226
- const mergedGridOptions: GridOptions = useMemo(() => ({
274
+ const mergedGridOptions = useMemo(() => ({
227
275
  ...gridOptions,
228
276
  pagination,
229
277
  paginationPageSize,
@@ -237,10 +285,38 @@ export default function AgGridImpl({
237
285
  enableRangeSelection,
238
286
  enableCharts,
239
287
  getContextMenuItems: contextMenu?.enabled ? getContextMenuItems : undefined,
288
+ // Tree data support
289
+ ...(treeData?.enabled ? {
290
+ treeData: true,
291
+ getDataPath: treeData.pathField
292
+ ? (data: any) => data[treeData.pathField as string]
293
+ : undefined,
294
+ autoGroupColumnDef: {
295
+ headerName: 'Hierarchy',
296
+ minWidth: 250,
297
+ cellRendererParams: {
298
+ suppressCount: false,
299
+ },
300
+ },
301
+ groupDefaultExpanded: treeData.expandAll ? -1 : (treeData.expandDepth ?? 0),
302
+ } : {}),
303
+ // Row grouping
304
+ ...(rowGrouping?.enabled ? {
305
+ groupDefaultExpanded: rowGrouping.groupByFields?.length ? 1 : 0,
306
+ autoGroupColumnDef: {
307
+ minWidth: 200,
308
+ cellRendererParams: {
309
+ suppressCount: !rowGrouping.showRowCount,
310
+ },
311
+ },
312
+ } : {}),
240
313
  // Default options for better UX
241
314
  suppressCellFocus: !editable,
242
315
  enableCellTextSelection: true,
243
316
  ensureDomOrder: true,
317
+ // Virtual scrolling optimizations for large datasets
318
+ rowBuffer: gridOptions.rowBuffer ?? 10,
319
+ debounceVerticalScrollbar: gridOptions.debounceVerticalScrollbar ?? (rowData.length > 1000),
244
320
  // Event handlers
245
321
  onCellClicked: handleCellClicked,
246
322
  onRowClicked: handleRowClicked,
@@ -262,7 +338,10 @@ export default function AgGridImpl({
262
338
  enableCharts,
263
339
  contextMenu,
264
340
  getContextMenuItems,
341
+ treeData,
342
+ rowGrouping,
265
343
  editable,
344
+ rowData.length,
266
345
  handleCellClicked,
267
346
  handleRowClicked,
268
347
  handleSelectionChanged,
@@ -290,14 +369,24 @@ export default function AgGridImpl({
290
369
 
291
370
  return (
292
371
  <div className="ag-grid-container">
293
- {exportConfig?.enabled && (
372
+ {(exportConfig?.enabled || excelExport?.enabled) && (
294
373
  <div className="mb-2 flex gap-2">
295
- <button
296
- onClick={handleExportCSV}
297
- className="px-3 py-1.5 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md transition-colors"
298
- >
299
- Export CSV
300
- </button>
374
+ {exportConfig?.enabled && (
375
+ <button
376
+ onClick={handleExportCSV}
377
+ className="px-3 py-1.5 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md transition-colors"
378
+ >
379
+ Export CSV
380
+ </button>
381
+ )}
382
+ {excelExport?.enabled && (
383
+ <button
384
+ onClick={handleExportExcel}
385
+ className="px-3 py-1.5 text-sm font-medium text-white bg-green-600 hover:bg-green-700 rounded-md transition-colors"
386
+ >
387
+ Export Excel (CSV)
388
+ </button>
389
+ )}
301
390
  </div>
302
391
  )}
303
392
  <div