99import React , { useMemo , useRef , useCallback } from 'react' ;
1010import { AgGridReact } from 'ag-grid-react' ;
1111import 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' ;
1313
1414export interface AgGridImplProps {
1515 rowData ?: any [ ] ;
@@ -34,6 +34,9 @@ export interface AgGridImplProps {
3434 enableRangeSelection ?: boolean ;
3535 enableCharts ?: boolean ;
3636 contextMenu ?: ContextMenuConfig ;
37+ treeData ?: TreeDataConfig ;
38+ rowGrouping ?: RowGroupingConfig ;
39+ excelExport ?: ExcelExportConfig ;
3740}
3841
3942/**
@@ -63,6 +66,9 @@ export default function AgGridImpl({
6366 enableRangeSelection = false ,
6467 enableCharts = false ,
6568 contextMenu,
69+ treeData,
70+ rowGrouping,
71+ excelExport,
6672} : AgGridImplProps ) {
6773 const gridRef = useRef < any > ( null ) ;
6874
@@ -113,6 +119,31 @@ export default function AgGridImpl({
113119 }
114120 } , [ exportConfig , callbacks , rowData ] ) ;
115121
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+
116147 // Context Menu handler
117148 const getContextMenuItems = useCallback ( ( params : GetContextMenuItemsParams ) : ( string | MenuItemDef ) [ ] => {
118149 if ( ! contextMenu ?. enabled ) return [ ] ;
@@ -127,6 +158,12 @@ export default function AgGridImpl({
127158 icon : '<span>📥</span>' ,
128159 action : ( ) => handleExportCSV ( ) ,
129160 } ) ;
161+ } else if ( item === 'export-excel' ) {
162+ items . push ( {
163+ name : 'Export Excel (CSV)' ,
164+ icon : '<span>📊</span>' ,
165+ action : ( ) => handleExportExcel ( ) ,
166+ } ) ;
130167 } else if ( item === 'autoSizeAll' ) {
131168 items . push ( {
132169 name : 'Auto-size All Columns' ,
@@ -170,7 +207,7 @@ export default function AgGridImpl({
170207 }
171208
172209 return items ;
173- } , [ contextMenu , handleExportCSV , callbacks ] ) ;
210+ } , [ contextMenu , handleExportCSV , handleExportExcel , callbacks ] ) ;
174211
175212 // Event handlers
176213 const handleCellClicked = useCallback ( ( event : CellClickedEvent ) => {
@@ -218,9 +255,20 @@ export default function AgGridImpl({
218255 }
219256 }
220257
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+
221269 return processed ;
222270 } ) ;
223- } , [ columnDefs , editable , columnConfig ] ) ;
271+ } , [ columnDefs , editable , columnConfig , rowGrouping ] ) ;
224272
225273 // Merge grid options with props
226274 const mergedGridOptions = useMemo ( ( ) => ( {
@@ -237,6 +285,31 @@ export default function AgGridImpl({
237285 enableRangeSelection,
238286 enableCharts,
239287 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+ } : { } ) ,
240313 // Default options for better UX
241314 suppressCellFocus : ! editable ,
242315 enableCellTextSelection : true ,
@@ -265,6 +338,8 @@ export default function AgGridImpl({
265338 enableCharts ,
266339 contextMenu ,
267340 getContextMenuItems ,
341+ treeData ,
342+ rowGrouping ,
268343 editable ,
269344 rowData . length ,
270345 handleCellClicked ,
@@ -294,14 +369,24 @@ export default function AgGridImpl({
294369
295370 return (
296371 < div className = "ag-grid-container" >
297- { exportConfig ?. enabled && (
372+ { ( exportConfig ?. enabled || excelExport ?. enabled ) && (
298373 < div className = "mb-2 flex gap-2" >
299- < button
300- onClick = { handleExportCSV }
301- className = "px-3 py-1.5 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md transition-colors"
302- >
303- Export CSV
304- </ 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+ ) }
305390 </ div >
306391 ) }
307392 < div
0 commit comments