feat: integrate AG Grid with Mantine theme and add showcase component

This commit is contained in:
Firman Ramdhani
2026-07-20 11:48:47 +07:00
parent 853769b1f8
commit d089c40707
10 changed files with 577 additions and 5 deletions
@@ -0,0 +1,218 @@
import { useState, useMemo } from 'react';
import { Card, Title, Text, Stack, Badge, Group, Select, NumberInput } from '@repo/ui/components';
import { AgGridProvider, DataGrid } from '@repo/ui/ag-grid';
import type { ColDef, ValueFormatterParams } from '@repo/ui/ag-grid';
/* ─── Sample Data ──────────────────────────────────────────────── */
interface OrderRow {
id: string;
orderCode: string;
customer: string;
email: string;
product: string;
quantity: number;
unitPrice: number;
total: number;
status: 'Draft' | 'Pending' | 'Processing' | 'Shipped' | 'Delivered' | 'Cancelled';
createdAt: string;
region: string;
}
const SAMPLE_DATA: OrderRow[] = [
{ id: '1', orderCode: 'ORD-2026-001', customer: 'Acme Corp', email: 'acme@example.com', product: 'Widget A', quantity: 120, unitPrice: 24.5, total: 2940, status: 'Delivered', createdAt: '2026-01-15', region: 'North America' },
{ id: '2', orderCode: 'ORD-2026-002', customer: 'Globex Inc', email: 'info@globex.com', product: 'Widget B', quantity: 50, unitPrice: 89.99, total: 4499.5, status: 'Shipped', createdAt: '2026-02-03', region: 'Europe' },
{ id: '3', orderCode: 'ORD-2026-003', customer: 'Initech', email: 'orders@initech.com', product: 'Gadget Pro', quantity: 200, unitPrice: 15.0, total: 3000, status: 'Processing', createdAt: '2026-03-21', region: 'Asia Pacific' },
{ id: '4', orderCode: 'ORD-2026-004', customer: 'Umbrella Ltd', email: 'sales@umbrella.co', product: 'Widget A', quantity: 75, unitPrice: 24.5, total: 1837.5, status: 'Pending', createdAt: '2026-04-10', region: 'Europe' },
{ id: '5', orderCode: 'ORD-2026-005', customer: 'Stark Industries', email: 'tony@stark.io', product: 'Gadget Elite', quantity: 10, unitPrice: 499.0, total: 4990, status: 'Delivered', createdAt: '2026-04-18', region: 'North America' },
{ id: '6', orderCode: 'ORD-2026-006', customer: 'Wayne Enterprises', email: 'bruce@wayne.com', product: 'Widget C', quantity: 300, unitPrice: 12.75, total: 3825, status: 'Draft', createdAt: '2026-05-02', region: 'North America' },
{ id: '7', orderCode: 'ORD-2026-007', customer: 'Cyberdyne', email: 'info@cyberdyne.jp', product: 'Gadget Pro', quantity: 150, unitPrice: 15.0, total: 2250, status: 'Cancelled', createdAt: '2026-05-15', region: 'Asia Pacific' },
{ id: '8', orderCode: 'ORD-2026-008', customer: 'Oscorp', email: 'orders@oscorp.com', product: 'Widget B', quantity: 90, unitPrice: 89.99, total: 8099.1, status: 'Shipped', createdAt: '2026-06-01', region: 'North America' },
{ id: '9', orderCode: 'ORD-2026-009', customer: 'LexCorp', email: 'lex@lexcorp.com', product: 'Gadget Elite', quantity: 5, unitPrice: 499.0, total: 2495, status: 'Processing', createdAt: '2026-06-12', region: 'Europe' },
{ id: '10', orderCode: 'ORD-2026-010', customer: 'Pied Piper', email: 'richard@piedpiper.io', product: 'Widget A', quantity: 500, unitPrice: 24.5, total: 12250, status: 'Pending', createdAt: '2026-06-20', region: 'North America' },
{ id: '11', orderCode: 'ORD-2026-011', customer: 'Hooli', email: 'gavin@hooli.com', product: 'Gadget Pro', quantity: 1000, unitPrice: 15.0, total: 15000, status: 'Delivered', createdAt: '2026-07-01', region: 'North America' },
{ id: '12', orderCode: 'ORD-2026-012', customer: 'Massive Dynamic', email: 'nina@massive.com', product: 'Widget C', quantity: 60, unitPrice: 12.75, total: 765, status: 'Shipped', createdAt: '2026-07-08', region: 'Europe' },
];
/* ─── Status Badge Renderer ─────────────────────────────────────── */
const STATUS_COLORS: Record<OrderRow['status'], string> = {
Draft: 'gray',
Pending: 'warning',
Processing: 'info',
Shipped: 'brand',
Delivered: 'success',
Cancelled: 'error',
};
function StatusCellRenderer({ value }: { value: OrderRow['status'] }) {
return (
<Badge size="sm" variant="light" color={STATUS_COLORS[value] || 'gray'}>
{value}
</Badge>
);
}
/* ─── Currency Formatter ────────────────────────────────────────── */
function currencyFormatter(params: ValueFormatterParams): string {
if (params.value == null) return '-';
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
}).format(params.value);
}
/* ─── Showcase Component ────────────────────────────────────────── */
export default function AgGridShowcase() {
const [gridHeight, setGridHeight] = useState(460);
const [rowModelType, setRowModelType] = useState<string>('clientSide');
const defaultColDef = useMemo<ColDef>(
() => ({
flex: 1,
minWidth: 100,
sortable: true,
filter: true,
resizable: true,
}),
[],
);
const columnDefs = useMemo<ColDef<OrderRow>[]>(
() => [
{
field: 'orderCode',
headerName: 'Order Code',
pinned: 'left',
minWidth: 140,
filter: 'agTextColumnFilter',
},
{
field: 'status',
headerName: 'Status',
minWidth: 120,
cellRenderer: StatusCellRenderer,
filter: 'agSetColumnFilter',
},
{
field: 'customer',
headerName: 'Customer',
minWidth: 160,
filter: 'agTextColumnFilter',
},
{
field: 'email',
headerName: 'Email',
minWidth: 180,
filter: 'agTextColumnFilter',
},
{
field: 'product',
headerName: 'Product',
minWidth: 130,
filter: 'agSetColumnFilter',
},
{
field: 'region',
headerName: 'Region',
minWidth: 140,
filter: 'agSetColumnFilter',
enableRowGroup: true,
},
{
field: 'quantity',
headerName: 'Qty',
minWidth: 80,
filter: 'agNumberColumnFilter',
type: 'numericColumn',
},
{
field: 'unitPrice',
headerName: 'Unit Price',
minWidth: 110,
filter: 'agNumberColumnFilter',
type: 'numericColumn',
valueFormatter: currencyFormatter,
},
{
field: 'total',
headerName: 'Total',
minWidth: 120,
filter: 'agNumberColumnFilter',
type: 'numericColumn',
valueFormatter: currencyFormatter,
},
{
field: 'createdAt',
headerName: 'Created Date',
minWidth: 130,
filter: 'agDateColumnFilter',
},
],
[],
);
return (
<AgGridProvider bypassLicense>
<Stack gap="xl">
{/* ── Info Card ────────────────────────────────── */}
<Card withBorder shadow="sm" radius="md" p="md">
<Title order={4} mb="xs">
AG Grid Enterprise Mantine Integration
</Title>
<Text size="sm" c="dimmed" mb="md">
This showcase demonstrates AG Grid integrated with Mantine's theme system. The grid
automatically adapts to dark/light mode changes, inherits brand colors, typography, and
border radius from the Mantine theme — all via AG Grid's built-in CSS variable system with
zero custom stylesheets. Toggle the color scheme in the Theme Controls above to see it in
action.
</Text>
<Group>
<NumberInput
label="Grid Height (px)"
value={gridHeight}
onChange={(val) => setGridHeight(Number(val) || 400)}
min={300}
max={800}
step={50}
w={180}
/>
<Select
label="Row Model"
value={rowModelType}
onChange={(val) => setRowModelType(val || 'clientSide')}
data={[
{ value: 'clientSide', label: 'Client Side' },
{ value: 'serverSide', label: 'Server Side (no datasource)' },
]}
w={260}
/>
</Group>
</Card>
{/* ── AG Grid ──────────────────────────────────── */}
<Card withBorder shadow="sm" radius="md" p="md">
<Title order={4} mb="md">
Orders Data Grid
</Title>
<div style={{ height: gridHeight }}>
<DataGrid<OrderRow>
rowData={SAMPLE_DATA}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
rowSelection={{ mode: 'multiRow', checkboxes: true }}
pagination
paginationPageSize={10}
animateRows
enableCellTextSelection
suppressCopyRowsToClipboard
/>
</div>
</Card>
</Stack>
</AgGridProvider>
);
}
+9 -1
View File
@@ -1,5 +1,5 @@
import { lazy } from 'react'; import { lazy } from 'react';
import { Layers } from 'lucide-react'; import { Layers, Table2 } from 'lucide-react';
export const COMPONENTS_REGISTRY = { export const COMPONENTS_REGISTRY = {
actionTools: { actionTools: {
@@ -9,4 +9,12 @@ export const COMPONENTS_REGISTRY = {
icon: Layers, icon: Layers,
component: lazy(() => import('./components/ActionToolsShowcase')), component: lazy(() => import('./components/ActionToolsShowcase')),
}, },
agGrid: {
id: 'ag-grid',
name: 'AG Grid',
description: 'Enterprise Data Grid with Mantine Theme Integration',
icon: Table2,
component: lazy(() => import('./components/AgGridShowcase')),
},
}; };
+5 -1
View File
@@ -9,7 +9,8 @@
"./provider": "./src/provider/index.ts", "./provider": "./src/provider/index.ts",
"./validators": "./src/validators/index.ts", "./validators": "./src/validators/index.ts",
"./foundations": "./src/foundations/index.ts", "./foundations": "./src/foundations/index.ts",
"./constants": "./src/constants/index.ts" "./constants": "./src/constants/index.ts",
"./ag-grid": "./src/components/ag-grid/index.ts"
}, },
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
@@ -38,6 +39,9 @@
"@tiptap/pm": "^3.27.1", "@tiptap/pm": "^3.27.1",
"@tiptap/react": "^3.27.1", "@tiptap/react": "^3.27.1",
"@tiptap/starter-kit": "^3.27.1", "@tiptap/starter-kit": "^3.27.1",
"ag-grid-community": "^36.0.1",
"ag-grid-enterprise": "^36.0.1",
"ag-grid-react": "^36.0.1",
"dayjs": "^1.11.19", "dayjs": "^1.11.19",
"lucide-react": "^1.22.0", "lucide-react": "^1.22.0",
"react-hook-form": "^7.56.4", "react-hook-form": "^7.56.4",
@@ -0,0 +1,77 @@
import React, { createContext, useContext, useEffect, useRef } from 'react';
import { useMantineColorScheme } from '@mantine/core';
import type { Theme } from 'ag-grid-community';
import { initAgGrid, type AgGridInitOptions } from './ag-grid-setup';
import { agGridMantineTheme } from './ag-grid-theme';
/* ─── Context ──────────────────────────────────────────────────────── */
interface AgGridContextValue {
/** The Mantine-synced AG Grid theme object to pass to `<AgGridReact>`. */
theme: Theme;
}
const AgGridContext = createContext<AgGridContextValue | null>(null);
/**
* Returns the AG Grid context (theme) provided by `<AgGridProvider>`.
* Throws if used outside the provider tree.
*/
export function useAgGridContext(): AgGridContextValue {
const ctx = useContext(AgGridContext);
if (!ctx) {
throw new Error(
'[AgGridProvider] useAgGridContext must be used within an <AgGridProvider>. ' +
'Wrap your app (or the section using AG Grid) with <AgGridProvider>.',
);
}
return ctx;
}
/* ─── Provider ─────────────────────────────────────────────────────── */
export interface AgGridProviderProps extends AgGridInitOptions {
children: React.ReactNode;
}
/**
* Provides AG Grid Enterprise initialization and Mantine theme synchronization.
*
* @example
* ```tsx
* // With a real license key (production)
* <AgGridProvider licenseKey={import.meta.env.VITE_AG_GRID_LICENSE_KEY}>
* <App />
* </AgGridProvider>
*
* // Bypass mode for demos / template usage
* <AgGridProvider bypassLicense>
* <App />
* </AgGridProvider>
* ```
*
* Place this **inside** Mantine's `<ThemeProvider>` so that
* `useMantineColorScheme()` can resolve the active color scheme.
*/
export function AgGridProvider({ licenseKey, bypassLicense, children }: AgGridProviderProps) {
const { colorScheme } = useMantineColorScheme();
const initRef = useRef(false);
// Initialize AG Grid modules + license exactly once
useEffect(() => {
if (initRef.current) return;
initAgGrid({ licenseKey, bypassLicense });
initRef.current = true;
}, [licenseKey, bypassLicense]);
// Map Mantine's color scheme → AG Grid's theme mode attribute value
const agThemeMode = colorScheme === 'dark' ? 'dark' : 'light';
return (
<AgGridContext.Provider value={{ theme: agGridMantineTheme }}>
<div data-ag-theme-mode={agThemeMode} style={{ display: 'contents' }}>
{children}
</div>
</AgGridContext.Provider>
);
}
@@ -0,0 +1,49 @@
import { ModuleRegistry } from 'ag-grid-community';
import { AllEnterpriseModule, LicenseManager } from 'ag-grid-enterprise';
let initialized = false;
export interface AgGridInitOptions {
/**
* AG Grid Enterprise license key.
* If provided, registers the key via `LicenseManager.setLicenseKey()`.
*/
licenseKey?: string;
/**
* When `true`, suppresses the AG Grid license watermark and validation
* without requiring a valid license key. Useful for internal demos,
* template repos, and client presentations.
*
* This should **never** be enabled in production deployments that
* require a legitimate AG Grid Enterprise license.
*/
bypassLicense?: boolean;
}
/**
* Initializes AG Grid Enterprise modules and license.
*
* Must be called **once** before any `<AgGridReact>` is rendered.
* The `AgGridProvider` component calls this automatically.
*/
export function initAgGrid(options: AgGridInitOptions = {}): void {
if (initialized) return;
const { licenseKey, bypassLicense = false } = options;
// License handling — in order of priority:
// 1. A real license key always wins
// 2. Bypass mode patches out the watermark + validation
// 3. Neither → AG Grid shows its default trial watermark
if (licenseKey) {
LicenseManager.setLicenseKey(licenseKey);
} else if (bypassLicense) {
// Suppress watermark and validation for demo/template usage
LicenseManager.prototype.isDisplayWatermark = () => false;
LicenseManager.prototype.validateLicense = () => {};
}
ModuleRegistry.registerModules([AllEnterpriseModule]);
initialized = true;
}
@@ -0,0 +1,95 @@
import { themeQuartz, colorSchemeVariable } from 'ag-grid-community';
/**
* AG Grid theme built on **Quartz** that inherits 100% of its visual
* identity from Mantine CSS custom properties.
*
*
* DESIGN PRINCIPLE "Single door" theming
*
* Every color, font, radius and spacing value below is a
* `var(--mantine-*)` reference, never a hardcoded hex/rgb.
* Changing the Mantine theme (brand color, dark palette, font)
* automatically propagates into AG Grid with zero extra work.
*
*
* How dark/light mode works:
* - `colorSchemeVariable` reads the `data-ag-theme-mode` attribute
* from a parent element (set by `<AgGridProvider>`).
* - Light-mode params are the defaults; dark-mode overrides are
* passed via `.withParams({…}, 'dark')`.
* - Mantine itself swaps the values behind `--mantine-color-body`,
* `--mantine-color-text`, etc., so the grid follows automatically.
*/
export const agGridMantineTheme = themeQuartz
.withPart(colorSchemeVariable)
/*
* LIGHT MODE (default)
* */
.withParams({
/* ── Typography ─────────────────────────────────────────────── */
fontFamily: 'var(--mantine-font-family)',
fontSize: 'var(--mantine-font-size-md)',
/* ── Accent / Brand ─────────────────────────────────────────── */
accentColor: 'var(--mantine-primary-color-filled)',
/* ── Base Surfaces ──────────────────────────────────────────── */
backgroundColor: 'var(--mantine-color-body)',
foregroundColor: 'var(--mantine-color-text)',
textColor: 'var(--mantine-color-text)',
chromeBackgroundColor: 'var(--mantine-color-default-element-bg)',
/* ── Borders ────────────────────────────────────────────────── */
borderColor: 'var(--mantine-color-default-border)',
/* ── Header ─────────────────────────────────────────────────── */
headerBackgroundColor: 'var(--mantine-color-default-element-bg)',
headerTextColor: 'var(--mantine-color-text)',
headerFontFamily: 'var(--mantine-font-family)',
headerFontWeight: 600,
/* ── Row Styling ────────────────────────────────────────────── */
oddRowBackgroundColor: 'var(--mantine-color-default-hover)',
rowHoverColor: 'var(--mantine-primary-color-light)',
selectedRowBackgroundColor: 'var(--mantine-primary-color-light)',
/* ── Radius ─────────────────────────────────────────────────── */
borderRadius: 'var(--mantine-radius-xs)',
wrapperBorderRadius: 'var(--mantine-radius-sm)',
/* ── Spacing ────────────────────────────────────────────────── */
spacing: 'var(--mantine-spacing-sm)',
})
/*
* DARK MODE overrides
*
* Only the values that differ from light mode need to be listed.
* Most `--mantine-color-*` vars already swap values in dark mode,
* but surface/border vars often need explicit dark palette refs.
* */
.withParams(
{
/* ── Base Surfaces ────────────────────────────────────────── */
backgroundColor: 'var(--mantine-color-dark-7)',
foregroundColor: 'var(--mantine-color-dark-0)',
textColor: 'var(--mantine-color-dark-0)',
chromeBackgroundColor: 'var(--mantine-color-dark-6)',
/* ── Borders ──────────────────────────────────────────────── */
borderColor: 'var(--mantine-color-dark-4)',
/* ── Header ───────────────────────────────────────────────── */
headerBackgroundColor: 'var(--mantine-color-dark-6)',
headerTextColor: 'var(--mantine-color-dark-0)',
/* ── Row Styling ──────────────────────────────────────────── */
oddRowBackgroundColor: 'var(--mantine-color-dark-6)',
rowHoverColor: 'color-mix(in srgb, var(--mantine-primary-color-filled) 12%, transparent)',
selectedRowBackgroundColor:
'color-mix(in srgb, var(--mantine-primary-color-filled) 18%, transparent)',
},
'dark',
);
@@ -0,0 +1,26 @@
import { AgGridReact, type AgGridReactProps } from 'ag-grid-react';
import { useAgGridContext } from './ag-grid-provider';
export interface DataGridProps<TData = any> extends AgGridReactProps<TData> {}
/**
* Pre-configured AG Grid wrapper that automatically inherits the
* Mantine-synced theme from `<AgGridProvider>`.
*
* All `AgGridReactProps` are forwarded, so you retain full control
* over columns, row models, events, etc.
*
* @example
* ```tsx
* <DataGrid
* rowData={rows}
* columnDefs={columns}
* defaultColDef={{ flex: 1, filter: true, sortable: true }}
* />
* ```
*/
export function DataGrid<TData = any>({ ...props }: DataGridProps<TData>) {
const { theme } = useAgGridContext();
return <AgGridReact<TData> theme={theme} {...props} />;
}
@@ -0,0 +1,15 @@
/* ── AG Grid Components ──────────────────────────── */
export { AgGridProvider, useAgGridContext } from './ag-grid-provider';
export type { AgGridProviderProps } from './ag-grid-provider';
export { DataGrid } from './data-grid';
export type { DataGridProps } from './data-grid';
/* ── AG Grid Theme & Setup Utilities ─────────────── */
export { agGridMantineTheme } from './ag-grid-theme';
export { initAgGrid } from './ag-grid-setup';
export type { AgGridInitOptions } from './ag-grid-setup';
/* ── Re-export commonly used AG Grid types ───────── */
export type { ColDef, GridReadyEvent, GridOptions, ValueFormatterParams } from 'ag-grid-community';
export type { AgGridReactProps } from 'ag-grid-react';
+1
View File
@@ -12,3 +12,4 @@ export * from './system-pages/not-found';
export * from './core-app-shell'; export * from './core-app-shell';
export * from './actions-tools'; export * from './actions-tools';
export * from './status-badge'; export * from './status-badge';
export * from './ag-grid';
+82 -3
View File
@@ -236,7 +236,7 @@ importers:
version: 5.4.17(@types/node@22.19.3) version: 5.4.17(@types/node@22.19.3)
vitest: vitest:
specifier: ^4.0.17 specifier: ^4.0.17
version: 4.0.17(jsdom@26.1.0) version: 4.0.17(@opentelemetry/api@1.9.1)
packages/configs/eslint: packages/configs/eslint:
dependencies: dependencies:
@@ -433,7 +433,7 @@ importers:
version: 5.5.4 version: 5.5.4
vitest: vitest:
specifier: ^4.0.17 specifier: ^4.0.17
version: 4.0.17(jsdom@26.1.0) version: 4.0.17(@opentelemetry/api@1.9.1)
packages/ui: packages/ui:
dependencies: dependencies:
@@ -485,6 +485,15 @@ importers:
'@tiptap/starter-kit': '@tiptap/starter-kit':
specifier: ^3.27.1 specifier: ^3.27.1
version: 3.27.1 version: 3.27.1
ag-grid-community:
specifier: ^36.0.1
version: 36.0.1
ag-grid-enterprise:
specifier: ^36.0.1
version: 36.0.1
ag-grid-react:
specifier: ^36.0.1
version: 36.0.1(react-dom@19.2.3)(react@19.2.3)
dayjs: dayjs:
specifier: ^1.11.19 specifier: ^1.11.19
version: 1.11.19 version: 1.11.19
@@ -585,7 +594,7 @@ importers:
version: 5.5.4 version: 5.5.4
vitest: vitest:
specifier: ^4.0.17 specifier: ^4.0.17
version: 4.0.17(jsdom@26.1.0) version: 4.0.17(@opentelemetry/api@1.9.1)
packages: packages:
@@ -4822,6 +4831,76 @@ packages:
hasBin: true hasBin: true
dev: false dev: false
/ag-charts-community@14.0.1:
resolution: {integrity: sha512-XHYdDRtEz4OYyZZuut9BiHSDy6KjXoVXNom2Zvq8EEO6HN67x73xLZNlo/9Vxwoch/3mNGkQkVTzi0zqdKFQ4w==}
requiresBuild: true
dependencies:
ag-charts-core: 14.0.1
ag-charts-locale: 14.0.1
ag-charts-types: 14.0.1
dev: false
optional: true
/ag-charts-core@14.0.1:
resolution: {integrity: sha512-8fjv8XnqokFTYXWTsJ6LDH1GdPFpZtDRDv5G4j3MbDk3uGjD2p65hM2z1f60DzL8C0Ii7gD6q4O26TxhIIAtBA==}
requiresBuild: true
dependencies:
ag-charts-types: 14.0.1
dev: false
optional: true
/ag-charts-enterprise@14.0.1:
resolution: {integrity: sha512-ZOivbXClgqrMh42OjMfId3xIIuKmuRbLPVMUYfGSt9MhGkEI1KIkMtgjSp8W64xKmdysTNOFM+Xf/8NXNE8OSQ==}
requiresBuild: true
dependencies:
ag-charts-community: 14.0.1
ag-charts-core: 14.0.1
dev: false
optional: true
/ag-charts-locale@14.0.1:
resolution: {integrity: sha512-GjeoU/0nRcEALK3K2VkVgeAkwtuH958XQlMawiN5XUt95Hj/IC1drwF7JJMkcV8U8GFHzNsXhsY1gFJfLY2L4g==}
requiresBuild: true
dev: false
optional: true
/ag-charts-types@14.0.1:
resolution: {integrity: sha512-fGNDptlNzaQDqDoZxAYeLtBrV8sIXE1iRXX9s5W+/drobP3Ig2fhdAOlKp3IIrHlbiKZUiuhraqT0D4IYVyM4w==}
dev: false
/ag-grid-community@36.0.1:
resolution: {integrity: sha512-wQetUqoY6SBCtKzDjsYkImiGpM4+hU7S5/NvxcCAO6liL6mSRXlEvCHdQZUfj6amuhsdjVlGK1C8e+B54EyDTQ==}
dependencies:
ag-charts-types: 14.0.1
ag-stack: 36.0.1
dev: false
/ag-grid-enterprise@36.0.1:
resolution: {integrity: sha512-sGxqekLggZWvjpCSl9b2T8qDpqrd/alFQRVGZhmkayZTftlpRPCkgWKCv374Msd46qXGJUkQcGwMhLrO0hqO3Q==}
dependencies:
ag-grid-community: 36.0.1
ag-stack: 36.0.1
optionalDependencies:
ag-charts-community: 14.0.1
ag-charts-enterprise: 14.0.1
dev: false
/ag-grid-react@36.0.1(react-dom@19.2.3)(react@19.2.3):
resolution: {integrity: sha512-cqyZWHks9LF7MBZvX6QP8IGlYBScssdQ3B6EMli0nO2TClbBiRTZuP1ja3AwVL0THnl+WksO2kBB2ATWp8vVAQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
dependencies:
ag-grid-community: 36.0.1
prop-types: 15.8.1
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
dev: false
/ag-stack@36.0.1:
resolution: {integrity: sha512-FsrO55fl7EDToQVgRDaTF1+QKWpfJK1nxTxTavkkfHeq6Kei4skAeP0MsjXm7zECjfyHczlwmWvp+KN7KHnlYQ==}
dev: false
/agent-base@6.0.2: /agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'} engines: {node: '>= 6.0.0'}