/* Minimal styles for the natural language grid state example */
.example-wrapper {
    display: flex;
    flex-direction: column;
    height: 100%;
}
.input-group {
    display: flex;
    margin-bottom: 15px;
    align-items: center;
}

.examples {
    background: #e7f3ff;
    padding: 15px;
    border-radius: 4px;
    margin: 15px 0;
    border-left: 4px solid #007bff;
}

.examples ul {
    margin: 10px 0 0 20px;
}

.examples li {
    margin: 5px 0;
}

#processingStatus {
    margin-top: 15px;
}

#aiResponse,
#currentState {
    margin-top: 15px;
    padding: 15px;
    background: #f8f9fa;
    border-radius: 4px;
    border: 1px solid #dee2e6;
}

#currentState {
    max-height: 300px;
    overflow-y: auto;
}

#aiResponse pre,
#currentState pre {
    background: #f8f9fa;
    padding: 10px;
    border-radius: 4px;
    overflow-x: auto;
    font-size: 12px;
    border: 1px solid #e9ecef;
}

#aiResponse h4,
#currentState h4 {
    margin: 0 0 10px 0;
    color: #495057;
}

@media (max-width: 768px) {
    .input-group {
        flex-direction: column;
    }

    .input-group input {
        margin-bottom: 10px;
        margin-right: 0 !important;
    }
}
import type { GridApi } from 'ag-grid-community';

import { generateChatGPTSchema } from './chatgptSchema';
import type { ChatGPTGridStateResponse } from './gridStateSchema';

// OpenAI API configuration
const OPENAI_API_URL = 'https://a2zblo9oti.execute-api.us-west-1.amazonaws.com';
const MODEL = 'gpt-4.1-mini';

/**
 * Calls ChatGPT API to process natural language requests for grid state changes
 * Returns a Promise that resolves to the ChatGPT response
 */
export function callChatGPT(
    userRequest: string,
    currentState: any,
    gridApi: GridApi
): Promise<ChatGPTGridStateResponse> {
    return new Promise((resolve, reject) => {
        const columnDefs = gridApi.getColumnDefs();
        if (!columnDefs) {
            reject(new Error('Column definitions not available'));
            return;
        }

        const schema = generateChatGPTSchema(columnDefs);

        const systemPrompt = `You are an AG-Grid state management assistant. You help users modify grid configuration using natural language commands.

The schema defines which columns can be used in different contexts based on their configuration:
- Only sortable columns can be used in sort operations
- Only groupable columns can be used for row grouping
- Only pivotable columns can be used for pivoting
- Only aggregatable columns can be used for aggregation
- Only resizable columns can have their width/flex changed
- Only pinnable columns can be pinned

Current grid state: ${JSON.stringify(currentState)}

Respond with only the necessary state changes, not the complete state. Provide a clear explanation of what you changed.

Any unchanged properties that are present in the current state must be included in \`propertiesToIgnore\`. Otherwise they will be removed from the state.

Important: Only modify the properties that the user specifically requested. If they ask to "hide the age column", only include columnVisibility in your response, not other unrelated properties.`;

        const requestBody = {
            model: MODEL,
            input: [
                {
                    role: 'system',
                    content: systemPrompt,
                },
                {
                    role: 'user',
                    content: userRequest,
                },
            ],
            max_output_tokens: 2048,
            text: {
                format: {
                    type: 'json_schema',
                    name: 'grid_state_response',
                    strict: true,
                    schema,
                },
            },
        };

        fetch(OPENAI_API_URL, {
            method: 'POST',
            body: JSON.stringify(requestBody),
        })
            .then((response) => {
                if (!response.ok) {
                    return response.json().then((error) => {
                        throw new Error(`OpenAI API error: ${error.error?.message || 'Unknown error'}`);
                    });
                }
                return response.json();
            })
            .then((data) => {
                console.log(data);
                if (!data.output[0]?.content[0]) {
                    throw new Error('Unknown Error');
                }

                const content = data.output[0].content[0];

                if (!content) {
                    throw new Error('No response content received');
                }

                try {
                    const parsedResponse = JSON.parse(content.text);
                    resolve(parsedResponse);
                } catch (e) {
                    throw new Error('Invalid JSON response from OpenAI');
                }
            })
            .catch((error) => {
                reject(error);
            });
    });
}
import type { ColDef, ColGroupDef } from 'ag-grid-community';

import { type JSONSchema, createEnumSchema, createObjectSchema } from './schema';

/**
 * Column analysis result for schema generation
 */
interface ColumnAnalysis {
    allColumnIds: string[];
    sortableColumnIds: string[];
    filterableColumnIds: string[];
    groupableColumnIds: string[];
    pivotableColumnIds: string[];
    aggregatableColumnIds: string[];
    resizableColumnIds: string[];
    pinnableColumnIds: string[];
}

/**
 * Analyzes column definitions to determine which columns can be used in different contexts
 */
function analyzeColumns(columnDefs: (ColDef | ColGroupDef)[]): ColumnAnalysis {
    const analysis: ColumnAnalysis = {
        allColumnIds: [],
        sortableColumnIds: [],
        filterableColumnIds: [],
        groupableColumnIds: [],
        pivotableColumnIds: [],
        aggregatableColumnIds: [],
        resizableColumnIds: [],
        pinnableColumnIds: [],
    };

    function processColumn(colDef: ColDef | ColGroupDef) {
        if ('children' in colDef && colDef.children) {
            // Process column group children
            colDef.children.forEach(processColumn);
        } else {
            const col = colDef as ColDef;
            const colId = col.field || col.colId;
            if (!colId) return;

            analysis.allColumnIds.push(colId);

            // Check if sortable (default true unless explicitly false)
            if (col.sortable !== false) {
                analysis.sortableColumnIds.push(colId);
            }

            // Check if filterable (default true unless explicitly false)
            if (col.filter !== false && col.filter !== null) {
                analysis.filterableColumnIds.push(colId);
            }

            // Check if can be used for row grouping
            if (col.enableRowGroup !== false && col.rowGroup !== false) {
                analysis.groupableColumnIds.push(colId);
            }

            // Check if can be used for pivoting
            if (col.enablePivot !== false && col.pivot !== false) {
                analysis.pivotableColumnIds.push(colId);
            }

            // Check if can be aggregated (typically numeric columns)
            if (col.enableValue !== false && (col.aggFunc || col.type === 'number')) {
                analysis.aggregatableColumnIds.push(colId);
            }

            // Check if resizable (default true unless explicitly false)
            if (col.resizable !== false) {
                analysis.resizableColumnIds.push(colId);
            }

            // Check if pinnable (usually all columns can be pinned)
            analysis.pinnableColumnIds.push(colId);
        }
    }

    columnDefs.forEach(processColumn);
    return analysis;
}

/**
 * Generates a dynamic ChatGPT schema based on column definitions
 */
export function generateChatGPTSchema(columnDefs: (ColDef | ColGroupDef)[]): JSONSchema {
    const analysis = analyzeColumns(columnDefs);

    return createObjectSchema({
        description: 'Response for modifying AG-Grid state using natural language commands',
        $defs: {
            allColumnId: createEnumSchema({
                enum: analysis.allColumnIds,
                description: 'Valid column ID from the grid',
            }),
            sortableColumnId: createEnumSchema({
                enum: analysis.sortableColumnIds,
                description: 'Column ID that supports sorting',
            }),
            filterableColumnId: createEnumSchema({
                enum: analysis.filterableColumnIds,
                description: 'Column ID that supports filtering',
            }),
            groupableColumnId: createEnumSchema({
                enum: analysis.groupableColumnIds,
                description: 'Column ID that supports row grouping',
            }),
            pivotableColumnId: createEnumSchema({
                enum: analysis.pivotableColumnIds,
                description: 'Column ID that supports pivoting',
            }),
            aggregatableColumnId: createEnumSchema({
                enum: analysis.aggregatableColumnIds,
                description: 'Column ID that supports aggregation',
            }),
            resizableColumnId: createEnumSchema({
                enum: analysis.resizableColumnIds,
                description: 'Column ID that supports resizing',
            }),
            pinnableColumnId: createEnumSchema({
                enum: analysis.pinnableColumnIds,
                description: 'Column ID that can be pinned',
            }),
            sortDirection: createEnumSchema({
                enum: ['asc', 'desc'],
                description: 'Sort direction: ascending or descending',
            }),
            aggregationFunction: createEnumSchema({
                enum: ['sum', 'avg', 'min', 'max', 'count', 'first', 'last'],
                description: 'Aggregation function to apply to numeric columns',
            }),
            sideBarPosition: createEnumSchema({ enum: ['left', 'right'], description: 'Position of the sidebar' }),
            toolPanelId: createEnumSchema({ enum: ['columns', 'filters'], description: 'Tool panel identifier' }),
            gridStateProperty: createEnumSchema({
                enum: [
                    'aggregation',
                    'columnGroup',
                    'columnOrder',
                    'columnPinning',
                    'columnSizing',
                    'columnVisibility',
                    'filter',
                    'focusedCell',
                    'pagination',
                    'rowPinning',
                    'pivot',
                    'cellSelection',
                    'rowGroup',
                    'rowGroupExpansion',
                    'rowSelection',
                    'scroll',
                    'sideBar',
                    'sort',
                ],
                description: 'Grid state property that can be ignored when setting state',
            }),
            filterModel: createObjectSchema({
                description: 'Column filter configurations where each key is a column ID',
                properties: analysis.filterableColumnIds.reduce(
                    (prev, current) => ({ ...prev, [current]: { $ref: '#/$defs/columnFilter' } }),
                    {}
                ),
            }),
            columnFilter: {
                anyOf: [
                    { $ref: '#/$defs/textFilter' },
                    { $ref: '#/$defs/numberFilter' },
                    { $ref: '#/$defs/dateFilter' },
                    { $ref: '#/$defs/setFilter' },
                    { $ref: '#/$defs/multiFilter' },
                ],
            },
            textFilter: createObjectSchema({
                properties: {
                    filterType: { type: 'string', enum: ['text'] },
                    type: {
                        type: 'string',
                        enum: [
                            'equals',
                            'notEqual',
                            'contains',
                            'notContains',
                            'startsWith',
                            'endsWith',
                            'blank',
                            'notBlank',
                        ],
                    },
                    filter: { type: 'string' },
                },
            }),
            numberFilter: createObjectSchema({
                properties: {
                    filterType: { type: 'string', enum: ['number'] },
                    type: {
                        type: 'string',
                        enum: [
                            'equals',
                            'notEqual',
                            'lessThan',
                            'lessThanOrEqual',
                            'greaterThan',
                            'greaterThanOrEqual',
                            'inRange',
                            'blank',
                            'notBlank',
                        ],
                    },
                    filter: { type: 'number' },
                    filterTo: { type: 'number' },
                },
            }),
            dateFilter: createObjectSchema({
                properties: {
                    filterType: { type: 'string', enum: ['date'] },
                    type: {
                        type: 'string',
                        enum: ['equals', 'notEqual', 'lessThan', 'greaterThan', 'inRange', 'blank', 'notBlank'],
                    },
                    dateFrom: { type: 'string' },
                    dateTo: { type: 'string' },
                },
            }),
            setFilter: createObjectSchema({
                properties: {
                    filterType: { type: 'string', enum: ['set'] },
                    values: {
                        type: 'array',
                        items: { type: 'string' },
                    },
                },
            }),
            multiFilter: createObjectSchema({
                properties: {
                    filterType: { type: 'string', enum: ['multi'] },
                    operator: { type: 'string', enum: ['AND', 'OR'] },
                    conditions: {
                        type: 'array',
                        items: { $ref: '#/$defs/columnFilter' },
                    },
                },
            }),
            advancedFilterModel: {
                anyOf: [{ $ref: '#/$defs/advancedFilterCondition' }, { $ref: '#/$defs/advancedFilterJoin' }],
            },
            advancedFilterCondition: createObjectSchema({
                properties: {
                    filterType: { type: 'string' },
                    colId: { $ref: '#/$defs/filterableColumnId' },
                    type: { type: 'string' },
                    filter: { anyOf: [{ type: 'string' }, { type: 'number' }] },
                    filterTo: { anyOf: [{ type: 'string' }, { type: 'number' }] },
                },
            }),
            advancedFilterJoin: createObjectSchema({
                properties: {
                    filterType: { type: 'string', enum: ['join'] },
                    type: { type: 'string', enum: ['AND', 'OR'] },
                    conditions: {
                        type: 'array',
                        items: { $ref: '#/$defs/advancedFilterModel' },
                    },
                },
            }),
            rowPosition: createObjectSchema({
                properties: {
                    rowIndex: { type: 'number', minimum: 0 },
                    rowPinned: { anyOf: [{ type: 'string', enum: ['top', 'bottom'] }, { type: 'null' }] },
                },
            }),
            toolPanelConfig: createObjectSchema({
                properties: {
                    id: { type: 'string' },
                    labelDefault: { type: 'string' },
                    labelKey: { type: 'string' },
                    iconKey: { type: 'string' },
                    toolPanel: { type: 'string' },
                },
            }),
            serverSideRowSelection: createObjectSchema({
                properties: {
                    selectAll: { type: 'boolean' },
                    toggledNodes: {
                        type: 'array',
                        items: { type: 'string' },
                    },
                },
            }),
        },
        properties: {
            gridState: createObjectSchema({
                description: 'The grid state changes to apply. Only include properties that need to be modified.',
                properties: {
                    version: {
                        type: 'string',
                        description: 'Grid state version',
                    },
                    columnOrder: {
                        type: 'object',
                        description: 'Change the order of columns in the grid',
                        properties: {
                            orderedColIds: {
                                type: 'array',
                                description: 'Array of column IDs in the desired order',
                                items: { $ref: '#/$defs/allColumnId' },
                            },
                        },
                        required: ['orderedColIds'],
                        additionalProperties: false,
                    },
                    columnPinning: {
                        type: 'object',
                        description: 'Pin or unpin columns to the left or right side of the grid',
                        properties: {
                            leftColIds: {
                                type: 'array',
                                description: 'Column IDs to pin to the left side',
                                items: { $ref: '#/$defs/pinnableColumnId' },
                            },
                            rightColIds: {
                                type: 'array',
                                description: 'Column IDs to pin to the right side',
                                items: { $ref: '#/$defs/pinnableColumnId' },
                            },
                        },
                        required: ['leftColIds', 'rightColIds'],
                        additionalProperties: false,
                    },
                    columnSizing: {
                        type: 'object',
                        description: 'Resize columns by setting width or flex values',
                        properties: {
                            columnSizingModel: {
                                type: 'array',
                                description: 'Array of column sizing configurations',
                                items: {
                                    anyOf: [
                                        {
                                            type: 'object',
                                            properties: {
                                                colId: {
                                                    $ref: '#/$defs/resizableColumnId',
                                                },
                                                width: {
                                                    type: 'number',
                                                    description: 'Fixed width in pixels',
                                                    minimum: 20,
                                                },
                                            },
                                            required: ['colId', 'width'],
                                            additionalProperties: false,
                                        },
                                        {
                                            type: 'object',
                                            properties: {
                                                colId: {
                                                    $ref: '#/$defs/resizableColumnId',
                                                },
                                                flex: {
                                                    type: 'number',
                                                    description: 'Flexible sizing ratio',
                                                    minimum: 0,
                                                },
                                            },
                                            required: ['colId', 'flex'],
                                            additionalProperties: false,
                                        },
                                    ],
                                },
                            },
                        },
                        required: ['columnSizingModel'],
                        additionalProperties: false,
                    },
                    columnVisibility: {
                        type: 'object',
                        description: 'Show or hide columns in the grid',
                        properties: {
                            hiddenColIds: {
                                type: 'array',
                                description: 'Array of column IDs to hide',
                                items: { $ref: '#/$defs/allColumnId' },
                            },
                        },
                        required: ['hiddenColIds'],
                        additionalProperties: false,
                    },
                    filter: createObjectSchema({
                        description: 'Apply filters to the grid data',
                        properties: {
                            filterModel: {
                                $ref: '#/$defs/filterModel',
                            },
                            columnFilterState: createObjectSchema({
                                description: 'Column filter state information (rarely used)',
                                properties: {},
                            }),
                            advancedFilterModel: {
                                $ref: '#/$defs/advancedFilterModel',
                            },
                        },
                    }),
                    sort: {
                        type: 'object',
                        description: 'Sort the grid data by one or more columns',
                        properties: {
                            sortModel: {
                                type: 'array',
                                description: 'Array of sort configurations',
                                items: {
                                    type: 'object',
                                    properties: {
                                        colId: {
                                            $ref: '#/$defs/sortableColumnId',
                                        },
                                        sort: {
                                            $ref: '#/$defs/sortDirection',
                                        },
                                    },
                                    required: ['colId', 'sort'],
                                    additionalProperties: false,
                                },
                            },
                        },
                        required: ['sortModel'],
                        additionalProperties: false,
                    },
                    rowGroup: {
                        type: 'object',
                        description: 'Group rows by one or more columns',
                        properties: {
                            groupColIds: {
                                type: 'array',
                                description: 'Array of column IDs to group by',
                                items: { $ref: '#/$defs/groupableColumnId' },
                            },
                        },
                        required: ['groupColIds'],
                        additionalProperties: false,
                    },
                    pivot: {
                        type: 'object',
                        description: 'Enable pivot mode and set pivot columns',
                        properties: {
                            pivotMode: {
                                type: 'boolean',
                                description: 'Whether pivot mode is enabled',
                            },
                            pivotColIds: {
                                type: 'array',
                                description: 'Array of column IDs to use as pivot columns',
                                items: { $ref: '#/$defs/pivotableColumnId' },
                            },
                        },
                        required: ['pivotMode', 'pivotColIds'],
                        additionalProperties: false,
                    },
                    aggregation: {
                        type: 'object',
                        description: 'Apply aggregation functions to columns',
                        properties: {
                            aggregationModel: {
                                type: 'array',
                                description: 'Array of aggregation configurations',
                                items: {
                                    type: 'object',
                                    properties: {
                                        colId: {
                                            $ref: '#/$defs/aggregatableColumnId',
                                        },
                                        aggFunc: {
                                            $ref: '#/$defs/aggregationFunction',
                                        },
                                    },
                                    required: ['colId', 'aggFunc'],
                                    additionalProperties: false,
                                },
                            },
                        },
                        required: ['aggregationModel'],
                        additionalProperties: false,
                    },
                    rowSelection: {
                        anyOf: [
                            {
                                type: 'array',
                                description: 'Array of row IDs to select',
                                items: { type: 'string' },
                            },
                            {
                                $ref: '#/$defs/serverSideRowSelection',
                            },
                        ],
                    },
                    pagination: {
                        type: 'object',
                        description: 'Control pagination settings',
                        properties: {
                            page: {
                                type: 'number',
                                description: 'Current page number (0-based)',
                                minimum: 0,
                            },
                            pageSize: {
                                type: 'number',
                                description: 'Number of rows per page',
                                minimum: 1,
                            },
                        },
                        required: ['page', 'pageSize'],
                        additionalProperties: false,
                    },
                    sideBar: {
                        type: 'object',
                        description: 'Control sidebar visibility and tool panels',
                        properties: {
                            visible: {
                                type: 'boolean',
                                description: 'Whether the sidebar is visible',
                            },
                            position: {
                                $ref: '#/$defs/sideBarPosition',
                            },
                            openToolPanel: {
                                anyOf: [{ type: 'string' }, { type: 'null' }],
                            },
                            toolPanels: createObjectSchema({
                                description: 'Tool panel configurations',
                                properties: {},
                            }),
                        },
                        required: ['visible', 'position', 'openToolPanel', 'toolPanels'],
                        additionalProperties: false,
                    },
                    rowGroupExpansion: {
                        type: 'object',
                        description: 'Control which row groups are expanded',
                        properties: {
                            expandedRowGroupIds: {
                                type: 'array',
                                description: 'Array of row group IDs that should be expanded',
                                items: { type: 'string' },
                            },
                        },
                        required: ['expandedRowGroupIds'],
                        additionalProperties: false,
                    },
                    rowPinning: {
                        type: 'object',
                        description: 'Pin specific rows to top or bottom of the grid',
                        properties: {
                            top: {
                                type: 'array',
                                description: 'Array of row IDs to pin to the top',
                                items: { type: 'string' },
                            },
                            bottom: {
                                type: 'array',
                                description: 'Array of row IDs to pin to the bottom',
                                items: { type: 'string' },
                            },
                        },
                        required: ['top', 'bottom'],
                        additionalProperties: false,
                    },
                    cellSelection: {
                        type: 'object',
                        description: 'Select specific cell ranges',
                        properties: {
                            cellRanges: {
                                type: 'array',
                                description: 'Array of cell range selections',
                                items: {
                                    type: 'object',
                                    properties: {
                                        id: {
                                            type: 'string',
                                            description: 'Unique identifier for the cell range',
                                        },
                                        type: {
                                            type: 'string',
                                            description: 'Type of cell range',
                                        },
                                        startRow: {
                                            $ref: '#/$defs/rowPosition',
                                        },
                                        endRow: {
                                            $ref: '#/$defs/rowPosition',
                                        },
                                        colIds: {
                                            type: 'array',
                                            description: 'Array of column IDs in the range',
                                            items: { $ref: '#/$defs/allColumnId' },
                                        },
                                        startColId: {
                                            $ref: '#/$defs/allColumnId',
                                        },
                                    },
                                    required: ['id', 'type', 'startRow', 'endRow', 'colIds', 'startColId'],
                                    additionalProperties: false,
                                },
                            },
                        },
                        required: ['cellRanges'],
                        additionalProperties: false,
                    },
                    focusedCell: {
                        type: 'object',
                        description: 'Set the currently focused cell',
                        properties: {
                            rowIndex: {
                                type: 'number',
                                description: 'Row index of the focused cell',
                                minimum: 0,
                            },
                            rowPinned: {
                                anyOf: [{ type: 'string' }, { type: 'null' }],
                            },
                            colId: {
                                $ref: '#/$defs/allColumnId',
                            },
                        },
                        required: ['rowIndex', 'rowPinned', 'colId'],
                        additionalProperties: false,
                    },
                    scroll: {
                        type: 'object',
                        description: 'Set the scroll position of the grid',
                        properties: {
                            top: {
                                type: 'number',
                                description: 'Vertical scroll position in pixels',
                                minimum: 0,
                            },
                            left: {
                                type: 'number',
                                description: 'Horizontal scroll position in pixels',
                                minimum: 0,
                            },
                        },
                        required: ['top', 'left'],
                        additionalProperties: false,
                    },
                    columnGroup: {
                        type: 'object',
                        description: 'Control which column groups are open',
                        properties: {
                            openColumnGroupIds: {
                                type: 'array',
                                description: 'Array of column group IDs that should be open',
                                items: { type: 'string' },
                            },
                        },
                        required: ['openColumnGroupIds'],
                        additionalProperties: false,
                    },
                },
            }),
            propertiesToIgnore: {
                type: 'array',
                description: 'Grid state properties to ignore when applying the state (optional)',
                items: { $ref: '#/$defs/gridStateProperty' },
            },
            explanation: {
                type: 'string',
                description: 'Human-readable explanation of what changes were made to the grid state',
            },
        },
    });
}
import type { GridState, GridStateKey } from 'ag-grid-community';

/**
 * Response format for ChatGPT when modifying AG-Grid state
 * Uses the official AG-Grid GridState interface
 */
export interface ChatGPTGridStateResponse {
    /**
     * The grid state object that will be passed to gridApi.setState()
     * Uses the official AG-Grid GridState interface
     */
    gridState: GridState;
    
    /**
     * Properties to ignore when setting state (optional)
     */
    propertiesToIgnore?: GridStateKey[];
    
    /**
     * Human-readable explanation of what changes were made
     */
    explanation: string;
}

export type JSONSchemaType = 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null' | 'anyOf';

export interface SchemaProperty {
    type: JSONSchemaType | JSONSchemaType[];
    description?: string;
    $defs?: Record<string, JSONSchema>;
}

export interface ReferencedProperty {
    $ref: string;
    description?: never;
}

export interface AnyOfSchema {
    anyOf: JSONSchema[];
}

export type StringFormat = 'date-time' | 'date' | 'time' | 'duration' | 'email' | 'hostname' | 'ipv4' | 'ipv6' | 'uuid';

export interface StringSchema extends SchemaProperty {
    type: 'string';
    pattern?: string;
    format?: StringFormat;
}

export const createStringSchema = (schema: Omit<StringSchema, 'type'>): StringSchema => ({
    type: 'string',
    ...schema,
});

export interface EnumSchema extends SchemaProperty {
    type: 'string';
    enum: (string | number | boolean)[];
}

export const createEnumSchema = (schema: Omit<EnumSchema, 'type'>): EnumSchema => ({
    type: 'string',
    ...schema,
});

export interface NumberSchema extends SchemaProperty {
    type: 'number' | 'integer';
    minimum?: number;
    maximum?: number;
    exclusiveMinimum?: number;
    exclusiveMaximum?: number;
    multipleOf?: number;
}

export const createNumberSchema = (schema: Omit<NumberSchema, 'type'>): NumberSchema => ({
    type: 'number',
    ...schema,
});

export interface BooleanSchema extends SchemaProperty {
    type: 'boolean';
}

export const createBooleanSchema = (schema: Omit<BooleanSchema, 'type'>): BooleanSchema => ({
    type: 'boolean',
    ...schema,
});

export interface ArraySchema extends SchemaProperty {
    type: 'array';
    items: JSONSchema;
    minItems?: number;
    maxItems?: number;
}

export const createArraySchema = (schema: Omit<ArraySchema, 'type'>): ArraySchema => ({
    type: 'array',
    ...schema,
});

export interface ObjectSchema extends SchemaProperty {
    type: 'object';
    properties: Record<string, JSONSchema>;
    required: string[];
    additionalProperties: false;
    minProperties?: number;
    maxProperties?: number;
}

export const createObjectSchema = (
    schema: Omit<ObjectSchema, 'type' | 'additionalProperties' | 'required'>
): ObjectSchema => ({
    type: 'object',
    required: Object.keys(schema.properties),
    additionalProperties: false,
    ...schema,
});

export interface NullSchema extends SchemaProperty {
    type: 'null';
}

export const createNullSchema = (schema: Omit<NullSchema, 'type'>): NullSchema => ({
    type: 'null',
    ...schema,
});

export type JSONSchema =
    | StringSchema
    | EnumSchema
    | NumberSchema
    | BooleanSchema
    | ObjectSchema
    | ArraySchema
    | NullSchema
    | ReferencedProperty
    | AnyOfSchema;

export interface ChatGPTJSONSchema {
    name: string;
    description?: string;
    strict: true;
    schema: JSONSchema;
}
'use client';

import React, { useCallback, useMemo, useRef, useState, StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { AgGridReact } from 'ag-grid-react';
import './styles.css';
import { AllCommunityModule, ColDef, ColGroupDef, GridApi, GridOptions, ModuleRegistry, SideBarDef } from 'ag-grid-community';
import { AllEnterpriseModule } from 'ag-grid-enterprise';
import { callChatGPT } from './chatgptApi';
ModuleRegistry.registerModules([AllCommunityModule, AllEnterpriseModule]);
import { useFetchJson } from './useFetchJson';



interface IOlympicData {
    athlete: string;
    age: number;
    country: string;
    year: number;
    sport: string;
    gold: number;
    silver: number;
    bronze: number;
    total: number;
}





const GridExample = () => {
    const gridRef = useRef<AgGridReact<IOlympicData>>(null);
    const containerStyle = useMemo(() => ({ width: '100%', height: '100%' }), []);
    const gridStyle = useMemo(() => ({height: '100%', width: '100%'}), []);
    
    const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    {
        field: 'athlete',
        headerName: 'Athlete',
        minWidth: 200,
        enableRowGroup: true,
        enablePivot: false,
    },
    {
        field: 'age',
        headerName: 'Age',
        width: 90,
        type: 'number',
        enableValue: true,
        enableRowGroup: false,
    },
    {
        field: 'country',
        headerName: 'Country',
        minWidth: 150,
        enableRowGroup: true,
        enablePivot: true,
    },
    {
        field: 'year',
        headerName: 'Year',
        width: 90,
        type: 'number',
        enableRowGroup: true,
        enableValue: false,
    },
    {
        field: 'sport',
        headerName: 'Sport',
        minWidth: 150,
        enableRowGroup: true,
        enablePivot: true,
    },
    {
        field: 'gold',
        headerName: 'Gold',
        width: 100,
        type: 'number',
        enableValue: true,
        aggFunc: 'sum',
    },
    {
        field: 'silver',
        headerName: 'Silver',
        width: 100,
        type: 'number',
        enableValue: true,
        aggFunc: 'sum',
    },
    {
        field: 'bronze',
        headerName: 'Bronze',
        width: 100,
        type: 'number',
        enableValue: true,
        aggFunc: 'sum',
    },
    {
        field: 'total',
        headerName: 'Total',
        width: 100,
        type: 'number',
        enableValue: true,
        aggFunc: 'sum',
    },
]);
    const defaultColDef = useMemo<ColDef>(() => { return {
    flex: 1,
    minWidth: 100,
    filter: true,
    sortable: true,
    resizable: true,
} }, []);
    const sideBar = useMemo<SideBarDef | string | string[] | boolean | null>(() => { return {
    toolPanels: [
        {
            id: 'columns',
            labelDefault: 'Columns',
            labelKey: 'columns',
            iconKey: 'columns',
            toolPanel: 'agColumnsToolPanel',
        },
        {
            id: 'filters',
            labelDefault: 'Filters',
            labelKey: 'filters',
            iconKey: 'filter',
            toolPanel: 'agFiltersToolPanel',
        },
    ],
    defaultToolPanel: 'columns',
} }, []);
    const paginationPageSizeSelector = useMemo<number[] | boolean>(() => { return [10, 20, 50, 100] }, []);

    const { data, loading } = useFetchJson<IOlympicData>(
                'https://www.ag-grid.com/example-assets/olympic-winners.json'
            );

const processNaturalLanguageRequest = useCallback(()   =>{
    const inputElement = document.getElementById('naturalLanguageInput') as HTMLInputElement;
    const outputElement = document.getElementById('aiResponse') as HTMLDivElement;
    const statusElement = document.getElementById('processingStatus') as HTMLDivElement;
    const userRequest = inputElement.value.trim();
    if (!userRequest) {
        outputElement.innerHTML = '<p style="color: red;">Please enter a request</p>';
        return;
    }
    statusElement.innerHTML = '<p>Processing request with ChatGPT...</p>';
    outputElement.innerHTML = '';
    const currentState = gridRef.current!.api.getState();
    callChatGPT(userRequest, currentState, gridRef.current!.api)
        .then(function (response) {
        // Apply the state changes
        if (Object.keys(response.gridState).length > 0) {
            gridRef.current!.api.setState(response.gridState, response.propertiesToIgnore);
        }
        // Display the response
        statusElement.innerHTML = '<p style="color: green;">✓ Request processed successfully!</p>';
        outputElement.innerHTML = `
                <h4>AI Response:</h4>
                <p>${response.explanation}</p>
            `;
        outputElement.style.display = 'block';
        // Clear the input
        inputElement.value = '';
    })
        .catch(function (error) {
        statusElement.innerHTML = '<p style="color: red;">✗ Error processing request</p>';
        outputElement.innerHTML = `<p style="color: red;">Error: ${error instanceof Error ? error.message : String(error)}</p>`;
        outputElement.style.display = 'block';
    });
}, [callChatGPT])

   const getCurrentState = useCallback(()   =>{
    const state = gridRef.current!.api.getState();
    const outputElement = document.getElementById('currentState') as HTMLDivElement;
    outputElement.innerHTML = `<h4>Current Grid State:</h4><pre>${JSON.stringify(state, null, 2)}</pre>`;
    outputElement.style.display = 'block';
}, [])

   const resetGrid = useCallback(()   =>{
    gridRef.current!.api.setState({
        columnVisibility: { hiddenColIds: [] },
        columnPinning: { leftColIds: [], rightColIds: [] },
        sort: { sortModel: [] },
        filter: { filterModel: {} },
        rowGroup: { groupColIds: [] },
        pagination: { page: 0, pageSize: 20 },
    });
    const aiResponse = document.getElementById('aiResponse')!;
    const processingStatus = document.getElementById('processingStatus')!;
    const currentState = document.getElementById('currentState')!;
    aiResponse.innerHTML = '';
    aiResponse.style.display = 'none';
    processingStatus.innerHTML = '';
    currentState.innerHTML = '';
    currentState.style.display = 'none';
}, [])

    return  (
            <div style={containerStyle}>
                <div className="example-wrapper">
    <div>
        <div className="input-group">
            <input type="text" id="naturalLanguageInput" placeholder="Enter your request in natural language (e.g., 'hide age column', 'sort by gold medals')" autocomplete="off" style={{"flex":"1","padding":"8px","border":"1px solid #ddd","borderRadius":"4px","marginRight":"10px"}} />
            <button id="processRequest" onClick={processNaturalLanguageRequest} style={{"padding":"8px 16px","background":"#007bff","color":"white","border":"none","borderRadius":"4px","cursor":"pointer"}}>
                Process Request
            </button>
        </div>
        
        <div style={{"background":"#fff3cd","border":"1px solid #ffeaa7","color":"#856404","padding":"15px","borderRadius":"4px","margin":"15px 0"}}>
            <strong>Setup Required:</strong> This example requires an OpenAI API key to be configured. Set the <code>OPENAI_API_KEY</code> environment variable or update the API key in the source code.
        </div>
        
        <div className="examples" style={{"background":"#e7f3ff","padding":"15px","borderRadius":"4px","margin":"15px 0","borderLeft":"4px solid #007bff"}}>
            <strong>Try these example commands:</strong>
            <ul style={{"margin":"10px 0 0 20px"}}>
                <li><code>hide the age column</code> - Hide the age column</li>
                <li><code>sort by gold medals descending</code> - Sort by gold medals</li>
                <li><code>group rows by country</code> - Group by country (only groupable columns)</li>
                <li><code>pin athlete column to the left</code> - Pin the athlete column</li>
                <li><code>aggregate gold medals using sum</code> - Apply aggregation (only numeric columns)</li>
                <li><code>create pivot table with sport as columns</code> - Enable pivot mode</li>
                <li><code>resize age column to 120 pixels</code> - Set column width</li>
            </ul>
        </div>
        
        <div className="button-group">
            <button onClick={getCurrentState}>Get Current State</button>
            <button onClick={resetGrid}>Reset Grid</button>
        </div>
        
        <div id="processingStatus" style={{"marginTop":"15px"}}></div>
        <div id="aiResponse" style={{"marginTop":"15px","padding":"15px","background":"#f8f9fa","borderRadius":"4px","display":"none"}}></div>
        <div id="currentState" style={{"marginTop":"15px","padding":"15px","background":"#f8f9fa","borderRadius":"4px","display":"none","maxHeight":"300px","overflowY":"auto"}}></div>
    </div>

    
        <div  style={gridStyle}>
            <AgGridReact<IOlympicData>
                ref={gridRef}
                
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableRangeSelection={true}
rowGroupPanelShow={'always'}
sideBar={sideBar}
pagination={true}
paginationPageSize={20}
paginationPageSizeSelector={paginationPageSizeSelector}
            />
        </div>
</div>
            </div>
        );

}

const root = createRoot(document.getElementById('root')!);
root.render(<StrictMode><GridExample /></StrictMode>);

export interface IOlympicData {
    athlete: string,
    age: number,
    country: string,
    year: number,
    date: string,
    sport: string,
    gold: number,
    silver: number,
    bronze: number,
    total: number
}
import { useState, useEffect } from 'react';

/**
 * Fetch example Json data
 * Not recommended for production use!
 */
export const useFetchJson = <T,>(url:string, limit?: number) => {
    const [data, setData] = useState<T[]>();
    const [loading, setLoading] = useState(false);
    useEffect(() => {
        const fetchData = async () => {
            setLoading(true);

            // Note error handling is omitted here for brevity
            const response = await fetch(url);
            const json = await response.json();
            const data = limit ? json.slice(0, limit) : json;
            setData(data);
            setLoading(false);
        };
        fetchData();
    }, [url, limit]);
    return { data, loading };
};
if (typeof window !== 'undefined') {
    var waitSeconds = 100;

    var head = document.getElementsByTagName('head')[0];

    var isWebkit = !!window.navigator.userAgent.match(/AppleWebKit\/([^ ;]*)/);
    var webkitLoadCheck = function (link, callback) {
        setTimeout(function () {
            for (var i = 0; i < document.styleSheets.length; i++) {
                var sheet = document.styleSheets[i];
                if (sheet.href == link.href) return callback();
            }
            webkitLoadCheck(link, callback);
        }, 10);
    };

    var cssIsReloadable = function cssIsReloadable(links) {
        // Css loaded on the page initially should be skipped by the first
        // systemjs load, and marked for reload
        var reloadable = true;
        forEach(links, function (link) {
            if (!link.hasAttribute('data-systemjs-css')) {
                reloadable = false;
                link.setAttribute('data-systemjs-css', '');
            }
        });
        return reloadable;
    };

    var findExistingCSS = function findExistingCSS(url) {
        // Search for existing link to reload
        var links = head.getElementsByTagName('link');
        return filter(links, function (link) {
            return link.href === url;
        });
    };

    var noop = function () {};

    var loadCSS = function (url, existingLinks) {
        const stylesUrl = url.includes('styles.css') || url.includes('style.css');
        return new Promise((outerResolve, outerReject) => {
            setTimeout(
                () => {
                    new Promise(function (resolve, reject) {
                        var timeout = setTimeout(function () {
                            reject('Unable to load CSS');
                        }, waitSeconds * 1000);
                        var _callback = function (error) {
                            clearTimeout(timeout);
                            link.onload = link.onerror = noop;
                            setTimeout(function () {
                                if (error) {
                                    reject(error);
                                    outerReject(error);
                                } else {
                                    resolve('');
                                    outerResolve('');
                                }
                            }, 7);
                        };
                        var link = document.createElement('link');
                        link.type = 'text/css';
                        link.rel = 'stylesheet';
                        link.href = url;
                        link.setAttribute('data-systemjs-css', '');
                        if (!isWebkit) {
                            link.onload = function () {
                                _callback();
                            };
                        } else {
                            webkitLoadCheck(link, _callback);
                        }
                        link.onerror = function (event) {
                            _callback(event.error || new Error('Error loading CSS file.'));
                        };
                        if (existingLinks.length) head.insertBefore(link, existingLinks[0]);
                        else head.appendChild(link);
                    })
                        // Remove the old link regardless of loading outcome
                        .then(
                            function (result) {
                                forEach(existingLinks, function (link) {
                                    link.parentElement.removeChild(link);
                                });
                                return result;
                            },
                            function (err) {
                                forEach(existingLinks, function (link) {
                                    link.parentElement.removeChild(link);
                                });
                                throw err;
                            }
                        );
                },
                stylesUrl ? 5 : 0
            );
        });
    };

    exports.fetch = function (load) {
        // dont reload styles loaded in the head
        var links = findExistingCSS(load.address);
        if (!cssIsReloadable(links)) return '';
        return loadCSS(load.address, links);
    };
} else {
    var builderPromise;
    function getBuilder(loader) {
        if (builderPromise) return builderPromise;

        return (builderPromise = System['import']('./css-plugin-base.js', module.id).then(function (CSSPluginBase) {
            return new CSSPluginBase(function compile(source, address) {
                return {
                    css: source,
                    map: null,
                    moduleSource: null,
                    moduleFormat: null,
                };
            });
        }));
    }

    exports.cssPlugin = true;
    exports.fetch = function (load, fetch) {
        if (!this.builder) return '';
        return fetch(load);
    };
    exports.translate = function (load, opts) {
        if (!this.builder) return '';
        var loader = this;
        return getBuilder(loader).then(function (builder) {
            return builder.translate.call(loader, load, opts);
        });
    };
    exports.instantiate = function (load, opts) {
        if (!this.builder) return;
        var loader = this;
        return getBuilder(loader).then(function (builder) {
            return builder.instantiate.call(loader, load, opts);
        });
    };
    exports.bundle = function (loads, compileOpts, outputOpts) {
        var loader = this;
        return getBuilder(loader).then(function (builder) {
            return builder.bundle.call(loader, loads, compileOpts, outputOpts);
        });
    };
    exports.listAssets = function (loads, opts) {
        var loader = this;
        return getBuilder(loader).then(function (builder) {
            return builder.listAssets.call(loader, loads, opts);
        });
    };
}

// Because IE8?
function filter(arrayLike, func) {
    var arr = [];
    forEach(arrayLike, function (item) {
        if (func(item)) arr.push(item);
    });
    return arr;
}

// Because IE8?
function forEach(arrayLike, func) {
    for (var i = 0; i < arrayLike.length; i++) {
        func(arrayLike[i]);
    }
}
(function (global) {
    process = { env: { NODE_ENV: 'development' } };

    // Valid versions (18/19)
    const config = { version: 19, isProd: false };

    const filePart = config.isProd ? 'production.min' : 'development';
    const reactConfig =
        config.version == 18
            ? {
                  map: {
                      react: 'npm:react@18.2.0',
                      'react-dom': 'npm:react-dom@18.2.0',
                      'react-dom/client': 'npm:react-dom@18.2.0',
                  },
                  packages: {
                      react: {
                          main: `./umd/react.${filePart}.js`,
                      },
                      'react-dom': {
                          main: `./umd/react-dom.${filePart}.js`,
                      },
                  },
              }
            : {
                  map: {
                      react: `npm:react@19.1.0/cjs/react.${filePart}.js`,
                      'react-dom': `npm:react-dom@19.1.0/cjs/react-dom.${filePart}.js`,
                      'react-dom/client': `npm:react-dom@19.1.0/cjs/react-dom-client.${filePart}.js`,
                      scheduler: `npm:scheduler@0.26.0/cjs/scheduler.${filePart}.js`,
                  },
                  packages: {
                      react: {
                          format: 'cjs',
                      },
                      'react-dom': {
                          format: 'cjs',
                      },
                      scheduler: {
                          format: 'cjs',
                      },
                  },
              };

    var sjsPaths = {};
    if (typeof systemJsPaths !== 'undefined') {
        sjsPaths = systemJsPaths;
    }
    System.config({
        transpiler: 'ts',
        typescriptOptions: {
            target: 'es2020',
            jsx: 'react',
        },
        paths: {
            // paths serve as alias
            'npm:': 'https://cdn.jsdelivr.net/npm/',
            ...sjsPaths,
        },
        map: {
            // css: boilerplatePath + "css.js",
            css: 'npm:systemjs-plugin-css@0.1.37/css.js',

            ...reactConfig.map,

            ts: 'npm:plugin-typescript@8.0.0/lib/plugin.js',
            typescript: 'npm:typescript@5.4.5/lib/typescript.min.js',

            app: appLocation,
            // systemJsMap comes from index.html
            ...systemJsMap,
        },

        packages: {
            css: {},
            ...reactConfig.packages,
            app: {
                main: './index.tsx',
                defaultExtension: 'tsx',
            },
            'ag-grid-community': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-grid-enterprise': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-grid-react': {
                main: './dist/package/index.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-types': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-core': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-community': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-enterprise': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            '@ag-grid-community/locale': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
        },
        meta: {
            typescript: {
                exports: 'ts',
            },
            '*.css': { loader: 'css' },
        },
    });

    window.addEventListener('error', (e) => {
        console.error('ERROR', e.message, e.filename);
    });

    System.import(startFile).catch(function (err) {
        document.body.innerHTML =
            '<div class="example-error" style="background:#fdb022;padding:1rem;">' + 'Example Error: ' + err + '</div>';
        console.error(err);
    });
})(this);
(function (global) {
    process = { env: { NODE_ENV: 'development' } };

    // Valid versions (18/19)
    const config = { version: 19, isProd: true };

    const filePart = config.isProd ? 'production.min' : 'development';
    const reactConfig =
        config.version == 18
            ? {
                  map: {
                      react: 'npm:react@18.2.0',
                      'react-dom': 'npm:react-dom@18.2.0',
                      'react-dom/client': 'npm:react-dom@18.2.0',
                  },
                  packages: {
                      react: {
                          main: `./umd/react.${filePart}.js`,
                      },
                      'react-dom': {
                          main: `./umd/react-dom.${filePart}.js`,
                      },
                  },
              }
            : {
                  map: {
                      react: `npm:react@19.1.0/cjs/react.${filePart}.js`,
                      'react-dom': `npm:react-dom@19.1.0/cjs/react-dom.${filePart}.js`,
                      'react-dom/client': `npm:react-dom@19.1.0/cjs/react-dom-client.${filePart}.js`,
                      scheduler: `npm:scheduler@0.26.0/cjs/scheduler.${filePart}.js`,
                  },
                  packages: {
                      react: {
                          format: 'cjs',
                      },
                      'react-dom': {
                          format: 'cjs',
                      },
                      scheduler: {
                          format: 'cjs',
                      },
                  },
              };

    System.config({
        transpiler: 'ts',
        typescriptOptions: {
            target: 'es2020',
            jsx: 'react',
        },
        paths: {
            // paths serve as alias
            'npm:': 'https://cdn.jsdelivr.net/npm/',
            ...systemJsPaths,
        },
        map: {
            css: (boilerplatePath.length === 0 ? `./` : `${boilerplatePath}/`) + 'css.js',

            ...reactConfig.map,

            ts: 'npm:plugin-typescript@8.0.0/lib/plugin.js',
            typescript: 'npm:typescript@5.4.5/lib/typescript.min.js',

            app: appLocation,
            // systemJsMap comes from index.html
            ...systemJsMap,
        },
        packages: {
            css: {},
            ...reactConfig.packages,
            app: {
                main: './index.tsx',
                defaultExtension: 'tsx',
            },
            'ag-grid-community': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-grid-enterprise': {
                main: './dist/package/main.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-grid-react': {
                main: './dist/package/index.cjs.js',
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-types': {
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-core': {
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-community': {
                defaultExtension: 'js',
                format: 'cjs',
            },
            'ag-charts-enterprise': {
                defaultExtension: 'js',
                format: 'cjs',
            },
            '@ag-grid-community/locale': {
                format: 'cjs',
            },
        },
        meta: {
            typescript: {
                exports: 'ts',
            },
            '*.css': { loader: 'css' },
        },
    });

    window.addEventListener('error', (e) => {
        console.error('ERROR', e.message, e.filename);
    });

    System.import(startFile).catch(function (err) {
        document.body.innerHTML =
            '<div class="example-error" style="background:#fdb022;padding:1rem;">' + 'Example Error: ' + err + '</div>';
        console.error(err);
    });
})(this);
{
  "name": "ag-grid-example",
  "dependencies": {
    "react": "18",
    "react-dom": "18",
    "@types/react": "18",
    "@types/react-dom": "18",
    "ag-grid-react": "34.0.0",
    "ag-grid-community": "34.0.0",
    "ag-grid-enterprise": "34.0.0"
  },
  "devDependencies": {
    "@types/node": "^22"
  }
}
<!DOCTYPE html><html lang="en"> <head><title>React Example - Ai Examples - Natural Language Grid State</title><meta charSet="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="robots" content="noindex"><meta http-equiv="last-modified" content="Wed Jul 09 2025 15:32:39 GMT+0100 (British Summer Time)"><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;700&amp;display=swap" rel="stylesheet"><style media="only screen">
        :root,
        body, #root {
            height: 100%;
            width: 100%;
            margin: 0;
            box-sizing: border-box;
            -webkit-overflow-scrolling: touch;
        }

        html {
            position: absolute;
            top: 0;
            left: 0;
            padding: 0;
            overflow: auto;
            font-family: -apple-system, 'system-ui', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans',
                'Liberation Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
                'Noto Color Emoji';
        }

        body {
            padding: 16px;
            overflow: auto;
            background-color: transparent;
        }

        
    </style></head> <body> <div id="root"></div>  <script>
            var appLocation = '';
            var boilerplatePath = '';
            var startFile = 'index.tsx';
            var systemJsMap = {
                "@ag-grid-community/locale": "https://localhost:4610/files/@ag-grid-community/locale",
                "ag-charts-community": "https://localhost:4610/files/ag-charts-community",
                "ag-charts-core": "https://localhost:4610/files/ag-charts-core",
                "ag-charts-enterprise": "https://localhost:4610/files/ag-charts-enterprise",
                "ag-charts-types": "https://localhost:4610/files/ag-charts-types",
                "ag-grid-community": "https://localhost:4610/files/ag-grid-community",
                "ag-grid-enterprise": "https://localhost:4610/files/ag-grid-enterprise",
                "ag-grid-react": "https://localhost:4610/files/ag-grid-react"
            };
            var systemJsPaths = {
                "@ag-grid-community/locale": "https://localhost:4610/files/@ag-grid-community/locale/dist/package/main.cjs.js",
                "ag-charts-community": "https://localhost:4610/files/ag-charts-community/dist/package/main.cjs.js",
                "ag-charts-core": "https://localhost:4610/files/ag-charts-core/dist/package/main.cjs.js",
                "ag-charts-enterprise": "https://localhost:4610/files/ag-charts-enterprise/dist/package/main.cjs.js",
                "ag-charts-types": "https://localhost:4610/files/ag-charts-types/dist/package/main.cjs.js"
            };
        </script><script src="https://cdn.jsdelivr.net/npm/systemjs@0.19.47/dist/system.js"></script><script src="systemjs.config.dev.js"></script>  </body></html>