@smallwebco/tinypivot-react 1.0.67 → 1.0.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/AIAnalyst.tsx","../src/hooks/useAIAnalyst.ts","../src/components/CalculatedFieldModal.tsx","../src/components/ChartBuilder.tsx","../src/components/ColumnFilter.tsx","../src/components/NumericRangeFilter.tsx","../src/components/DataGrid.tsx","../src/hooks/useExcelGrid.ts","../src/hooks/useGridFeatures.ts","../src/hooks/useLicense.ts","../src/hooks/usePivotTable.ts","../src/components/PivotConfig.tsx","../src/components/PivotSkeleton.tsx"],"sourcesContent":["/**\n * TinyPivot React\n * A powerful Excel-like data grid and pivot table component for React\n *\n * @packageDocumentation\n */\n\n// Components\nexport { AIAnalyst, ColumnFilter, DataGrid, PivotConfig, PivotSkeleton } from './components'\n\n// Hooks\nexport {\n configureLicenseSecret,\n copyToClipboard,\n enableDemoMode,\n exportPivotToCSV,\n exportToCSV,\n formatCellValue,\n formatSelectionForClipboard,\n getAggregationLabel,\n getColumnUniqueValues,\n setLicenseKey,\n useAIAnalyst,\n useColumnResize,\n useExcelGrid,\n useGlobalSearch,\n useLicense,\n usePagination,\n usePivotTable,\n useRowSelection,\n} from './hooks'\nexport type { UseAIAnalystOptions } from './hooks'\n\n// Re-export types from core\nexport type {\n // Pivot Types\n AggregationFunction,\n // AI Data Analyst Types\n AIAnalystConfig,\n AIColumnSchema,\n AIConversation,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIDataSource,\n AIErrorEvent,\n AIMessage,\n AIMessageMetadata,\n AIQueryExecutedEvent,\n\n AITableSchema,\n CellClickEvent,\n\n // Grid Types\n ColumnStats,\n CopyEvent,\n // Component Props Types\n DataGridProps,\n ExportEvent,\n ExportOptions,\n FieldStats,\n // Event Types\n FilterEvent,\n\n GridOptions,\n LicenseInfo,\n\n // License Types\n LicenseType,\n // Feature Types\n PaginationOptions,\n\n PivotCell,\n PivotConfig as PivotConfigType,\n PivotField,\n PivotResult,\n PivotTableProps,\n PivotValueField,\n RowSelectionChangeEvent,\n\n SelectionBounds,\n SelectionChangeEvent,\n SortEvent,\n} from '@smallwebco/tinypivot-core'\n","/**\n * TinyPivot React - AI Data Analyst Component\n * Split-panel layout: 1/4 chat, 3/4 data preview\n * Each query step shows data visually with expandable SQL\n */\nimport type {\n AIAnalystConfig,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIErrorEvent,\n AIMessage,\n AIQueryExecutedEvent,\n AITableSchema,\n} from '@smallwebco/tinypivot-core'\nimport { stripSQLFromContent } from '@smallwebco/tinypivot-core'\nimport React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'\nimport { useAIAnalyst } from '../hooks/useAIAnalyst'\n\ninterface AIAnalystProps {\n config: AIAnalystConfig\n theme?: 'light' | 'dark'\n onDataLoaded?: (payload: AIDataLoadedEvent) => void\n onConversationUpdate?: (payload: AIConversationUpdateEvent) => void\n onQueryExecuted?: (payload: AIQueryExecutedEvent) => void\n onError?: (payload: AIErrorEvent) => void\n onViewResults?: (payload: { data: Record<string, unknown>[], query: string }) => void\n}\n\nexport interface AIAnalystHandle {\n loadFullData: () => Promise<Record<string, unknown>[] | null>\n selectedDataSource: string | undefined\n}\n\nexport const AIAnalyst = forwardRef<AIAnalystHandle, AIAnalystProps>(({\n config,\n theme = 'light',\n onDataLoaded,\n onConversationUpdate,\n onQueryExecuted,\n onError,\n onViewResults,\n}, ref) => {\n const {\n messages,\n hasMessages,\n isLoading,\n isLoadingTables,\n schemas,\n selectedDataSource,\n selectedDataSourceInfo,\n lastLoadedData,\n dataSources,\n selectDataSource,\n sendMessage,\n clearConversation,\n loadFullData,\n } = useAIAnalyst({\n config,\n onDataLoaded,\n onConversationUpdate,\n onQueryExecuted,\n onError,\n })\n\n // Expose methods to parent via ref\n useImperativeHandle(ref, () => ({\n loadFullData,\n selectedDataSource,\n }), [loadFullData, selectedDataSource])\n\n const [inputText, setInputText] = useState('')\n const [searchQuery, setSearchQuery] = useState('')\n const [selectedMessageId, setSelectedMessageId] = useState<string | null>(null)\n const [showSqlPanel, setShowSqlPanel] = useState(false)\n const messagesContainerRef = useRef<HTMLDivElement>(null)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n // Filter data sources by search\n const filteredDataSources = useMemo(() => {\n if (!searchQuery.trim())\n return dataSources\n const q = searchQuery.toLowerCase()\n return dataSources.filter((ds: { name: string, description?: string, table: string }) =>\n ds.name.toLowerCase().includes(q)\n || ds.description?.toLowerCase().includes(q)\n || ds.table.toLowerCase().includes(q),\n )\n }, [dataSources, searchQuery])\n\n // Get schema for selected data source\n const currentSchema: AITableSchema | undefined = useMemo(() => {\n if (!selectedDataSource)\n return undefined\n return schemas.get(selectedDataSource)\n }, [selectedDataSource, schemas])\n\n // Get data for the selected message (or latest)\n const previewData = useMemo(() => {\n if (selectedMessageId) {\n const msg = messages.find((m: AIMessage) => m.id === selectedMessageId)\n if (msg?.metadata?.data) {\n return msg.metadata.data.slice(0, 100)\n }\n }\n if (!lastLoadedData)\n return []\n return lastLoadedData.slice(0, 100)\n }, [selectedMessageId, messages, lastLoadedData])\n\n // Get full data for the selected message\n const fullPreviewData = useMemo(() => {\n if (selectedMessageId) {\n const msg = messages.find((m: AIMessage) => m.id === selectedMessageId)\n if (msg?.metadata?.data) {\n return msg.metadata.data\n }\n }\n return lastLoadedData || []\n }, [selectedMessageId, messages, lastLoadedData])\n\n // Get column keys from preview data\n const previewColumns = useMemo(() => {\n if (previewData.length > 0) {\n return Object.keys(previewData[0])\n }\n if (currentSchema) {\n return currentSchema.columns.map((c: { name: string }) => c.name)\n }\n return []\n }, [previewData, currentSchema])\n\n // Get the selected message's query\n const selectedQuery = useMemo(() => {\n if (selectedMessageId) {\n const msg = messages.find((m: AIMessage) => m.id === selectedMessageId)\n return msg?.metadata?.query || ''\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].metadata?.data) {\n return messages[i].metadata?.query || ''\n }\n }\n return ''\n }, [selectedMessageId, messages])\n\n // Scroll to bottom when messages change and auto-select latest with data\n useEffect(() => {\n if (messagesContainerRef.current) {\n messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight\n }\n const latestWithData = [...messages].reverse().find((m: AIMessage) => m.metadata?.data)\n if (latestWithData) {\n setSelectedMessageId(latestWithData.id)\n }\n }, [messages])\n\n // Auto-resize textarea\n const autoResizeTextarea = useCallback(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`\n }\n }, [])\n\n useEffect(() => {\n autoResizeTextarea()\n }, [inputText, autoResizeTextarea])\n\n const handleSubmit = useCallback((e: React.FormEvent) => {\n e.preventDefault()\n if (!inputText.trim() || isLoading)\n return\n sendMessage(inputText)\n setInputText('')\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n }\n }, [inputText, isLoading, sendMessage])\n\n const handleKeydown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (!inputText.trim() || isLoading)\n return\n sendMessage(inputText)\n setInputText('')\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n }\n }\n }, [inputText, isLoading, sendMessage])\n\n const handleViewResults = useCallback(() => {\n if (fullPreviewData.length > 0) {\n onViewResults?.({ data: fullPreviewData, query: selectedQuery })\n }\n }, [fullPreviewData, selectedQuery, onViewResults])\n\n const selectMessage = useCallback((messageId: string) => {\n const msg = messages.find((m: AIMessage) => m.id === messageId)\n if (msg?.metadata?.data) {\n setSelectedMessageId(messageId)\n }\n }, [messages])\n\n const copyToClipboard = useCallback((text: string) => {\n navigator.clipboard.writeText(text)\n }, [])\n\n const handleClearConversation = useCallback(() => {\n clearConversation()\n setSearchQuery('')\n setSelectedMessageId(null)\n setShowSqlPanel(false)\n }, [clearConversation])\n\n const handleChangeDataSource = useCallback(() => {\n clearConversation()\n setSearchQuery('')\n setSelectedMessageId(null)\n setShowSqlPanel(false)\n }, [clearConversation])\n\n const toggleSqlPanel = useCallback(() => {\n setShowSqlPanel(prev => !prev)\n }, [])\n\n const getColumnTypeIcon = (type: string): string => {\n const t = type.toLowerCase()\n if (t.includes('int') || t.includes('float') || t.includes('decimal') || t.includes('number'))\n return '#'\n if (t.includes('date') || t.includes('time'))\n return 'D'\n if (t.includes('bool'))\n return '?'\n return 'T'\n }\n\n const formatCellValue = (value: unknown): string => {\n if (value === null || value === undefined)\n return ''\n if (typeof value === 'number') {\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n return String(value)\n }\n return String(value)\n }\n\n const getMessageContent = (message: AIMessage): string => {\n // Strip SQL blocks and clean up markdown formatting\n return stripSQLFromContent(message.content)\n .replace(/\\*\\*/g, '')\n .replace(/`([^`]+)`/g, '$1')\n .trim()\n }\n\n const hasQueryResult = (message: AIMessage): boolean => {\n return !!message.metadata?.data && message.metadata.data.length > 0\n }\n\n // Render data source picker (full screen)\n if (!selectedDataSource) {\n return (\n <div className={`vpg-ai-analyst ${theme === 'dark' ? 'vpg-theme-dark' : ''}`}>\n <div className=\"vpg-ai-picker-fullscreen\">\n <div className=\"vpg-ai-picker-content\">\n <div className=\"vpg-ai-picker-header\">\n <div className=\"vpg-ai-icon-lg\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z\" />\n <circle cx=\"7.5\" cy=\"14.5\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"16.5\" cy=\"14.5\" r=\"1.5\" fill=\"currentColor\" />\n </svg>\n </div>\n <h2>AI Data Analyst</h2>\n <p>Select a data source to start exploring with AI</p>\n </div>\n\n {dataSources.length === 0 && !isLoadingTables ? (\n <div className=\"vpg-ai-empty-state\">\n <p>No data sources configured.</p>\n <a\n href=\"https://tinypivot.com/docs/ai-analyst\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"vpg-ai-docs-link\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n View Documentation\n </a>\n </div>\n ) : (\n <>\n <div className=\"vpg-ai-search\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n <input\n type=\"text\"\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n placeholder=\"Search data sources...\"\n className=\"vpg-ai-search-input\"\n />\n </div>\n <div className=\"vpg-ai-datasource-grid\">\n {filteredDataSources.map((ds: { id: string, name: string, description?: string }) => (\n <button\n key={ds.id}\n className=\"vpg-ai-datasource-card\"\n onClick={() => selectDataSource(ds.id)}\n >\n <div className=\"vpg-ai-datasource-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n </div>\n <div className=\"vpg-ai-datasource-info\">\n <span className=\"vpg-ai-datasource-name\">{ds.name}</span>\n {ds.description && (\n <span className=\"vpg-ai-datasource-desc\">{ds.description}</span>\n )}\n </div>\n </button>\n ))}\n </div>\n {filteredDataSources.length === 0 && (\n <div className=\"vpg-ai-no-results\">\n No data sources match \"\n {searchQuery}\n \"\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n )\n }\n\n // Render split layout\n return (\n <div className={`vpg-ai-analyst ${theme === 'dark' ? 'vpg-theme-dark' : ''}`}>\n <div className=\"vpg-ai-split-layout\">\n {/* Left Panel: Chat */}\n <div className=\"vpg-ai-chat-panel\">\n {/* Chat Header */}\n <div className=\"vpg-ai-chat-header\">\n <button\n className=\"vpg-ai-back-btn\"\n title=\"Change data source\"\n onClick={handleChangeDataSource}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n <div className=\"vpg-ai-chat-title\">\n <span className=\"vpg-ai-chat-name\">{selectedDataSourceInfo?.name}</span>\n </div>\n {hasMessages && (\n <button\n className=\"vpg-ai-clear-btn\"\n title=\"Clear conversation\"\n onClick={handleClearConversation}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n </button>\n )}\n </div>\n\n {/* Messages */}\n <div ref={messagesContainerRef} className=\"vpg-ai-messages\">\n {/* Welcome message */}\n {!hasMessages && (\n <div className=\"vpg-ai-welcome\">\n <p>Ask questions about your data</p>\n <div className=\"vpg-ai-suggestions\">\n <button onClick={() => sendMessage('Show me a summary of the data')}>\n Summary\n </button>\n <button onClick={() => sendMessage('Show me the top 10 records')}>\n Top 10\n </button>\n <button onClick={() => sendMessage('What are the trends?')}>\n Trends\n </button>\n </div>\n </div>\n )}\n\n {/* Message list */}\n {messages.map((message: AIMessage) => {\n if (message.role === 'user') {\n return (\n <div key={message.id} className=\"vpg-ai-msg vpg-ai-msg-user\">\n <span>{message.content}</span>\n </div>\n )\n }\n\n if (hasQueryResult(message)) {\n return (\n <div\n key={message.id}\n className={`vpg-ai-msg vpg-ai-msg-result ${selectedMessageId === message.id ? 'vpg-ai-msg-selected' : ''}`}\n onClick={() => selectMessage(message.id)}\n >\n {/* Header with result badge and SQL toggle */}\n <div className=\"vpg-ai-result-header\">\n <div className=\"vpg-ai-result-badge\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <polyline points=\"22 4 12 14.01 9 11.01\" />\n </svg>\n <span>\n {message.metadata?.rowCount?.toLocaleString()}\n {' '}\n rows\n </span>\n </div>\n {/* SQL toggle button - toggles right pane SQL panel */}\n {message.metadata?.query && (\n <button\n className={`vpg-ai-sql-toggle ${showSqlPanel && selectedMessageId === message.id ? 'vpg-ai-sql-expanded' : ''}`}\n title=\"View SQL query\"\n onClick={(e) => {\n e.stopPropagation()\n toggleSqlPanel()\n }}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </svg>\n <span>SQL</span>\n </button>\n )}\n </div>\n {/* Full message content (insight from AI) */}\n <div className=\"vpg-ai-result-content\">\n {getMessageContent(message)}\n </div>\n </div>\n )\n }\n\n // Regular assistant message\n return (\n <div key={message.id} className=\"vpg-ai-msg vpg-ai-msg-assistant\">\n <div className=\"vpg-ai-assistant-content\">{getMessageContent(message)}</div>\n {message.metadata?.error && (\n <div className=\"vpg-ai-msg-error\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n Error\n </div>\n )}\n </div>\n )\n })}\n\n {/* Loading indicator */}\n {isLoading && (\n <div className=\"vpg-ai-msg vpg-ai-msg-loading\">\n <div className=\"vpg-ai-typing\">\n <span />\n <span />\n <span />\n </div>\n </div>\n )}\n </div>\n\n {/* Input Area */}\n <div className=\"vpg-ai-input-area\">\n <form className=\"vpg-ai-input-form\" onSubmit={handleSubmit}>\n <textarea\n ref={textareaRef}\n className=\"vpg-ai-input\"\n placeholder=\"Ask about your data...\"\n disabled={isLoading}\n rows={1}\n value={inputText}\n onChange={e => setInputText(e.target.value)}\n onKeyDown={handleKeydown}\n />\n <button\n type=\"submit\"\n className=\"vpg-ai-send-btn\"\n disabled={!inputText.trim() || isLoading}\n title=\"Send\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n </svg>\n </button>\n </form>\n {/* Input footer with model name and actions */}\n <div className=\"vpg-ai-input-footer\">\n {config.aiModelName && (\n <span className=\"vpg-ai-model-name\">{config.aiModelName}</span>\n )}\n <div className=\"vpg-ai-input-actions\">\n {fullPreviewData.length > 0 && (\n <button\n className=\"vpg-ai-action-btn vpg-ai-action-primary\"\n title=\"View in Grid tab\"\n onClick={handleViewResults}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n View in Grid\n </button>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* Right Panel: Data Scratchpad */}\n <div className=\"vpg-ai-preview-panel\">\n {/* Header with schema */}\n <div className=\"vpg-ai-preview-header\">\n <div className=\"vpg-ai-preview-title-row\">\n <h3>{selectedDataSourceInfo?.name}</h3>\n <div className=\"vpg-ai-preview-meta\">\n {fullPreviewData.length > 0 && (\n <span className=\"vpg-ai-preview-count\">\n {fullPreviewData.length.toLocaleString()}\n {' '}\n rows\n </span>\n )}\n {selectedQuery && (\n <button\n className={`vpg-ai-preview-sql-btn ${showSqlPanel ? 'vpg-ai-sql-active' : ''}`}\n title=\"Toggle SQL query\"\n onClick={toggleSqlPanel}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </svg>\n SQL\n </button>\n )}\n {fullPreviewData.length > 0 && (\n <button\n className=\"vpg-ai-preview-view-btn\"\n title=\"View in Grid\"\n onClick={handleViewResults}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" />\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\" />\n </svg>\n View in Grid\n </button>\n )}\n </div>\n </div>\n {/* Schema chips in preview header */}\n {currentSchema && (\n <div className=\"vpg-ai-schema-bar\">\n {currentSchema.columns.map((col: { name: string, type: string }) => (\n <div\n key={col.name}\n className=\"vpg-ai-schema-chip\"\n title={`${col.name} (${col.type})`}\n >\n <span className=\"vpg-ai-chip-type\">{getColumnTypeIcon(col.type)}</span>\n <span className=\"vpg-ai-chip-name\">{col.name}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* SQL Panel (expandable, above the table) */}\n {showSqlPanel && selectedQuery && (\n <div className=\"vpg-ai-sql-panel\">\n <div className=\"vpg-ai-sql-panel-header\">\n <span className=\"vpg-ai-sql-panel-title\">SQL Query</span>\n <div className=\"vpg-ai-sql-panel-actions\">\n <button\n className=\"vpg-ai-copy-btn\"\n title=\"Copy SQL\"\n onClick={() => copyToClipboard(selectedQuery)}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n </button>\n <button\n className=\"vpg-ai-sql-panel-close\"\n title=\"Close\"\n onClick={() => setShowSqlPanel(false)}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n </div>\n <pre className=\"vpg-ai-sql-panel-code\"><code>{selectedQuery}</code></pre>\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"vpg-ai-preview-loading\">\n <div className=\"vpg-ai-preview-spinner\" />\n <span>Running query...</span>\n </div>\n ) : previewData.length === 0 && currentSchema ? (\n /* Ready state (schema loaded, no data yet) */\n <div className=\"vpg-ai-preview-ready\">\n <div className=\"vpg-ai-preview-ready-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n <path d=\"M3 12c0 1.66 4 3 9 3s9-1.34 9-3\" />\n </svg>\n </div>\n <p>Data source connected</p>\n <span>\n {currentSchema.columns.length}\n {' '}\n columns available\n </span>\n <div className=\"vpg-ai-preview-hint\">\n Ask a question to explore the data\n </div>\n </div>\n ) : previewData.length === 0 ? (\n /* No schema loaded yet */\n <div className=\"vpg-ai-preview-empty\">\n <div className=\"vpg-ai-preview-empty-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </div>\n <p>Loading data source...</p>\n </div>\n ) : (\n /* Data table */\n <div className=\"vpg-ai-preview-table-container\">\n <table className=\"vpg-ai-preview-table\">\n <thead>\n <tr>\n {previewColumns.map((col: string) => (\n <th key={col}>{col}</th>\n ))}\n </tr>\n </thead>\n <tbody>\n {previewData.map((row: Record<string, unknown>, idx: number) => (\n <tr key={idx}>\n {previewColumns.map((col: string) => (\n <td key={col}>{formatCellValue(row[col])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {fullPreviewData.length > 100 && (\n <div className=\"vpg-ai-preview-more\">\n Showing 100 of\n {' '}\n {fullPreviewData.length.toLocaleString()}\n {' '}\n rows.\n <button onClick={handleViewResults}>View all in Grid</button>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n})\n","/**\n * TinyPivot React - AI Analyst Hook\n * Manages AI conversation state and data fetching\n */\nimport type {\n AIAnalystConfig,\n AIConversation,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIDataSource,\n AIErrorEvent,\n AIProxyResponse,\n AIQueryExecutedEvent,\n AITableSchema,\n ListTablesResponse,\n SchemaResponse,\n} from '@smallwebco/tinypivot-core'\nimport {\n addMessageToConversation,\n buildSystemPrompt,\n createAssistantMessage,\n createConversation,\n createUserMessage,\n extractSQLFromResponse,\n findDemoResponse,\n getDefaultDemoResponse,\n getDemoSchema,\n getInitialDemoData,\n getMessagesForAPI,\n setConversationDataSource,\n validateSQLSafety,\n} from '@smallwebco/tinypivot-core'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nexport interface UseAIAnalystOptions {\n config: AIAnalystConfig\n onDataLoaded?: (event: AIDataLoadedEvent) => void\n onConversationUpdate?: (event: AIConversationUpdateEvent) => void\n onQueryExecuted?: (event: AIQueryExecutedEvent) => void\n onError?: (event: AIErrorEvent) => void\n}\n\nexport function useAIAnalyst(options: UseAIAnalystOptions) {\n const { config, onDataLoaded, onConversationUpdate, onQueryExecuted, onError } = options\n\n // Use refs to avoid stale closures in callbacks\n const configRef = useRef(config)\n configRef.current = config\n\n // LocalStorage key for persistence\n const storageKey = config.persistToLocalStorage\n ? `tinypivot-ai-conversation-${config.sessionId || 'default'}`\n : null\n\n // Load initial conversation from localStorage if enabled\n const loadFromStorage = useCallback((): AIConversation => {\n if (storageKey && typeof window !== 'undefined') {\n try {\n const stored = localStorage.getItem(storageKey)\n if (stored) {\n const parsed = JSON.parse(stored)\n if (parsed.id && Array.isArray(parsed.messages)) {\n return parsed as AIConversation\n }\n }\n }\n catch (e) {\n console.warn('[TinyPivot] Failed to load conversation from localStorage:', e)\n }\n }\n return createConversation(config.sessionId)\n }, [storageKey, config.sessionId])\n\n // Save conversation to localStorage if enabled\n const saveToStorage = useCallback((conv: AIConversation) => {\n if (storageKey && typeof window !== 'undefined') {\n try {\n // Custom replacer to handle BigInt values (common in DuckDB results)\n const replacer = (_key: string, value: unknown) => {\n if (typeof value === 'bigint') {\n return Number(value)\n }\n return value\n }\n localStorage.setItem(storageKey, JSON.stringify(conv, replacer))\n }\n catch (e) {\n console.warn('[TinyPivot] Failed to save conversation to localStorage:', e)\n }\n }\n }, [storageKey])\n\n // State\n const [conversation, setConversation] = useState<AIConversation>(() => loadFromStorage())\n const [schemas, setSchemas] = useState<Map<string, AITableSchema>>(new Map())\n const [allSchemas, setAllSchemas] = useState<AITableSchema[]>([]) // All table schemas for JOINs\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [lastLoadedData, setLastLoadedData] = useState<Record<string, unknown>[] | null>(null)\n\n // Dynamic data sources (discovered from endpoint)\n const [discoveredDataSources, setDiscoveredDataSources] = useState<AIDataSource[]>([])\n const [isLoadingTables, setIsLoadingTables] = useState(false)\n\n // Get effective data sources (config or discovered)\n const effectiveDataSources = useMemo<AIDataSource[]>(() => {\n if (config.dataSources && config.dataSources.length > 0) {\n return config.dataSources\n }\n return discoveredDataSources\n }, [config.dataSources, discoveredDataSources])\n\n // Save to storage whenever conversation changes\n useEffect(() => {\n saveToStorage(conversation)\n }, [conversation, saveToStorage])\n\n // Computed values\n const selectedDataSource = conversation.dataSourceId\n const selectedDataSourceInfo = useMemo(\n () => effectiveDataSources.find((ds: AIDataSource) => ds.id === conversation.dataSourceId),\n [effectiveDataSources, conversation.dataSourceId],\n )\n const messages = conversation.messages\n const hasMessages = conversation.messages.length > 0\n\n /**\n * Fetch schemas for ALL tables at once (enables JOINs)\n */\n const fetchAllSchemas = useCallback(async () => {\n if (!configRef.current.endpoint)\n return\n\n try {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'get-all-schemas' }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch all schemas: ${response.statusText}`)\n }\n\n const data: SchemaResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n // Store all schemas for JOIN support\n setAllSchemas(data.schemas)\n\n // Also populate the individual schemas map\n setSchemas((prev) => {\n const newMap = new Map(prev)\n for (const schema of data.schemas) {\n newMap.set(schema.table, schema)\n }\n return newMap\n })\n }\n catch (err) {\n // Schema fetch is optional - continue without it\n console.warn('[TinyPivot] Failed to fetch all schemas:', err)\n }\n }, [])\n\n /**\n * Fetch available tables from endpoint (auto-discovery mode)\n */\n const fetchTables = useCallback(async () => {\n if (!configRef.current.endpoint)\n return\n\n setIsLoadingTables(true)\n try {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'list-tables' }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch tables: ${response.statusText}`)\n }\n\n const data: ListTablesResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n // Convert to AIDataSource format\n setDiscoveredDataSources(data.tables.map((t: { name: string, description?: string }) => ({\n id: t.name,\n table: t.name,\n name: t.name.charAt(0).toUpperCase() + t.name.slice(1), // Capitalize\n description: t.description,\n })))\n\n // Fetch all schemas for JOIN support\n await fetchAllSchemas()\n }\n catch (err) {\n console.warn('[TinyPivot] Failed to fetch tables:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to fetch tables',\n type: 'network',\n })\n }\n finally {\n setIsLoadingTables(false)\n }\n }, [onError, fetchAllSchemas])\n\n // Initialize: fetch tables if using endpoint\n useEffect(() => {\n if (configRef.current.endpoint && (!config.dataSources || config.dataSources.length === 0)) {\n fetchTables()\n }\n }, [fetchTables, config.dataSources])\n\n /**\n * Fetch schema from the unified endpoint\n */\n const fetchSchema = useCallback(async (dataSource: AIDataSource) => {\n if (!configRef.current.endpoint)\n return\n\n try {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'get-schema',\n tables: [dataSource.table],\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch schema: ${response.statusText}`)\n }\n\n const data: SchemaResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n if (data.schemas.length > 0) {\n setSchemas(prev => new Map(prev).set(dataSource.id, data.schemas[0]))\n }\n }\n catch (err) {\n // Schema fetch is optional - continue without it\n console.warn('Failed to fetch schema:', err)\n }\n }, [])\n\n /**\n * Fetch sample data (first 100 rows) from the unified endpoint\n */\n const fetchSampleData = useCallback(async (dataSource: AIDataSource) => {\n if (!configRef.current.endpoint)\n return\n\n try {\n const sql = `SELECT * FROM ${dataSource.table} LIMIT 100`\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'query',\n sql,\n table: dataSource.table,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch sample data: ${response.statusText}`)\n }\n\n const result = await response.json()\n\n if (result.error) {\n throw new Error(result.error)\n }\n\n if (result.data && result.data.length > 0) {\n setLastLoadedData(result.data)\n onDataLoaded?.({\n data: result.data,\n query: sql,\n dataSourceId: dataSource.id,\n rowCount: result.data.length,\n })\n }\n }\n catch (err) {\n // Sample data fetch is optional - continue without it\n console.warn('Failed to fetch sample data:', err)\n }\n }, [onDataLoaded])\n\n /**\n * Select a data source and fetch its schema\n */\n const selectDataSource = useCallback(async (dataSourceId: string) => {\n const dataSource = effectiveDataSources.find(ds => ds.id === dataSourceId)\n if (!dataSource) {\n setError(`Data source \"${dataSourceId}\" not found`)\n return\n }\n\n // Update conversation\n setConversation((prev) => {\n const updated = setConversationDataSource(prev, dataSourceId)\n const withMessage = addMessageToConversation(\n updated,\n createAssistantMessage(\n `I'm now connected to **${dataSource.name}**. ${dataSource.description || ''}\\n\\nWhat would you like to know about this data?`,\n ),\n )\n onConversationUpdate?.({ conversation: withMessage })\n return withMessage\n })\n\n // Load data source if custom loader is provided (demo mode)\n if (configRef.current.dataSourceLoader) {\n try {\n const { data, schema } = await configRef.current.dataSourceLoader(dataSourceId)\n if (schema) {\n setSchemas(prev => new Map(prev).set(dataSourceId, schema))\n }\n // Store the loaded data for the data source\n if (data && data.length > 0) {\n setLastLoadedData(data)\n onDataLoaded?.({\n data,\n query: `SELECT * FROM ${dataSource.table} LIMIT 100`,\n dataSourceId,\n rowCount: data.length,\n })\n }\n }\n catch (err) {\n console.warn('Failed to load data source:', err)\n }\n }\n // Fetch schema (demo mode uses mock schemas)\n else if (configRef.current.demoMode) {\n const demoSchema = getDemoSchema(dataSourceId)\n if (demoSchema) {\n setSchemas(prev => new Map(prev).set(dataSourceId, demoSchema))\n }\n // Load initial sample data for the preview\n const initialData = getInitialDemoData(dataSourceId)\n if (initialData) {\n setLastLoadedData(initialData)\n onDataLoaded?.({\n data: initialData,\n query: `SELECT * FROM ${dataSource.table} LIMIT 10`,\n dataSourceId,\n rowCount: initialData.length,\n })\n }\n }\n // Use endpoint for schema discovery and sample data\n else if (configRef.current.endpoint) {\n await fetchSchema(dataSource)\n await fetchSampleData(dataSource)\n }\n }, [effectiveDataSources, fetchSchema, fetchSampleData, onConversationUpdate, onDataLoaded])\n\n /**\n * Call the AI endpoint\n */\n const callAIEndpoint = useCallback(async (\n userInput: string,\n currentConversation: AIConversation,\n currentSchemas: Map<string, AITableSchema>,\n currentDataSources: AIDataSource[],\n currentAllSchemas: AITableSchema[],\n ): Promise<string> => {\n if (!configRef.current.endpoint) {\n throw new Error('No endpoint configured. Set `endpoint` in AI analyst config.')\n }\n\n const dataSourceId = currentConversation.dataSourceId\n\n // Build system prompt using effective data sources\n // Pass allSchemas to enable JOINs with related tables\n const systemPrompt = buildSystemPrompt(\n currentDataSources,\n currentSchemas,\n dataSourceId,\n currentAllSchemas.length > 0 ? currentAllSchemas : undefined,\n )\n\n // Get conversation messages for API\n const apiMessages = getMessagesForAPI(currentConversation)\n\n // Add system prompt and current user message\n const messages = [\n { role: 'user' as const, content: systemPrompt },\n { role: 'assistant' as const, content: 'I understand. I\\'m ready to help you analyze the data.' },\n ...apiMessages.slice(0, -1), // Exclude the just-added user message\n { role: 'user' as const, content: userInput },\n ]\n\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'chat', messages }),\n })\n\n if (!response.ok) {\n throw new Error(`AI request failed: ${response.statusText}`)\n }\n\n const data: AIProxyResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n return data.content\n }, [])\n\n /**\n * Execute a SQL query and update the specified message with results\n * @param sql The SQL query to execute\n * @param currentConversation Current conversation state\n * @param currentDataSources Available data sources\n * @param messageId Optional message ID to update with results (instead of adding new message)\n */\n const executeQuery = useCallback(async (\n sql: string,\n currentConversation: AIConversation,\n currentDataSources: AIDataSource[],\n messageId?: string,\n ) => {\n const dataSourceId = currentConversation.dataSourceId\n if (!dataSourceId)\n return\n\n const dataSource = currentDataSources.find((ds: { id: string }) => ds.id === dataSourceId)\n if (!dataSource)\n return\n\n const startTime = Date.now()\n\n try {\n let data: { data?: Record<string, unknown>[], rowCount?: number, truncated?: boolean, error?: string, success?: boolean }\n\n // Use custom query executor if provided (demo mode)\n if (configRef.current.queryExecutor) {\n const result = await configRef.current.queryExecutor(sql, dataSource.table)\n data = {\n data: result.data,\n rowCount: result.rowCount,\n truncated: result.truncated,\n error: result.error,\n success: !result.error,\n }\n }\n // Use unified endpoint\n else if (configRef.current.endpoint) {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'query',\n sql,\n table: dataSource.table,\n }),\n })\n\n data = await response.json()\n }\n else {\n throw new Error('No query executor or endpoint configured')\n }\n\n const duration = Date.now() - startTime\n\n if (!data.success || data.error) {\n // Add error message\n setConversation((prev: AIConversation) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `The query failed: ${data.error || 'Unknown error'}. Would you like me to try a different approach?`,\n { error: data.error, query: sql },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n onQueryExecuted?.({\n query: sql,\n rowCount: 0,\n duration,\n dataSourceId,\n success: false,\n error: data.error,\n })\n\n onError?.({\n message: data.error || 'Query failed',\n query: sql,\n type: 'query',\n })\n return\n }\n\n // Success - load data\n if (data.data) {\n setLastLoadedData(data.data)\n\n // Update the existing message with data, or add a new one if no messageId\n if (messageId) {\n // Find and update the existing message's metadata with the data\n setConversation((prev: AIConversation) => {\n const updatedMessages = prev.messages.map((msg) => {\n if (msg.id === messageId) {\n return {\n ...msg,\n metadata: {\n ...msg.metadata,\n data: data.data,\n rowCount: data.rowCount,\n truncated: data.truncated,\n },\n }\n }\n return msg\n })\n const updated = {\n ...prev,\n messages: updatedMessages,\n updatedAt: Date.now(),\n }\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n else {\n // Fallback: add a new message (shouldn't happen in normal flow)\n const truncatedNote = data.truncated\n ? ` (limited to ${configRef.current.maxRows || 10000} rows)`\n : ''\n\n setConversation((prev: AIConversation) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `Retrieved **${data.rowCount} rows**${truncatedNote}.`,\n { query: sql, rowCount: data.rowCount, data: data.data },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n\n onDataLoaded?.({\n data: data.data,\n query: sql,\n dataSourceId,\n rowCount: data.rowCount || data.data.length,\n })\n\n onQueryExecuted?.({\n query: sql,\n rowCount: data.rowCount || data.data.length,\n duration,\n dataSourceId,\n success: true,\n })\n }\n }\n catch (err) {\n const duration = Date.now() - startTime\n const errorMsg = err instanceof Error ? err.message : 'Query execution failed'\n\n setConversation((prev: AIConversation) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `Failed to execute query: ${errorMsg}`,\n { error: errorMsg, query: sql },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n onQueryExecuted?.({\n query: sql,\n rowCount: 0,\n duration,\n dataSourceId,\n success: false,\n error: errorMsg,\n })\n\n onError?.({\n message: errorMsg,\n query: sql,\n type: 'network',\n })\n }\n }, [onConversationUpdate, onDataLoaded, onQueryExecuted, onError])\n\n /**\n * Handle demo mode responses\n */\n const handleDemoResponse = useCallback(async (\n userInput: string,\n currentConversation: AIConversation,\n ) => {\n // Simulate loading delay\n await new Promise(resolve => setTimeout(resolve, 800))\n\n const dataSourceId = currentConversation.dataSourceId\n\n if (!dataSourceId) {\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n 'Please select a data source first by clicking one of the options above.',\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n return\n }\n\n // Find matching demo response\n const demoTrigger = findDemoResponse(dataSourceId, userInput)\n\n if (demoTrigger) {\n // Add AI response\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(demoTrigger.response, {\n query: demoTrigger.query,\n rowCount: demoTrigger.mockData?.length,\n }),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n // Load mock data\n if (demoTrigger.mockData) {\n setLastLoadedData(demoTrigger.mockData)\n\n onDataLoaded?.({\n data: demoTrigger.mockData,\n query: demoTrigger.query || '',\n dataSourceId,\n rowCount: demoTrigger.mockData.length,\n })\n\n onQueryExecuted?.({\n query: demoTrigger.query || '',\n rowCount: demoTrigger.mockData.length,\n duration: 150, // Fake duration\n dataSourceId,\n success: true,\n })\n }\n }\n else {\n // Use default response\n const defaultResponse = getDefaultDemoResponse(dataSourceId)\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(defaultResponse),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n }, [onConversationUpdate, onDataLoaded, onQueryExecuted])\n\n /**\n * Send a message to the AI\n */\n const sendMessage = useCallback(async (content: string) => {\n if (!content.trim())\n return\n if (isLoading)\n return\n\n setError(null)\n setIsLoading(true)\n\n // Add user message\n let updatedConversation: AIConversation\n setConversation((prev) => {\n updatedConversation = addMessageToConversation(prev, createUserMessage(content))\n onConversationUpdate?.({ conversation: updatedConversation })\n return updatedConversation\n })\n\n try {\n // Wait for state to update\n await new Promise(resolve => setTimeout(resolve, 0))\n\n // Get current state\n const currentConv = updatedConversation!\n\n // Handle demo mode\n if (configRef.current.demoMode) {\n await handleDemoResponse(content, currentConv)\n return\n }\n\n // Check if data source is selected\n if (!currentConv.dataSourceId) {\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n 'Please select a data source first by clicking one of the options above.',\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n return\n }\n\n // Call AI endpoint\n const aiResponse = await callAIEndpoint(content, currentConv, schemas, effectiveDataSources, allSchemas)\n\n // Check if AI wants to run a query\n const sqlQuery = extractSQLFromResponse(aiResponse)\n\n if (sqlQuery) {\n // Validate SQL\n const validation = validateSQLSafety(sqlQuery)\n if (!validation.valid) {\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `I generated an invalid query: ${validation.error}. Let me try again with a corrected approach.`,\n { error: validation.error },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n return\n }\n\n // Create the AI message and capture its ID for updating with query results\n const aiMessage = createAssistantMessage(aiResponse, { query: sqlQuery })\n\n setConversation((prev) => {\n const updated = addMessageToConversation(prev, aiMessage)\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n // Execute query and update the same message with data\n await executeQuery(sqlQuery, currentConv, effectiveDataSources, aiMessage.id)\n }\n else {\n // Just add AI response\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(aiResponse),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n }\n catch (err) {\n const errorMsg = err instanceof Error ? err.message : 'An error occurred'\n setError(errorMsg)\n\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `Sorry, I encountered an error: ${errorMsg}. Please try again.`,\n { error: errorMsg },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n onError?.({\n message: errorMsg,\n type: 'ai',\n })\n }\n finally {\n setIsLoading(false)\n }\n }, [isLoading, schemas, effectiveDataSources, callAIEndpoint, executeQuery, handleDemoResponse, onConversationUpdate, onError])\n\n /**\n * Load full data for the currently selected data source\n * Returns the full dataset (not limited) for displaying in the grid\n */\n const loadFullData = useCallback(async (): Promise<Record<string, unknown>[] | null> => {\n const dataSourceId = conversation.dataSourceId\n if (!dataSourceId) {\n return null\n }\n\n const dataSource = effectiveDataSources.find(ds => ds.id === dataSourceId)\n if (!dataSource) {\n return null\n }\n\n const currentConfig = configRef.current\n\n // Use custom data source loader if provided\n if (currentConfig.dataSourceLoader) {\n try {\n const { data } = await currentConfig.dataSourceLoader(dataSourceId)\n if (data && data.length > 0) {\n return data\n }\n }\n catch (err) {\n console.warn('Failed to load full data:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to load full data',\n type: 'network',\n })\n }\n return null\n }\n\n // Use query executor to get all data\n if (currentConfig.queryExecutor) {\n try {\n const result = await currentConfig.queryExecutor(\n `SELECT * FROM ${dataSource.table}`,\n dataSource.table,\n )\n if (result.data && result.data.length > 0) {\n return result.data\n }\n }\n catch (err) {\n console.warn('Failed to load full data via query:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to load full data',\n type: 'network',\n })\n }\n return null\n }\n\n // Use endpoint query action\n if (currentConfig.endpoint) {\n try {\n const response = await fetch(currentConfig.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'query',\n sql: `SELECT * FROM ${dataSource.table}`,\n table: dataSource.table,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to load data: ${response.statusText}`)\n }\n\n const data = await response.json()\n if (data.data && data.data.length > 0) {\n return data.data\n }\n }\n catch (err) {\n console.warn('Failed to load full data from endpoint:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to load full data',\n type: 'network',\n })\n }\n return null\n }\n\n // Demo mode - get initial data\n if (currentConfig.demoMode) {\n const initialData = getInitialDemoData(dataSourceId)\n return initialData || null\n }\n\n return null\n }, [conversation.dataSourceId, effectiveDataSources, onError])\n\n /**\n * Clear the conversation\n */\n const clearConversation = useCallback(() => {\n const newConv = createConversation(configRef.current.sessionId)\n setConversation(newConv)\n setError(null)\n setLastLoadedData(null)\n onConversationUpdate?.({ conversation: newConv })\n }, [onConversationUpdate])\n\n /**\n * Export conversation for persistence\n */\n const exportConversation = useCallback((): AIConversation => {\n return { ...conversation }\n }, [conversation])\n\n /**\n * Import a conversation\n */\n const importConversation = useCallback((conv: AIConversation) => {\n setConversation(conv)\n onConversationUpdate?.({ conversation: conv })\n }, [onConversationUpdate])\n\n return {\n // State\n conversation,\n messages,\n hasMessages,\n schemas,\n isLoading,\n isLoadingTables,\n error,\n lastLoadedData,\n selectedDataSource,\n selectedDataSourceInfo,\n /** Available data sources (either from config or auto-discovered) */\n dataSources: effectiveDataSources,\n\n // Actions\n selectDataSource,\n sendMessage,\n clearConversation,\n exportConversation,\n importConversation,\n /** Refresh table list from endpoint */\n fetchTables,\n /** Load full data for the currently selected data source */\n loadFullData,\n }\n}\n","import type { CalculatedField } from '@smallwebco/tinypivot-core'\nimport { validateSimpleFormula } from '@smallwebco/tinypivot-core'\n/**\n * Calculated Field Modal for React\n * UI for creating custom calculated fields with formulas\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\ninterface CalculatedFieldModalProps {\n show: boolean\n availableFields: string[]\n existingField?: CalculatedField | null\n onClose: () => void\n onSave: (field: CalculatedField) => void\n}\n\nexport function CalculatedFieldModal({\n show,\n availableFields,\n existingField,\n onClose,\n onSave,\n}: CalculatedFieldModalProps) {\n // Form state\n const [name, setName] = useState('')\n const [formula, setFormula] = useState('')\n const [formatAs, setFormatAs] = useState<'number' | 'percent' | 'currency'>('number')\n const [decimals, setDecimals] = useState(2)\n const [error, setError] = useState<string | null>(null)\n\n // Reset form when modal opens\n useEffect(() => {\n if (show) {\n if (existingField) {\n setName(existingField.name)\n setFormula(existingField.formula)\n setFormatAs(existingField.formatAs || 'number')\n setDecimals(existingField.decimals ?? 2)\n }\n else {\n setName('')\n setFormula('')\n setFormatAs('number')\n setDecimals(2)\n }\n setError(null)\n }\n }, [show, existingField])\n\n // Validate formula on change\n const validationError = useMemo(() => {\n if (!formula.trim())\n return null\n return validateSimpleFormula(formula, availableFields)\n }, [formula, availableFields])\n\n // Insert field into formula\n const insertField = useCallback((field: string) => {\n setFormula((prev) => {\n if (prev.trim() && !prev.endsWith(' ')) {\n return `${prev} ${field}`\n }\n return prev + field\n })\n }, [])\n\n // Insert operator into formula\n const insertOperator = useCallback((op: string) => {\n setFormula((prev) => {\n if (prev.trim() && !prev.endsWith(' ')) {\n return `${prev} ${op} `\n }\n return `${prev + op} `\n })\n }, [])\n\n // Save calculated field\n const handleSave = useCallback(() => {\n if (!name.trim()) {\n setError('Name is required')\n return\n }\n\n const validationResult = validateSimpleFormula(formula, availableFields)\n if (validationResult) {\n setError(validationResult)\n return\n }\n\n const field: CalculatedField = {\n id: existingField?.id || `calc_${Date.now()}`,\n name: name.trim(),\n formula: formula.trim(),\n formatAs,\n decimals,\n }\n\n onSave(field)\n onClose()\n }, [name, formula, formatAs, decimals, existingField, availableFields, onSave, onClose])\n\n // Handle overlay click\n const handleOverlayClick = useCallback((e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose()\n }\n }, [onClose])\n\n if (!show)\n return null\n\n const modalContent = (\n <div className=\"vpg-modal-overlay\" onClick={handleOverlayClick}>\n <div className=\"vpg-modal\">\n <div className=\"vpg-modal-header\">\n <h3>\n {existingField ? 'Edit' : 'Create'}\n {' '}\n Calculated Field\n </h3>\n <button className=\"vpg-modal-close\" onClick={onClose}>×</button>\n </div>\n\n <div className=\"vpg-modal-body\">\n {/* Name */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label\">Name</label>\n <input\n type=\"text\"\n className=\"vpg-input\"\n placeholder=\"e.g., Profit Margin %\"\n value={name}\n onChange={e => setName(e.target.value)}\n />\n </div>\n\n {/* Formula */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label\">Formula</label>\n <textarea\n className=\"vpg-textarea\"\n placeholder=\"e.g., revenue / units\"\n rows={2}\n value={formula}\n onChange={e => setFormula(e.target.value)}\n />\n <div className=\"vpg-formula-hint\">Use field names with math operators: + - * / ( )</div>\n {validationError && <div className=\"vpg-error\">{validationError}</div>}\n </div>\n\n {/* Quick Insert: Operators */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label-small\">Operators</label>\n <div className=\"vpg-button-group\">\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('+')}>+</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('-')}>−</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('*')}>×</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('/')}>÷</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('(')}>(</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator(')')}>)</button>\n </div>\n </div>\n\n {/* Quick Insert: Fields (numeric only) */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label-small\">Insert Field</label>\n {availableFields.length > 0\n ? (\n <div className=\"vpg-button-group vpg-field-buttons\">\n {availableFields.map(field => (\n <button\n key={field}\n className=\"vpg-insert-btn vpg-field-btn\"\n onClick={() => insertField(field)}\n >\n {field}\n </button>\n ))}\n </div>\n )\n : (\n <div className=\"vpg-no-fields\">No numeric fields available</div>\n )}\n </div>\n\n {/* Format Options */}\n <div className=\"vpg-form-row\">\n <div className=\"vpg-form-group vpg-form-group-half\">\n <label className=\"vpg-label\">Format As</label>\n <select\n className=\"vpg-select\"\n value={formatAs}\n onChange={e => setFormatAs(e.target.value as 'number' | 'percent' | 'currency')}\n >\n <option value=\"number\">Number</option>\n <option value=\"percent\">Percentage</option>\n <option value=\"currency\">Currency ($)</option>\n </select>\n </div>\n <div className=\"vpg-form-group vpg-form-group-half\">\n <label className=\"vpg-label\">Decimals</label>\n <input\n type=\"number\"\n className=\"vpg-input\"\n min={0}\n max={6}\n value={decimals}\n onChange={e => setDecimals(Number(e.target.value))}\n />\n </div>\n </div>\n\n {/* Error */}\n {error && <div className=\"vpg-error vpg-error-box\">{error}</div>}\n </div>\n\n <div className=\"vpg-modal-footer\">\n <button className=\"vpg-btn vpg-btn-secondary\" onClick={onClose}>Cancel</button>\n <button className=\"vpg-btn vpg-btn-primary\" onClick={handleSave}>\n {existingField ? 'Update' : 'Add'}\n {' '}\n Field\n </button>\n </div>\n </div>\n </div>\n )\n\n // Guard for SSR\n if (typeof document === 'undefined')\n return null\n return createPortal(modalContent, document.body)\n}\n","import type {\n ChartAggregation,\n ChartConfig,\n ChartFieldInfo,\n ChartType,\n} from '@smallwebco/tinypivot-core'\n/**\n * TinyPivot React - Chart Builder Component\n * Drag-and-drop chart configuration with ApexCharts rendering\n */\nimport type { ApexOptions } from 'apexcharts'\nimport {\n analyzeFieldsForChart,\n CHART_AGGREGATIONS,\n CHART_COLORS,\n CHART_TYPES,\n createDefaultChartConfig,\n getChartGuidance,\n isChartConfigValid,\n processChartData,\n processChartDataForHeatmap,\n processChartDataForPie,\n processChartDataForScatter,\n} from '@smallwebco/tinypivot-core'\nimport React, { Suspense, useCallback, useEffect, useMemo, useState } from 'react'\n\n// Lazy load ApexCharts to avoid SSR issues (window not defined in Node.js)\nconst Chart = React.lazy(() => import('react-apexcharts'))\n\ninterface ChartBuilderProps {\n data: Record<string, unknown>[]\n theme?: 'light' | 'dark'\n onConfigChange?: (config: ChartConfig) => void\n}\n\nexport function ChartBuilder({\n data,\n theme = 'light',\n onConfigChange,\n}: ChartBuilderProps) {\n // Chart configuration state\n const [chartConfig, setChartConfig] = useState<ChartConfig>(createDefaultChartConfig())\n\n // Drag state\n const [draggingField, setDraggingField] = useState<ChartFieldInfo | null>(null)\n const [dragOverZone, setDragOverZone] = useState<string | null>(null)\n\n // Field analysis\n const fieldInfos = useMemo(() => analyzeFieldsForChart(data), [data])\n\n // Separate fields by role\n const dimensions = useMemo(\n () => fieldInfos.filter(f => f.role === 'dimension' || f.role === 'temporal'),\n [fieldInfos],\n )\n const measures = useMemo(\n () => fieldInfos.filter(f => f.role === 'measure'),\n [fieldInfos],\n )\n\n // Current guidance message\n const guidance = useMemo(() => getChartGuidance(chartConfig), [chartConfig])\n\n // Check if chart is ready to render\n const chartIsValid = useMemo(() => isChartConfigValid(chartConfig), [chartConfig])\n\n // Get currently selected chart type info\n const selectedChartType = useMemo(\n () => CHART_TYPES.find(ct => ct.type === chartConfig.type),\n [chartConfig.type],\n )\n\n // Check if scatter/bubble needs numeric fields\n const isScatterType = useMemo(\n () => ['scatter', 'bubble'].includes(chartConfig.type),\n [chartConfig.type],\n )\n const isHeatmapType = useMemo(\n () => chartConfig.type === 'heatmap',\n [chartConfig.type],\n )\n\n // Dynamic zone labels based on chart type\n const zoneLabels = useMemo(() => {\n const type = chartConfig.type\n switch (type) {\n case 'scatter':\n case 'bubble':\n return {\n xAxis: 'X-Axis (measure)',\n xAxisPlaceholder: 'Drop a measure',\n yAxis: 'Y-Axis (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: 'Color by (optional)',\n seriesPlaceholder: 'Group points by dimension',\n showSize: type === 'bubble',\n showSeries: true,\n }\n case 'heatmap':\n return {\n xAxis: 'X-Axis (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Y-Axis (dimension)',\n yAxisPlaceholder: 'Drop a dimension',\n series: 'Value / Intensity',\n seriesPlaceholder: 'Drop a measure for color intensity',\n showSize: false,\n showSeries: true,\n }\n case 'pie':\n case 'donut':\n return {\n xAxis: 'Slices (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Values (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: '',\n seriesPlaceholder: '',\n showSize: false,\n showSeries: false,\n }\n case 'radar':\n return {\n xAxis: 'Axes (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Values (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: 'Compare by (optional)',\n seriesPlaceholder: 'Group by dimension',\n showSize: false,\n showSeries: true,\n }\n default: // bar, line, area\n return {\n xAxis: 'X-Axis (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Y-Axis (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: 'Color / Series (optional)',\n seriesPlaceholder: 'Group by dimension',\n showSize: false,\n showSeries: true,\n }\n }\n }, [chartConfig.type])\n\n // Drag handlers\n const handleDragStart = useCallback((field: ChartFieldInfo, event: React.DragEvent) => {\n setDraggingField(field)\n event.dataTransfer?.setData('text/plain', field.field)\n }, [])\n\n const handleDragEnd = useCallback(() => {\n setDraggingField(null)\n setDragOverZone(null)\n }, [])\n\n const handleDragOver = useCallback((zone: string, event: React.DragEvent) => {\n event.preventDefault()\n setDragOverZone(zone)\n }, [])\n\n const handleDragLeave = useCallback(() => {\n setDragOverZone(null)\n }, [])\n\n const handleDrop = useCallback((zone: string, event: React.DragEvent) => {\n event.preventDefault()\n setDragOverZone(null)\n\n if (!draggingField)\n return\n\n const field = draggingField\n const chartField = {\n field: field.field,\n label: field.label,\n role: field.role,\n aggregation: field.role === 'measure' ? 'sum' as ChartAggregation : undefined,\n }\n\n let newConfig = { ...chartConfig }\n switch (zone) {\n case 'xAxis':\n newConfig = { ...newConfig, xAxis: chartField }\n break\n case 'yAxis':\n newConfig = { ...newConfig, yAxis: chartField }\n break\n case 'series':\n newConfig = { ...newConfig, seriesField: chartField }\n break\n case 'size':\n newConfig = { ...newConfig, sizeField: chartField }\n break\n case 'color':\n newConfig = { ...newConfig, colorField: chartField }\n break\n }\n\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, draggingField, onConfigChange])\n\n const removeField = useCallback((zone: string) => {\n let newConfig = { ...chartConfig }\n switch (zone) {\n case 'xAxis':\n newConfig = { ...newConfig, xAxis: undefined }\n break\n case 'yAxis':\n newConfig = { ...newConfig, yAxis: undefined }\n break\n case 'series':\n newConfig = { ...newConfig, seriesField: undefined }\n break\n case 'size':\n newConfig = { ...newConfig, sizeField: undefined }\n break\n case 'color':\n newConfig = { ...newConfig, colorField: undefined }\n break\n }\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, onConfigChange])\n\n const selectChartType = useCallback((type: ChartType) => {\n const newConfig = { ...chartConfig, type }\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, onConfigChange])\n\n const updateAggregation = useCallback((zone: string, aggregation: ChartAggregation) => {\n let field\n switch (zone) {\n case 'xAxis':\n field = chartConfig.xAxis\n break\n case 'yAxis':\n field = chartConfig.yAxis\n break\n case 'size':\n field = chartConfig.sizeField\n break\n case 'color':\n field = chartConfig.colorField\n break\n default:\n return\n }\n if (!field)\n return\n\n const updated = { ...field, aggregation }\n let newConfig = { ...chartConfig }\n switch (zone) {\n case 'xAxis':\n newConfig = { ...newConfig, xAxis: updated }\n break\n case 'yAxis':\n newConfig = { ...newConfig, yAxis: updated }\n break\n case 'size':\n newConfig = { ...newConfig, sizeField: updated }\n break\n case 'color':\n newConfig = { ...newConfig, colorField: updated }\n break\n }\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, onConfigChange])\n\n // Chart rendering helpers\n type ApexChartType = 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'heatmap' | 'bubble'\n\n const getApexChartType = useCallback((type: ChartType): ApexChartType => {\n const mapping: Record<ChartType, ApexChartType> = {\n bar: 'bar',\n line: 'line',\n area: 'area',\n pie: 'pie',\n donut: 'donut',\n radar: 'radar',\n scatter: 'scatter',\n bubble: 'bubble',\n heatmap: 'heatmap',\n }\n return mapping[type] || 'bar'\n }, [])\n\n const formatValue = useCallback((val: unknown, format?: string, decimals?: number): string => {\n // Handle non-number values (ApexCharts sometimes passes strings or undefined)\n if (val === null || val === undefined)\n return ''\n if (typeof val !== 'number')\n return String(val)\n if (Number.isNaN(val))\n return ''\n\n const dec = decimals ?? 0\n if (format === 'percent') {\n return `${val.toFixed(dec)}%`\n }\n if (format === 'currency') {\n return `$${val.toLocaleString(undefined, { minimumFractionDigits: dec, maximumFractionDigits: dec })}`\n }\n if (Math.abs(val) >= 1000) {\n return val.toLocaleString(undefined, { maximumFractionDigits: dec })\n }\n return val.toFixed(dec)\n }, [])\n\n // Chart options\n const chartOptions = useMemo<ApexOptions>(() => {\n const isDark = theme === 'dark'\n const config = chartConfig\n const options = config.options || {}\n\n const baseOptions: ApexOptions = {\n chart: {\n type: getApexChartType(config.type),\n background: 'transparent',\n foreColor: isDark ? '#e2e8f0' : '#334155',\n toolbar: {\n show: true,\n tools: {\n download: true,\n selection: false,\n zoom: options.enableZoom ?? false,\n zoomin: options.enableZoom ?? false,\n zoomout: options.enableZoom ?? false,\n pan: false,\n reset: options.enableZoom ?? false,\n },\n export: {\n csv: { filename: 'chart-data' },\n svg: { filename: 'chart' },\n png: { filename: 'chart' },\n },\n },\n animations: {\n enabled: options.animated ?? true,\n speed: 400,\n dynamicAnimation: { enabled: true, speed: 300 },\n },\n fontFamily: 'system-ui, -apple-system, sans-serif',\n },\n colors: options.colors || CHART_COLORS,\n theme: {\n mode: isDark ? 'dark' : 'light',\n },\n grid: {\n show: options.showGrid ?? true,\n borderColor: isDark ? '#334155' : '#e2e8f0',\n },\n legend: {\n show: options.showLegend ?? true,\n position: options.legendPosition || 'top',\n },\n dataLabels: {\n enabled: options.showDataLabels ?? false,\n },\n tooltip: {\n theme: isDark ? 'dark' : 'light',\n style: {\n fontSize: '12px',\n },\n },\n stroke: {\n curve: 'smooth',\n width: config.type === 'line' ? 3 : config.type === 'area' ? 2 : 0,\n },\n fill: {\n opacity: config.type === 'area' ? 0.4 : 1,\n },\n }\n\n // Add axis titles\n if (config.xAxis) {\n baseOptions.xaxis = {\n ...baseOptions.xaxis,\n title: { text: options.xAxisTitle || config.xAxis.label },\n labels: {\n style: { colors: isDark ? '#94a3b8' : '#64748b' },\n },\n }\n }\n\n if (config.yAxis && !['pie', 'donut', 'radar'].includes(config.type)) {\n baseOptions.yaxis = {\n title: { text: options.yAxisTitle || config.yAxis.label },\n labels: {\n style: { colors: isDark ? '#94a3b8' : '#64748b' },\n formatter: (val: number) => formatValue(val, options.valueFormat, options.decimals),\n },\n }\n }\n\n // Chart title\n if (options.title) {\n baseOptions.title = {\n text: options.title,\n style: {\n fontSize: '16px',\n fontWeight: '600',\n color: isDark ? '#e2e8f0' : '#334155',\n },\n }\n }\n\n // Stacking\n if (options.stacked && ['bar', 'area'].includes(config.type)) {\n baseOptions.chart!.stacked = true\n }\n\n // Pie/Donut specific\n if (config.type === 'pie' || config.type === 'donut') {\n baseOptions.plotOptions = {\n pie: {\n donut: {\n size: config.type === 'donut' ? '55%' : '0%',\n labels: {\n show: config.type === 'donut',\n total: {\n show: true,\n label: 'Total',\n formatter: (w) => {\n const total = w.globals.seriesTotals.reduce((a: number, b: number) => a + b, 0)\n return formatValue(total, options.valueFormat, options.decimals)\n },\n },\n },\n },\n },\n }\n }\n\n // Radar specific\n if (config.type === 'radar') {\n baseOptions.plotOptions = {\n radar: {\n polygons: {\n strokeColors: isDark ? '#334155' : '#e2e8f0',\n fill: { colors: isDark ? ['#1e293b', '#0f172a'] : ['#f8fafc', '#f1f5f9'] },\n },\n },\n }\n }\n\n return baseOptions\n }, [chartConfig, theme, getApexChartType, formatValue])\n\n const chartSeries = useMemo(() => {\n const config = chartConfig\n\n if (!chartIsValid)\n return []\n\n // Process based on chart type\n if (config.type === 'pie' || config.type === 'donut') {\n const chartData = processChartDataForPie(data, config)\n return chartData.series[0]?.data || []\n }\n\n if (config.type === 'scatter' || config.type === 'bubble') {\n const scatterData = processChartDataForScatter(data, config)\n return scatterData.series\n }\n\n if (config.type === 'heatmap') {\n const heatmapData = processChartDataForHeatmap(data, config)\n return heatmapData.series\n }\n\n // Standard charts (bar, line, area, etc.)\n const chartData = processChartData(data, config)\n return chartData.series\n }, [data, chartConfig, chartIsValid])\n\n const chartLabels = useMemo(() => {\n const config = chartConfig\n\n if (!chartIsValid)\n return []\n\n if (config.type === 'pie' || config.type === 'donut') {\n const chartData = processChartDataForPie(data, config)\n return chartData.categories\n }\n\n const chartData = processChartData(data, config)\n return chartData.categories\n }, [data, chartConfig, chartIsValid])\n\n // Update xaxis categories in options\n const chartOptionsWithCategories = useMemo<ApexOptions>(() => {\n const options = { ...chartOptions }\n const config = chartConfig\n\n // Heatmap, scatter, bubble have x values in data itself\n if (!['pie', 'donut', 'scatter', 'bubble', 'heatmap'].includes(config.type)) {\n options.xaxis = {\n ...options.xaxis,\n categories: chartLabels,\n }\n }\n\n if (config.type === 'pie' || config.type === 'donut') {\n options.labels = chartLabels\n }\n\n // Heatmap specific options\n if (config.type === 'heatmap') {\n options.chart = {\n ...options.chart,\n type: 'heatmap',\n }\n options.xaxis = {\n ...options.xaxis,\n type: 'category',\n }\n options.dataLabels = {\n enabled: true,\n style: {\n colors: ['#fff'],\n fontSize: '10px',\n },\n formatter: (val: unknown) => {\n if (val === null || val === undefined)\n return ''\n if (typeof val !== 'number')\n return String(val)\n if (val >= 1000000)\n return `${(val / 1000000).toFixed(1)}M`\n if (val >= 1000)\n return `${(val / 1000).toFixed(0)}K`\n return Math.round(val).toLocaleString()\n },\n }\n options.plotOptions = {\n heatmap: {\n shadeIntensity: 0.5,\n radius: 2,\n enableShades: true,\n colorScale: {\n inverse: false,\n },\n },\n }\n // Use a single color that varies by intensity\n options.colors = ['#6366f1']\n // Disable legend for heatmap (color scale is self-explanatory)\n options.legend = { show: false }\n }\n\n return options\n }, [chartOptions, chartConfig, chartLabels])\n\n // Icons for chart types (inline SVG paths)\n const getChartIcon = useCallback((type: ChartType): string => {\n const icons: Record<ChartType, string> = {\n bar: 'M3 3v18h18V3H3zm4 14H5v-6h2v6zm4 0H9V7h2v10zm4 0h-2V9h2v8zm4 0h-2v-4h2v4z',\n line: 'M3.5 18.5l6-6 4 4 8-8M14.5 8.5h6v6',\n area: 'M3 17l6-6 4 4 8-8v10H3z',\n pie: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8v8l5.66 5.66C14.28 19.04 13.18 20 12 20z',\n donut: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z',\n scatter: 'M7 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm-3 4a2 2 0 1 0 0-4 2 2 0 0 0 0 4z',\n bubble: 'M7 14a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm5-5a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z',\n heatmap: 'M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z',\n radar: 'M12 2L4 6v6c0 5.55 3.84 10.74 8 12 4.16-1.26 8-6.45 8-12V6l-8-4zm0 3.18l6 3v5.09c0 4.08-2.76 7.91-6 9.14V5.18z',\n }\n return icons[type] || icons.bar\n }, [])\n\n // Emit initial config on mount\n useEffect(() => {\n onConfigChange?.(chartConfig)\n // Only run on mount - intentionally not including dependencies\n }, [])\n\n return (\n <div className=\"vpg-chart-builder\">\n {/* Chart Type Selector */}\n <div className=\"vpg-chart-type-bar\">\n {CHART_TYPES.map(ct => (\n <button\n key={ct.type}\n className={`vpg-chart-type-btn ${chartConfig.type === ct.type ? 'active' : ''}`}\n title={ct.description}\n onClick={() => selectChartType(ct.type)}\n >\n <svg className=\"vpg-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d={getChartIcon(ct.type)} />\n </svg>\n <span className=\"vpg-chart-type-label\">{ct.label.replace(' Chart', '')}</span>\n </button>\n ))}\n </div>\n\n <div className=\"vpg-chart-builder-content\">\n {/* Field Lists */}\n <div className=\"vpg-chart-fields-panel\">\n <div className=\"vpg-chart-fields-section\">\n <h4 className=\"vpg-chart-fields-title\">\n <svg className=\"vpg-icon-sm\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M4 6h16M4 12h10M4 18h6\" />\n </svg>\n Dimensions\n <span className=\"vpg-chart-fields-hint\">(text/date)</span>\n </h4>\n <div className=\"vpg-chart-fields-list\">\n {dimensions.map(field => (\n <div\n key={field.field}\n className=\"vpg-chart-field-chip vpg-field-dimension\"\n draggable\n onDragStart={e => handleDragStart(field, e)}\n onDragEnd={handleDragEnd}\n >\n <span className=\"vpg-field-name\">{field.label}</span>\n <span className=\"vpg-field-type\">{field.role === 'temporal' ? 'date' : 'text'}</span>\n </div>\n ))}\n {dimensions.length === 0 && (\n <div className=\"vpg-chart-fields-empty\">\n No dimension fields detected\n </div>\n )}\n </div>\n </div>\n\n <div className=\"vpg-chart-fields-section\">\n <h4 className=\"vpg-chart-fields-title\">\n <svg className=\"vpg-icon-sm\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M16 8v8M12 11v5M8 14v2M4 4v16h16\" />\n </svg>\n Measures\n <span className=\"vpg-chart-fields-hint\">(numbers)</span>\n </h4>\n <div className=\"vpg-chart-fields-list\">\n {measures.map(field => (\n <div\n key={field.field}\n className=\"vpg-chart-field-chip vpg-field-measure\"\n draggable\n onDragStart={e => handleDragStart(field, e)}\n onDragEnd={handleDragEnd}\n >\n <span className=\"vpg-field-name\">{field.label}</span>\n <span className=\"vpg-field-type\">#</span>\n </div>\n ))}\n {measures.length === 0 && (\n <div className=\"vpg-chart-fields-empty\">\n No numeric fields detected\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Drop Zones */}\n <div className=\"vpg-chart-config-panel\">\n {/* X-Axis */}\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">{zoneLabels.xAxis}</label>\n <div\n className={`vpg-chart-drop-zone ${dragOverZone === 'xAxis' ? 'drag-over' : ''} ${chartConfig.xAxis ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver('xAxis', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('xAxis', e)}\n >\n {chartConfig.xAxis\n ? (\n <>\n <span className=\"vpg-zone-field-name\">{chartConfig.xAxis.label}</span>\n {isScatterType && chartConfig.xAxis.role === 'measure' && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.xAxis.aggregation || 'sum'}\n onChange={e => updateAggregation('xAxis', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField('xAxis')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">{zoneLabels.xAxisPlaceholder}</span>\n )}\n </div>\n </div>\n\n {/* Y-Axis */}\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">{zoneLabels.yAxis}</label>\n <div\n className={`vpg-chart-drop-zone ${dragOverZone === 'yAxis' ? 'drag-over' : ''} ${chartConfig.yAxis ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver('yAxis', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('yAxis', e)}\n >\n {chartConfig.yAxis\n ? (\n <>\n <span className=\"vpg-zone-field-name\">{chartConfig.yAxis.label}</span>\n {chartConfig.yAxis.role === 'measure' && !isHeatmapType && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.yAxis.aggregation || 'sum'}\n onChange={e => updateAggregation('yAxis', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField('yAxis')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">{zoneLabels.yAxisPlaceholder}</span>\n )}\n </div>\n </div>\n\n {/* Series / Color (conditional) */}\n {zoneLabels.showSeries && (\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">{zoneLabels.series}</label>\n <div\n className={`vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === 'series' ? 'drag-over' : ''} ${(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver(isHeatmapType ? 'color' : 'series', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop(isHeatmapType ? 'color' : 'series', e)}\n >\n {(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField)\n ? (\n <>\n <span className=\"vpg-zone-field-name\">\n {isHeatmapType ? chartConfig.colorField?.label : chartConfig.seriesField?.label}\n </span>\n {isHeatmapType && chartConfig.colorField?.role === 'measure' && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.colorField?.aggregation || 'sum'}\n onChange={e => updateAggregation('color', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField(isHeatmapType ? 'color' : 'series')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">{zoneLabels.seriesPlaceholder}</span>\n )}\n </div>\n </div>\n )}\n\n {/* Size (for bubble charts) */}\n {zoneLabels.showSize && (\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">Size (number)</label>\n <div\n className={`vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === 'size' ? 'drag-over' : ''} ${chartConfig.sizeField ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver('size', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('size', e)}\n >\n {chartConfig.sizeField\n ? (\n <>\n <span className=\"vpg-zone-field-name\">{chartConfig.sizeField.label}</span>\n {chartConfig.sizeField.role === 'measure' && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.sizeField.aggregation || 'sum'}\n onChange={e => updateAggregation('size', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField('size')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">Drop a number for bubble size</span>\n )}\n </div>\n </div>\n )}\n\n {/* Guidance */}\n <div className=\"vpg-chart-guidance\">\n <svg className=\"vpg-icon-sm\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4M12 8h.01\" />\n </svg>\n <span>{guidance}</span>\n </div>\n </div>\n\n {/* Chart Preview */}\n <div className=\"vpg-chart-preview-panel\">\n {chartIsValid\n ? (\n <div className=\"vpg-chart-container\">\n <Suspense fallback={(\n <div className=\"vpg-chart-loading\">\n <div className=\"vpg-chart-spinner\" />\n <span>Loading chart...</span>\n </div>\n )}\n >\n <Chart\n key={`${chartConfig.type}-${JSON.stringify(chartConfig.xAxis)}-${JSON.stringify(chartConfig.yAxis)}`}\n type={getApexChartType(chartConfig.type)}\n options={chartOptionsWithCategories}\n series={chartSeries}\n height=\"100%\"\n />\n </Suspense>\n </div>\n )\n : (\n <div className=\"vpg-chart-empty-state\">\n <svg className=\"vpg-icon-lg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d={getChartIcon(chartConfig.type)} />\n </svg>\n <h3>Build your chart</h3>\n <p>Drag fields from the left panel to configure your visualization</p>\n <div className=\"vpg-chart-hint\">\n <strong>{selectedChartType?.label}</strong>\n :\n {' '}\n {selectedChartType?.description}\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import type { ColumnStats, NumericRange } from '@smallwebco/tinypivot-core'\n/**\n * Column Filter Dropdown Component for React\n * Shows unique values with checkboxes, search, and sort controls\n * For numeric columns, also provides a range filter option\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { NumericRangeFilter } from './NumericRangeFilter'\n\ntype FilterMode = 'values' | 'range'\n\ninterface ColumnFilterProps {\n columnId: string\n columnName: string\n stats: ColumnStats\n selectedValues: string[]\n sortDirection: 'asc' | 'desc' | null\n /** Current numeric range filter (if any) */\n numericRange?: NumericRange | null\n onFilter: (values: string[]) => void\n onSort: (direction: 'asc' | 'desc' | null) => void\n onClose: () => void\n /** Called when a numeric range filter is applied */\n onRangeFilter?: (range: NumericRange | null) => void\n}\n\nexport function ColumnFilter({\n columnName,\n stats,\n selectedValues,\n sortDirection,\n numericRange,\n onFilter,\n onSort,\n onClose,\n onRangeFilter,\n}: ColumnFilterProps) {\n const [searchQuery, setSearchQuery] = useState('')\n const [localSelected, setLocalSelected] = useState<Set<string>>(new Set(selectedValues))\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Filter mode (values vs range) - only available for numeric columns\n const isNumericColumn = stats.type === 'number'\n && stats.numericMin !== undefined\n && stats.numericMax !== undefined\n\n // Determine initial mode based on existing filters\n const [filterMode, setFilterMode] = useState<FilterMode>(numericRange ? 'range' : 'values')\n\n // Local range for the numeric filter\n const [localRange, setLocalRange] = useState<NumericRange | null>(numericRange ?? null)\n\n // Include blank option if there are null values\n const hasBlankValues = stats.nullCount > 0\n\n // Filtered unique values based on search\n const filteredValues = useMemo(() => {\n const values = stats.uniqueValues\n if (!searchQuery)\n return values\n\n const query = searchQuery.toLowerCase()\n return values.filter(v => v.toLowerCase().includes(query))\n }, [stats.uniqueValues, searchQuery])\n\n // All values including blank\n const allValues = useMemo(() => {\n const values = [...filteredValues]\n if (hasBlankValues && (!searchQuery || '(blank)'.includes(searchQuery.toLowerCase()))) {\n values.unshift('(blank)')\n }\n return values\n }, [filteredValues, hasBlankValues, searchQuery])\n\n // Check states (kept for potential future use)\n const _isAllSelected = useMemo(\n () => allValues.every(v => localSelected.has(v)),\n [allValues, localSelected],\n )\n\n // Toggle single value\n const toggleValue = useCallback((value: string) => {\n setLocalSelected((prev) => {\n const next = new Set(prev)\n if (next.has(value)) {\n next.delete(value)\n }\n else {\n next.add(value)\n }\n return next\n })\n }, [])\n\n // Select all visible\n const selectAll = useCallback(() => {\n setLocalSelected((prev) => {\n const next = new Set(prev)\n for (const value of allValues) {\n next.add(value)\n }\n return next\n })\n }, [allValues])\n\n // Clear all\n const clearAll = useCallback(() => {\n setLocalSelected(new Set())\n }, [])\n\n // Apply filter\n const applyFilter = useCallback(() => {\n if (localSelected.size === 0) {\n onFilter([])\n }\n else {\n onFilter(Array.from(localSelected))\n }\n onClose()\n }, [localSelected, onFilter, onClose])\n\n // Sort handlers\n const sortAscending = useCallback(() => {\n onSort(sortDirection === 'asc' ? null : 'asc')\n }, [sortDirection, onSort])\n\n const sortDescending = useCallback(() => {\n onSort(sortDirection === 'desc' ? null : 'desc')\n }, [sortDirection, onSort])\n\n // Clear filter only\n const clearFilter = useCallback(() => {\n setLocalSelected(new Set())\n onFilter([])\n onClose()\n }, [onFilter, onClose])\n\n // Handle range filter change from the NumericRangeFilter component\n const handleRangeChange = useCallback((range: NumericRange | null) => {\n setLocalRange(range)\n }, [])\n\n // Apply the range filter\n const applyRangeFilter = useCallback(() => {\n onRangeFilter?.(localRange)\n onClose()\n }, [localRange, onRangeFilter, onClose])\n\n // Clear range filter\n const clearRangeFilter = useCallback(() => {\n setLocalRange(null)\n onRangeFilter?.(null)\n onClose()\n }, [onRangeFilter, onClose])\n\n // Click outside handler\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n onClose()\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [onClose])\n\n // Keyboard handling\n useEffect(() => {\n const handleKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose()\n }\n else if (event.key === 'Enter' && event.ctrlKey) {\n applyFilter()\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n return () => document.removeEventListener('keydown', handleKeydown)\n }, [onClose, applyFilter])\n\n // Focus search on mount\n useEffect(() => {\n searchInputRef.current?.focus()\n }, [])\n\n // Sync with props\n useEffect(() => {\n setLocalSelected(new Set(selectedValues))\n }, [selectedValues])\n\n // Sync numeric range with props\n useEffect(() => {\n setLocalRange(numericRange ?? null)\n if (numericRange) {\n setFilterMode('range')\n }\n }, [numericRange])\n\n return (\n <div ref={dropdownRef} className=\"vpg-filter-dropdown\">\n {/* Header */}\n <div className=\"vpg-filter-header\">\n <span className=\"vpg-filter-title\">{columnName}</span>\n <span className=\"vpg-filter-count\">\n {stats.uniqueValues.length.toLocaleString()}\n {' '}\n unique\n </span>\n </div>\n\n {/* Sort Controls */}\n <div className=\"vpg-sort-controls\">\n <button\n className={`vpg-sort-btn ${sortDirection === 'asc' ? 'active' : ''}`}\n title={isNumericColumn ? 'Sort Low to High' : 'Sort A to Z'}\n onClick={sortAscending}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12\"\n />\n </svg>\n <span>{isNumericColumn ? '1→9' : 'A→Z'}</span>\n </button>\n <button\n className={`vpg-sort-btn ${sortDirection === 'desc' ? 'active' : ''}`}\n title={isNumericColumn ? 'Sort High to Low' : 'Sort Z to A'}\n onClick={sortDescending}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4\"\n />\n </svg>\n <span>{isNumericColumn ? '9→1' : 'Z→A'}</span>\n </button>\n </div>\n\n <div className=\"vpg-divider\" />\n\n {/* Filter Mode Tabs (only for numeric columns) */}\n {isNumericColumn && (\n <div className=\"vpg-filter-tabs\">\n <button\n className={`vpg-tab-btn ${filterMode === 'values' ? 'active' : ''}`}\n onClick={() => setFilterMode('values')}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"\n />\n </svg>\n Values\n </button>\n <button\n className={`vpg-tab-btn ${filterMode === 'range' ? 'active' : ''}`}\n onClick={() => setFilterMode('range')}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01\"\n />\n </svg>\n Range\n </button>\n </div>\n )}\n\n {/* Values Filter Mode */}\n {(!isNumericColumn || filterMode === 'values') && (\n <>\n {/* Search */}\n <div className=\"vpg-search-container\">\n <svg className=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n placeholder=\"Search values...\"\n className=\"vpg-search-input\"\n />\n {searchQuery && (\n <button className=\"vpg-clear-search\" onClick={() => setSearchQuery('')}>\n ×\n </button>\n )}\n </div>\n\n {/* Select All / Clear All */}\n <div className=\"vpg-bulk-actions\">\n <button className=\"vpg-bulk-btn\" onClick={selectAll}>\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Select All\n </button>\n <button className=\"vpg-bulk-btn\" onClick={clearAll}>\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Clear All\n </button>\n </div>\n\n {/* Values List */}\n <div className=\"vpg-values-list\">\n {allValues.map(value => (\n <label\n key={value}\n className={`vpg-value-item ${localSelected.has(value) ? 'selected' : ''}`}\n >\n <input\n type=\"checkbox\"\n checked={localSelected.has(value)}\n onChange={() => toggleValue(value)}\n className=\"vpg-value-checkbox\"\n />\n <span className={`vpg-value-text ${value === '(blank)' ? 'vpg-blank' : ''}`}>\n {value}\n </span>\n </label>\n ))}\n\n {allValues.length === 0 && <div className=\"vpg-no-results\">No matching values</div>}\n </div>\n\n {/* Footer for Values Mode */}\n <div className=\"vpg-filter-footer\">\n <button className=\"vpg-btn-clear\" onClick={clearFilter}>\n Clear Filter\n </button>\n <button className=\"vpg-btn-apply\" onClick={applyFilter}>\n Apply\n </button>\n </div>\n </>\n )}\n\n {/* Range Filter Mode */}\n {isNumericColumn && filterMode === 'range' && (\n <>\n <NumericRangeFilter\n dataMin={stats.numericMin!}\n dataMax={stats.numericMax!}\n currentRange={localRange}\n onChange={handleRangeChange}\n />\n\n {/* Footer for Range Mode */}\n <div className=\"vpg-filter-footer\">\n <button className=\"vpg-btn-clear\" onClick={clearRangeFilter}>\n Clear Filter\n </button>\n <button className=\"vpg-btn-apply\" onClick={applyRangeFilter}>\n Apply\n </button>\n </div>\n </>\n )}\n </div>\n )\n}\n","import type { NumericRange } from '@smallwebco/tinypivot-core'\n/**\n * Numeric Range Filter Component for React\n * Provides an intuitive dual-handle slider and input fields for filtering numeric data\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\n\ninterface NumericRangeFilterProps {\n dataMin: number\n dataMax: number\n currentRange: NumericRange | null\n onChange: (range: NumericRange | null) => void\n}\n\nexport function NumericRangeFilter({\n dataMin,\n dataMax,\n currentRange,\n onChange,\n}: NumericRangeFilterProps) {\n // Local state for the range values\n const [localMin, setLocalMin] = useState<number | null>(currentRange?.min ?? null)\n const [localMax, setLocalMax] = useState<number | null>(currentRange?.max ?? null)\n\n // Calculate step based on data range\n const step = useMemo(() => {\n const range = dataMax - dataMin\n if (range === 0)\n return 1\n if (range <= 1)\n return 0.01\n if (range <= 10)\n return 0.1\n if (range <= 100)\n return 1\n if (range <= 1000)\n return 10\n return 10 ** (Math.floor(Math.log10(range)) - 2)\n }, [dataMin, dataMax])\n\n // Format numbers for display\n const formatValue = useCallback((val: number | null): string => {\n if (val === null)\n return ''\n if (Number.isInteger(val))\n return val.toLocaleString()\n return val.toLocaleString(undefined, { maximumFractionDigits: 2 })\n }, [])\n\n // Check if filter is active\n const isFilterActive = localMin !== null || localMax !== null\n\n // Calculate slider percentages for visual representation\n const minPercent = useMemo(() => {\n if (localMin === null || dataMax === dataMin)\n return 0\n return ((localMin - dataMin) / (dataMax - dataMin)) * 100\n }, [localMin, dataMin, dataMax])\n\n const maxPercent = useMemo(() => {\n if (localMax === null || dataMax === dataMin)\n return 100\n return ((localMax - dataMin) / (dataMax - dataMin)) * 100\n }, [localMax, dataMin, dataMax])\n\n // Handle min slider change\n const handleMinSlider = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = Number.parseFloat(event.target.value)\n setLocalMin(() => {\n // Ensure min doesn't exceed max\n if (localMax !== null && value > localMax) {\n return localMax\n }\n return value\n })\n }, [localMax])\n\n // Handle max slider change\n const handleMaxSlider = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = Number.parseFloat(event.target.value)\n setLocalMax(() => {\n // Ensure max doesn't go below min\n if (localMin !== null && value < localMin) {\n return localMin\n }\n return value\n })\n }, [localMin])\n\n // Handle slider change complete (emit change)\n const handleSliderChange = useCallback(() => {\n if (localMin === null && localMax === null) {\n onChange(null)\n }\n else {\n onChange({ min: localMin, max: localMax })\n }\n }, [localMin, localMax, onChange])\n\n // Handle min input change\n const handleMinInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value === '' ? null : Number.parseFloat(event.target.value)\n if (value !== null && !Number.isNaN(value)) {\n // Clamp to data bounds\n setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)))\n }\n else if (value === null) {\n setLocalMin(null)\n }\n }, [dataMin, dataMax, localMax])\n\n // Handle max input change\n const handleMaxInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value === '' ? null : Number.parseFloat(event.target.value)\n if (value !== null && !Number.isNaN(value)) {\n // Clamp to data bounds\n setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)))\n }\n else if (value === null) {\n setLocalMax(null)\n }\n }, [dataMin, dataMax, localMin])\n\n // Handle input blur (emit change)\n const handleInputBlur = useCallback(() => {\n if (localMin === null && localMax === null) {\n onChange(null)\n }\n else {\n onChange({ min: localMin, max: localMax })\n }\n }, [localMin, localMax, onChange])\n\n // Clear the filter\n const clearFilter = useCallback(() => {\n setLocalMin(null)\n setLocalMax(null)\n onChange(null)\n }, [onChange])\n\n // Set to full range\n const setFullRange = useCallback(() => {\n setLocalMin(dataMin)\n setLocalMax(dataMax)\n onChange({ min: dataMin, max: dataMax })\n }, [dataMin, dataMax, onChange])\n\n // Sync with props\n useEffect(() => {\n setLocalMin(currentRange?.min ?? null)\n setLocalMax(currentRange?.max ?? null)\n }, [currentRange])\n\n return (\n <div className=\"vpg-range-filter\">\n {/* Data range info */}\n <div className=\"vpg-range-info\">\n <span className=\"vpg-range-label\">Data range:</span>\n <span className=\"vpg-range-bounds\">\n {formatValue(dataMin)}\n {' '}\n –\n {formatValue(dataMax)}\n </span>\n </div>\n\n {/* Dual slider track */}\n <div className=\"vpg-slider-container\">\n <div className=\"vpg-slider-track\">\n <div\n className=\"vpg-slider-fill\"\n style={{\n left: `${minPercent}%`,\n right: `${100 - maxPercent}%`,\n }}\n />\n </div>\n\n {/* Min slider (lower handle) */}\n <input\n type=\"range\"\n className=\"vpg-slider vpg-slider-min\"\n min={dataMin}\n max={dataMax}\n step={step}\n value={localMin ?? dataMin}\n onChange={handleMinSlider}\n onMouseUp={handleSliderChange}\n onTouchEnd={handleSliderChange}\n />\n\n {/* Max slider (upper handle) */}\n <input\n type=\"range\"\n className=\"vpg-slider vpg-slider-max\"\n min={dataMin}\n max={dataMax}\n step={step}\n value={localMax ?? dataMax}\n onChange={handleMaxSlider}\n onMouseUp={handleSliderChange}\n onTouchEnd={handleSliderChange}\n />\n </div>\n\n {/* Input fields for precise entry */}\n <div className=\"vpg-range-inputs\">\n <div className=\"vpg-input-group\">\n <label className=\"vpg-input-label\">Min</label>\n <input\n type=\"number\"\n className=\"vpg-range-input\"\n placeholder={formatValue(dataMin)}\n value={localMin ?? ''}\n step={step}\n onChange={handleMinInput}\n onBlur={handleInputBlur}\n />\n </div>\n <span className=\"vpg-input-separator\">to</span>\n <div className=\"vpg-input-group\">\n <label className=\"vpg-input-label\">Max</label>\n <input\n type=\"number\"\n className=\"vpg-range-input\"\n placeholder={formatValue(dataMax)}\n value={localMax ?? ''}\n step={step}\n onChange={handleMaxInput}\n onBlur={handleInputBlur}\n />\n </div>\n </div>\n\n {/* Quick actions */}\n <div className=\"vpg-range-actions\">\n <button\n className=\"vpg-range-btn\"\n disabled={!isFilterActive}\n onClick={clearFilter}\n >\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Clear\n </button>\n <button className=\"vpg-range-btn\" onClick={setFullRange}>\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4\"\n />\n </svg>\n Full Range\n </button>\n </div>\n\n {/* Current filter display */}\n {isFilterActive && (\n <div className=\"vpg-filter-summary\">\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n <span>\n Showing values\n {' '}\n {localMin !== null && (\n <strong>\n ≥\n {formatValue(localMin)}\n </strong>\n )}\n {localMin !== null && localMax !== null && ' and '}\n {localMax !== null && (\n <strong>\n ≤\n {formatValue(localMax)}\n </strong>\n )}\n </span>\n </div>\n )}\n </div>\n )\n}\n","/**\n * TinyPivot React - Main DataGrid Component\n * Excel-like data grid with optional pivot table functionality\n */\nimport type {\n AIAnalystConfig,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIErrorEvent,\n AIQueryExecutedEvent,\n ChartConfig,\n} from '@smallwebco/tinypivot-core'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useExcelGrid } from '../hooks/useExcelGrid'\nimport {\n copyToClipboard,\n exportPivotToCSV,\n exportToCSV,\n formatSelectionForClipboard,\n} from '../hooks/useGridFeatures'\nimport { useLicense } from '../hooks/useLicense'\nimport { usePivotTable } from '../hooks/usePivotTable'\nimport { AIAnalyst, type AIAnalystHandle } from './AIAnalyst'\nimport { ChartBuilder } from './ChartBuilder'\nimport { ColumnFilter } from './ColumnFilter'\nimport { PivotConfig } from './PivotConfig'\nimport { PivotSkeleton } from './PivotSkeleton'\n\n// Re-export AI types for public API\nexport type { AIAnalystConfig, AIConversationUpdateEvent, AIDataLoadedEvent, AIErrorEvent, AIQueryExecutedEvent }\n\ninterface DataGridProps {\n data: Record<string, unknown>[]\n loading?: boolean\n rowHeight?: number\n headerHeight?: number\n fontSize?: 'xs' | 'sm' | 'base'\n showPivot?: boolean\n enableExport?: boolean\n enableSearch?: boolean\n enablePagination?: boolean\n pageSize?: number\n enableColumnResize?: boolean\n enableClipboard?: boolean\n theme?: 'light' | 'dark' | 'auto'\n stripedRows?: boolean\n exportFilename?: string\n enableVerticalResize?: boolean\n initialHeight?: number\n minHeight?: number\n maxHeight?: number\n /** AI Data Analyst configuration (Pro feature, disabled by default) */\n aiAnalyst?: AIAnalystConfig\n onCellClick?: (payload: {\n row: number\n col: number\n value: unknown\n rowData: Record<string, unknown>\n }) => void\n onSelectionChange?: (payload: { cells: Array<{ row: number, col: number }>, values: unknown[] }) => void\n onExport?: (payload: { rowCount: number, filename: string }) => void\n onCopy?: (payload: { text: string, cellCount: number }) => void\n // AI Analyst events\n onAIDataLoaded?: (payload: AIDataLoadedEvent) => void\n onAIConversationUpdate?: (payload: AIConversationUpdateEvent) => void\n onAIQueryExecuted?: (payload: AIQueryExecutedEvent) => void\n onAIError?: (payload: AIErrorEvent) => void\n}\n\nconst MIN_COL_WIDTH = 120\nconst MAX_COL_WIDTH = 350\n\nexport function DataGrid({\n data,\n loading = false,\n fontSize: initialFontSize = 'xs',\n showPivot = true,\n enableExport = true,\n enableSearch = true,\n enablePagination = false,\n pageSize = 50,\n enableColumnResize = true,\n enableClipboard = true,\n theme = 'light',\n stripedRows = true,\n exportFilename = 'data-export.csv',\n enableVerticalResize = true,\n initialHeight = 600,\n minHeight = 300,\n maxHeight = 1200,\n aiAnalyst,\n onCellClick,\n onExport,\n onCopy,\n onAIDataLoaded,\n onAIConversationUpdate,\n onAIQueryExecuted,\n onAIError,\n}: DataGridProps) {\n const { showWatermark, canUsePivot, canUseCharts, canUseAIAnalyst, isDemo, isPro } = useLicense()\n\n // Check if AI Analyst should be shown (enabled in config + licensed)\n const showAIAnalyst = aiAnalyst?.enabled && canUseAIAnalyst\n\n // Theme handling\n const currentTheme = useMemo(() => {\n if (theme === 'auto') {\n return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n return theme\n }, [theme])\n\n // State\n const [currentFontSize, setCurrentFontSize] = useState(initialFontSize)\n const [globalSearchTerm, setGlobalSearchTerm] = useState('')\n const [showSearchInput, setShowSearchInput] = useState(false)\n const [currentPage, setCurrentPage] = useState(1)\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>({})\n const [resizingColumnId, setResizingColumnId] = useState<string | null>(null)\n const [resizeStartX, setResizeStartX] = useState(0)\n const [resizeStartWidth, setResizeStartWidth] = useState(0)\n const [gridHeight, setGridHeight] = useState(initialHeight)\n const [isResizingVertically, setIsResizingVertically] = useState(false)\n const [verticalResizeStartY, setVerticalResizeStartY] = useState(0)\n const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState(0)\n const [showCopyToast, setShowCopyToast] = useState(false)\n const [copyToastMessage, setCopyToastMessage] = useState('')\n const [viewMode, setViewMode] = useState<'ai' | 'grid' | 'pivot' | 'chart'>('grid')\n\n // AI Analyst ref (for accessing loadFullData)\n const aiAnalystRef = useRef<AIAnalystHandle>(null)\n\n // AI-loaded data (replaces current data when AI loads results)\n const [aiLoadedData, setAiLoadedData] = useState<Record<string, unknown>[] | null>(null)\n\n // Loading state for full data reset\n const [isLoadingFullData, setIsLoadingFullData] = useState(false)\n\n // Data to display - AI loaded data takes precedence\n const displayData = useMemo(() => aiLoadedData || data, [aiLoadedData, data])\n const [_chartConfig, setChartConfig] = useState<ChartConfig | null>(null)\n\n const handleChartConfigChange = useCallback((config: ChartConfig) => {\n setChartConfig(config)\n }, [])\n const [showPivotConfig, setShowPivotConfig] = useState(true)\n const [draggingField, setDraggingField] = useState<string | null>(null)\n const [activeFilterColumn, setActiveFilterColumn] = useState<string | null>(null)\n const [filterDropdownPosition, setFilterDropdownPosition] = useState({ top: 0, left: 0, maxHeight: 400 })\n const [selectedCell, setSelectedCell] = useState<{ row: number, col: number } | null>(null)\n const [selectionStart, setSelectionStart] = useState<{ row: number, col: number } | null>(null)\n const [selectionEnd, setSelectionEnd] = useState<{ row: number, col: number } | null>(null)\n const [isSelecting, setIsSelecting] = useState(false)\n\n const tableContainerRef = useRef<HTMLDivElement>(null)\n const tableBodyRef = useRef<HTMLTableSectionElement>(null)\n\n const fontSizeOptions = [\n { value: 'xs' as const, label: 'S' },\n { value: 'sm' as const, label: 'M' },\n { value: 'base' as const, label: 'L' },\n ]\n\n // Grid composable\n const {\n table,\n columnKeys,\n filteredRowCount,\n totalRowCount,\n getColumnStats,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n columnFilters,\n activeFilters,\n // Numeric range filters\n setNumericRangeFilter,\n getNumericRangeFilter,\n } = useExcelGrid({ data: displayData, enableSorting: true, enableFiltering: true })\n\n // Filtered data for pivot table\n const filteredDataForPivot = useMemo(() => {\n const filteredRows = table.getFilteredRowModel().rows\n return filteredRows.map(row => row.original)\n }, [table, columnFilters])\n\n // Pivot table composable\n const {\n rowFields: pivotRowFields,\n columnFields: pivotColumnFields,\n valueFields: pivotValueFields,\n showRowTotals: pivotShowRowTotals,\n showColumnTotals: pivotShowColumnTotals,\n calculatedFields: pivotCalculatedFields,\n availableFields: pivotAvailableFields,\n isConfigured: pivotIsConfigured,\n pivotResult,\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig: clearPivotConfig,\n autoSuggestConfig,\n setShowRowTotals: setPivotShowRowTotals,\n setShowColumnTotals: setPivotShowColumnTotals,\n setRowFields,\n setColumnFields,\n addCalculatedField,\n removeCalculatedField,\n } = usePivotTable(filteredDataForPivot)\n\n // Active filters info for display\n const activeFilterInfo = useMemo(() => {\n if (activeFilters.length === 0)\n return null\n return activeFilters.map((f) => {\n if (f.type === 'range' && f.range) {\n // Format range filter display\n const parts = []\n if (f.range.min !== null)\n parts.push(`≥ ${f.range.min}`)\n if (f.range.max !== null)\n parts.push(`≤ ${f.range.max}`)\n return {\n column: f.column,\n valueCount: 1,\n displayText: parts.join(' and '),\n isRange: true,\n }\n }\n return {\n column: f.column,\n valueCount: f.values?.length || 0,\n values: f.values || [],\n isRange: false,\n }\n })\n }, [activeFilters])\n\n // Rows - depends on columnFilters to recompute when filters change\n const rows = useMemo(() => table.getFilteredRowModel().rows, [table, columnFilters])\n\n // Filtered data based on global search\n const searchFilteredData = useMemo(() => {\n if (!globalSearchTerm.trim() || !enableSearch) {\n return rows\n }\n const term = globalSearchTerm.toLowerCase().trim()\n return rows.filter((row) => {\n for (const col of columnKeys) {\n const value = row.original[col]\n if (value === null || value === undefined)\n continue\n if (String(value).toLowerCase().includes(term)) {\n return true\n }\n }\n return false\n })\n }, [rows, globalSearchTerm, enableSearch, columnKeys])\n\n // Paginated rows\n const totalSearchedRows = searchFilteredData.length\n const totalPages = useMemo(() => {\n if (!enablePagination)\n return 1\n return Math.max(1, Math.ceil(totalSearchedRows / pageSize))\n }, [enablePagination, totalSearchedRows, pageSize])\n\n const paginatedRows = useMemo(() => {\n if (!enablePagination)\n return searchFilteredData\n const start = (currentPage - 1) * pageSize\n const end = start + pageSize\n return searchFilteredData.slice(start, end)\n }, [enablePagination, searchFilteredData, currentPage, pageSize])\n\n // Reset to page 1 when filters or search changes\n useEffect(() => {\n setCurrentPage(1)\n }, [columnFilters, globalSearchTerm])\n\n // Selection bounds\n const selectionBounds = useMemo(() => {\n if (!selectionStart || !selectionEnd)\n return null\n return {\n minRow: Math.min(selectionStart.row, selectionEnd.row),\n maxRow: Math.max(selectionStart.row, selectionEnd.row),\n minCol: Math.min(selectionStart.col, selectionEnd.col),\n maxCol: Math.max(selectionStart.col, selectionEnd.col),\n }\n }, [selectionStart, selectionEnd])\n\n // Selection stats\n const selectionStats = useMemo(() => {\n if (!selectionBounds)\n return null\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n\n const values: number[] = []\n let count = 0\n\n for (let r = minRow; r <= maxRow; r++) {\n const row = rows[r]\n if (!row)\n continue\n\n for (let c = minCol; c <= maxCol; c++) {\n const colId = columnKeys[c]\n if (!colId)\n continue\n\n const value = row.original[colId]\n count++\n\n if (value !== null && value !== undefined && value !== '') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (!Number.isNaN(num)) {\n values.push(num)\n }\n }\n }\n }\n\n if (values.length === 0)\n return { count, sum: null, avg: null, numericCount: 0 }\n\n const sum = values.reduce((a, b) => a + b, 0)\n const avg = sum / values.length\n\n return { count, sum, avg, numericCount: values.length }\n }, [selectionBounds, rows, columnKeys])\n\n // Calculate column widths\n useEffect(() => {\n // Skip during SSR (no document available)\n if (typeof document === 'undefined')\n return\n if (displayData.length === 0)\n return\n\n const widths: Record<string, number> = {}\n const sampleSize = Math.min(100, displayData.length)\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n\n ctx.font = '13px system-ui, -apple-system, sans-serif'\n\n for (const key of columnKeys) {\n let maxWidth = ctx.measureText(key).width + 56\n\n for (let i = 0; i < sampleSize; i++) {\n const value = displayData[i][key]\n const text = value === null || value === undefined ? '' : String(value)\n const width = ctx.measureText(text).width + 28\n maxWidth = Math.max(maxWidth, width)\n }\n\n widths[key] = Math.min(Math.max(maxWidth, MIN_COL_WIDTH), MAX_COL_WIDTH)\n }\n\n setColumnWidths(widths)\n }, [displayData, columnKeys])\n\n // Column resize handlers\n const startColumnResize = useCallback(\n (columnId: string, event: React.MouseEvent) => {\n if (!enableColumnResize)\n return\n event.preventDefault()\n event.stopPropagation()\n\n setResizingColumnId(columnId)\n setResizeStartX(event.clientX)\n setResizeStartWidth(columnWidths[columnId] || MIN_COL_WIDTH)\n },\n [enableColumnResize, columnWidths],\n )\n\n useEffect(() => {\n if (!resizingColumnId)\n return\n\n const handleResizeMove = (event: MouseEvent) => {\n const diff = event.clientX - resizeStartX\n const newWidth = Math.max(MIN_COL_WIDTH, Math.min(MAX_COL_WIDTH, resizeStartWidth + diff))\n setColumnWidths(prev => ({\n ...prev,\n [resizingColumnId]: newWidth,\n }))\n }\n\n const handleResizeEnd = () => {\n setResizingColumnId(null)\n }\n\n document.addEventListener('mousemove', handleResizeMove)\n document.addEventListener('mouseup', handleResizeEnd)\n return () => {\n document.removeEventListener('mousemove', handleResizeMove)\n document.removeEventListener('mouseup', handleResizeEnd)\n }\n }, [resizingColumnId, resizeStartX, resizeStartWidth])\n\n // Vertical resize handlers\n const startVerticalResize = useCallback(\n (event: React.MouseEvent) => {\n if (!enableVerticalResize)\n return\n event.preventDefault()\n\n setIsResizingVertically(true)\n setVerticalResizeStartY(event.clientY)\n setVerticalResizeStartHeight(gridHeight)\n },\n [enableVerticalResize, gridHeight],\n )\n\n useEffect(() => {\n if (!isResizingVertically)\n return\n\n const handleVerticalResizeMove = (event: MouseEvent) => {\n const diff = event.clientY - verticalResizeStartY\n const newHeight = Math.max(minHeight, Math.min(maxHeight, verticalResizeStartHeight + diff))\n setGridHeight(newHeight)\n }\n\n const handleVerticalResizeEnd = () => {\n setIsResizingVertically(false)\n }\n\n document.addEventListener('mousemove', handleVerticalResizeMove)\n document.addEventListener('mouseup', handleVerticalResizeEnd)\n return () => {\n document.removeEventListener('mousemove', handleVerticalResizeMove)\n document.removeEventListener('mouseup', handleVerticalResizeEnd)\n }\n }, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight])\n\n // Export handlers\n const handleExport = useCallback(() => {\n if (viewMode === 'pivot') {\n if (!pivotResult)\n return\n\n const pivotFilename = exportFilename.replace('.csv', '-pivot.csv')\n exportPivotToCSV(\n {\n headers: pivotResult.headers,\n rowHeaders: pivotResult.rowHeaders,\n data: pivotResult.data,\n rowTotals: pivotResult.rowTotals,\n columnTotals: pivotResult.columnTotals,\n grandTotal: pivotResult.grandTotal,\n showRowTotals: pivotShowRowTotals,\n showColumnTotals: pivotShowColumnTotals,\n },\n pivotRowFields,\n pivotColumnFields,\n pivotValueFields,\n { filename: pivotFilename },\n )\n\n onExport?.({ rowCount: pivotResult.rowHeaders.length, filename: pivotFilename })\n return\n }\n\n const dataToExport\n = enableSearch && globalSearchTerm.trim()\n ? searchFilteredData.map(row => row.original)\n : rows.map(row => row.original)\n\n exportToCSV(dataToExport, columnKeys, {\n filename: exportFilename,\n includeHeaders: true,\n })\n\n onExport?.({ rowCount: dataToExport.length, filename: exportFilename })\n }, [\n viewMode,\n pivotResult,\n exportFilename,\n pivotShowRowTotals,\n pivotShowColumnTotals,\n pivotRowFields,\n pivotColumnFields,\n pivotValueFields,\n enableSearch,\n globalSearchTerm,\n searchFilteredData,\n rows,\n columnKeys,\n onExport,\n ])\n\n // Copy to clipboard\n const copySelectionToClipboard = useCallback(() => {\n if (!selectionBounds || !enableClipboard)\n return\n\n const text = formatSelectionForClipboard(\n rows.map(r => r.original),\n columnKeys,\n selectionBounds,\n )\n\n copyToClipboard(\n text,\n () => {\n const cellCount\n = (selectionBounds.maxRow - selectionBounds.minRow + 1)\n * (selectionBounds.maxCol - selectionBounds.minCol + 1)\n setCopyToastMessage(`Copied ${cellCount} cell${cellCount > 1 ? 's' : ''}`)\n setShowCopyToast(true)\n setTimeout(() => setShowCopyToast(false), 2000)\n onCopy?.({ text, cellCount })\n },\n (err) => {\n setCopyToastMessage('Copy failed')\n setShowCopyToast(true)\n setTimeout(() => setShowCopyToast(false), 2000)\n console.error('Copy failed:', err)\n },\n )\n }, [selectionBounds, enableClipboard, rows, columnKeys, onCopy])\n\n // Cell selection handlers\n const handleMouseDown = useCallback(\n (rowIndex: number, colIndex: number, event: React.MouseEvent) => {\n event.preventDefault()\n\n if (event.shiftKey && selectedCell) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n else {\n setSelectedCell({ row: rowIndex, col: colIndex })\n setSelectionStart({ row: rowIndex, col: colIndex })\n setSelectionEnd({ row: rowIndex, col: colIndex })\n setIsSelecting(true)\n }\n\n const row = rows[rowIndex]\n if (row) {\n const colId = columnKeys[colIndex]\n onCellClick?.({\n row: rowIndex,\n col: colIndex,\n value: row.original[colId],\n rowData: row.original,\n })\n }\n },\n [selectedCell, rows, columnKeys, onCellClick],\n )\n\n const handleMouseEnter = useCallback(\n (rowIndex: number, colIndex: number) => {\n if (isSelecting) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n },\n [isSelecting],\n )\n\n // Track if we're showing AI-shaped data (filtered/aggregated by AI queries)\n const isShowingAIData = aiLoadedData !== null\n\n // Reset to full original dataset\n // If AI Analyst is enabled and has a selected data source, load full data from that source\n // Otherwise, just clear the AI loaded data to show original props.data\n const resetToFullData = useCallback(async () => {\n // If we have AI Analyst with a selected data source, load full data from it\n if (aiAnalystRef.current?.selectedDataSource) {\n setIsLoadingFullData(true)\n try {\n const fullData = await aiAnalystRef.current.loadFullData()\n if (fullData && fullData.length > 0) {\n setAiLoadedData(fullData)\n }\n else {\n // Fall back to props.data if loading fails\n setAiLoadedData(null)\n }\n }\n catch (err) {\n console.warn('Failed to load full data:', err)\n setAiLoadedData(null)\n }\n finally {\n setIsLoadingFullData(false)\n }\n }\n else {\n // No AI Analyst or no selected data source - just clear filters by resetting to props.data\n setAiLoadedData(null)\n }\n // Also clear any grid filters\n clearAllFilters()\n }, [clearAllFilters])\n\n // AI Analyst event handlers\n const handleAIDataLoaded = useCallback(\n (payload: AIDataLoadedEvent) => {\n setAiLoadedData(payload.data)\n // Don't auto-switch to grid - let user decide when to view results\n onAIDataLoaded?.(payload)\n },\n [onAIDataLoaded],\n )\n\n const handleAIConversationUpdate = useCallback(\n (payload: AIConversationUpdateEvent) => {\n onAIConversationUpdate?.(payload)\n },\n [onAIConversationUpdate],\n )\n\n const handleAIQueryExecuted = useCallback(\n (payload: AIQueryExecutedEvent) => {\n onAIQueryExecuted?.(payload)\n },\n [onAIQueryExecuted],\n )\n\n const handleAIError = useCallback(\n (payload: AIErrorEvent) => {\n onAIError?.(payload)\n },\n [onAIError],\n )\n\n useEffect(() => {\n const handleMouseUp = () => setIsSelecting(false)\n document.addEventListener('mouseup', handleMouseUp)\n return () => document.removeEventListener('mouseup', handleMouseUp)\n }, [])\n\n // Keyboard handling\n useEffect(() => {\n const handleKeydown = (event: KeyboardEvent) => {\n // Handle Ctrl+C / Cmd+C for clipboard\n if ((event.ctrlKey || event.metaKey) && event.key === 'c' && selectionBounds) {\n event.preventDefault()\n copySelectionToClipboard()\n return\n }\n\n // Handle Escape\n if (event.key === 'Escape') {\n setSelectedCell(null)\n setSelectionStart(null)\n setSelectionEnd(null)\n setShowSearchInput(false)\n setGlobalSearchTerm('')\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n return () => document.removeEventListener('keydown', handleKeydown)\n }, [selectionBounds, copySelectionToClipboard])\n\n // Filter dropdown\n const openFilterDropdown = useCallback(\n (columnId: string, event: React.MouseEvent) => {\n event.stopPropagation()\n const target = event.currentTarget as HTMLElement\n const headerCell = target.closest('.vpg-header-cell') as HTMLElement\n const rect = headerCell?.getBoundingClientRect() || target.getBoundingClientRect()\n\n const dropdownWidth = 280\n const padding = 12\n\n let left = rect.left\n if (left + dropdownWidth > window.innerWidth - padding) {\n left = window.innerWidth - dropdownWidth - padding\n }\n left = Math.max(padding, left)\n\n const spaceBelow = window.innerHeight - rect.bottom - padding\n const spaceAbove = rect.top - padding\n\n let top: number\n let maxDropdownHeight: number\n\n if (spaceBelow >= 300 || spaceBelow >= spaceAbove) {\n top = rect.bottom + 4\n maxDropdownHeight = Math.min(400, spaceBelow - 4)\n }\n else {\n maxDropdownHeight = Math.min(400, spaceAbove - 4)\n top = rect.top - maxDropdownHeight - 4\n }\n\n setFilterDropdownPosition({ top, left, maxHeight: maxDropdownHeight })\n setActiveFilterColumn(columnId)\n },\n [],\n )\n\n const closeFilterDropdown = useCallback(() => {\n setActiveFilterColumn(null)\n }, [])\n\n const handleFilter = useCallback(\n (columnId: string, values: string[]) => {\n setColumnFilter(columnId, values)\n },\n [setColumnFilter],\n )\n\n const handleRangeFilter = useCallback(\n (columnId: string, range: import('@smallwebco/tinypivot-core').NumericRange | null) => {\n setNumericRangeFilter(columnId, range)\n },\n [setNumericRangeFilter],\n )\n\n const handleSort = useCallback(\n (columnId: string, direction: 'asc' | 'desc' | null) => {\n if (direction === null) {\n const current = getSortDirection(columnId)\n if (current) {\n toggleSort(columnId)\n if (getSortDirection(columnId)) {\n toggleSort(columnId)\n }\n }\n }\n else {\n const current = getSortDirection(columnId)\n if (current === null) {\n toggleSort(columnId)\n if (direction === 'desc' && getSortDirection(columnId) === 'asc') {\n toggleSort(columnId)\n }\n }\n else if (current !== direction) {\n toggleSort(columnId)\n }\n }\n },\n [getSortDirection, toggleSort],\n )\n\n const isCellSelected = useCallback(\n (rowIndex: number, colIndex: number): boolean => {\n if (!selectionBounds) {\n return selectedCell?.row === rowIndex && selectedCell?.col === colIndex\n }\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol\n },\n [selectionBounds, selectedCell],\n )\n\n const formatStatValue = (value: number | null): string => {\n if (value === null)\n return '-'\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n return value.toLocaleString('en-US', { maximumFractionDigits: 4 })\n }\n\n // Format cell value\n const noFormatPatterns\n = /^(?:.*_)?(?:id|code|year|month|quarter|day|week|date|zip|phone|fax|ssn|ein|npi|ndc|gpi|hcpcs|icd|cpt|rx|bin|pcn|group|member|claim|rx_number|script|fill)(?:_.*)?$/i\n\n const shouldFormatNumber = (columnId: string): boolean => {\n return !noFormatPatterns.test(columnId)\n }\n\n const formatCellValueDisplay = (value: unknown, columnId: string): string => {\n if (value === null || value === undefined)\n return ''\n if (value === '')\n return ''\n\n const stats = getColumnStats(columnId)\n if (stats.type === 'number') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (Number.isNaN(num))\n return String(value)\n\n if (shouldFormatNumber(columnId) && Math.abs(num) >= 1000) {\n return num.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n\n if (Number.isInteger(num)) {\n return String(num)\n }\n return num.toLocaleString('en-US', { maximumFractionDigits: 4, useGrouping: false })\n }\n\n return String(value)\n }\n\n const totalTableWidth = useMemo(() => {\n return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0)\n }, [columnKeys, columnWidths])\n\n const activeFilterCount = columnFilters.length\n\n return (\n <div\n className={`vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? 'vpg-striped' : ''} ${resizingColumnId ? 'vpg-resizing' : ''} ${isResizingVertically ? 'vpg-resizing-vertical' : ''}`}\n style={{ height: `${gridHeight}px` }}\n >\n {/* Copy Toast */}\n {showCopyToast && (\n <div className=\"vpg-toast\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n {copyToastMessage}\n </div>\n )}\n\n {/* Toolbar */}\n <div className=\"vpg-toolbar\">\n <div className=\"vpg-toolbar-left\">\n {/* View mode toggle */}\n {showPivot && (\n <div className=\"vpg-view-toggle\">\n {/* AI Analyst button (first, only if enabled) */}\n {showAIAnalyst && (\n <button\n className={`vpg-view-btn vpg-ai-btn ${viewMode === 'ai' ? 'active' : ''}`}\n onClick={() => setViewMode('ai')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z\" />\n </svg>\n AI Analyst\n </button>\n )}\n {aiAnalyst?.enabled && !canUseAIAnalyst && (\n <button\n className=\"vpg-view-btn vpg-ai-btn vpg-pro-feature\"\n title=\"AI Analyst (Pro feature)\"\n onClick={e => e.preventDefault()}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z\" />\n </svg>\n AI Analyst\n <span className=\"vpg-pro-badge\">Pro</span>\n </button>\n )}\n <button\n className={`vpg-view-btn ${viewMode === 'grid' ? 'active' : ''}`}\n onClick={() => setViewMode('grid')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n Grid\n </button>\n <button\n className={`vpg-view-btn vpg-pivot-btn ${viewMode === 'pivot' ? 'active' : ''}`}\n onClick={() => setViewMode('pivot')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n Pivot\n </button>\n <button\n className={`vpg-view-btn vpg-chart-btn ${viewMode === 'chart' ? 'active' : ''} ${!canUseCharts ? 'vpg-pro-feature' : ''}`}\n title={canUseCharts ? 'Chart Builder' : 'Chart Builder (Pro feature)'}\n onClick={() => canUseCharts && setViewMode('chart')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n Chart\n {!canUseCharts && <span className=\"vpg-pro-badge\">Pro</span>}\n </button>\n </div>\n )}\n\n {/* Grid mode controls */}\n {viewMode === 'grid' && (\n <>\n {/* Search */}\n {enableSearch && (\n <div className=\"vpg-search-container\">\n {!showSearchInput\n ? (\n <button\n className=\"vpg-icon-btn\"\n title=\"Search (Ctrl+F)\"\n onClick={() => setShowSearchInput(true)}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n </button>\n )\n : (\n <div className=\"vpg-search-box\">\n <svg\n className=\"vpg-search-icon\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <input\n type=\"text\"\n value={globalSearchTerm}\n onChange={e => setGlobalSearchTerm(e.target.value)}\n className=\"vpg-search-input\"\n placeholder=\"Search all columns...\"\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n setShowSearchInput(false)\n setGlobalSearchTerm('')\n }\n }}\n autoFocus\n />\n {globalSearchTerm && (\n <button className=\"vpg-search-clear\" onClick={() => setGlobalSearchTerm('')}>\n <svg\n className=\"vpg-icon-xs\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n )}\n </div>\n )}\n\n <div className=\"vpg-font-size-control\">\n <span className=\"vpg-label\">Size:</span>\n <div className=\"vpg-font-size-toggle\">\n {fontSizeOptions.map(opt => (\n <button\n key={opt.value}\n className={`vpg-font-size-btn ${currentFontSize === opt.value ? 'active' : ''}`}\n onClick={() => setCurrentFontSize(opt.value)}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </div>\n\n {activeFilterCount > 0 && (\n <div className=\"vpg-filter-info\">\n <svg className=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span>\n {activeFilterCount}\n {' '}\n filter\n {activeFilterCount > 1 ? 's' : ''}\n </span>\n </div>\n )}\n\n {globalSearchTerm && (\n <div className=\"vpg-search-info\">\n <span>\n {totalSearchedRows}\n {' '}\n match\n {totalSearchedRows !== 1 ? 'es' : ''}\n </span>\n </div>\n )}\n </>\n )}\n\n {/* Pivot mode controls */}\n {viewMode === 'pivot' && canUsePivot && (\n <>\n <button\n className={`vpg-config-toggle ${showPivotConfig ? 'active' : ''}`}\n onClick={() => setShowPivotConfig(!showPivotConfig)}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4\"\n />\n </svg>\n {showPivotConfig ? 'Hide' : 'Show'}\n {' '}\n Config\n </button>\n\n {pivotIsConfigured && (\n <div className=\"vpg-pivot-status\">\n <svg className=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span>Pivot configured</span>\n </div>\n )}\n </>\n )}\n </div>\n\n <div className=\"vpg-toolbar-right\">\n {viewMode === 'grid' && activeFilterCount > 0 && (\n <button className=\"vpg-clear-filters\" onClick={clearAllFilters}>\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Clear Filters\n </button>\n )}\n\n {/* Reset to full data button (when showing AI-filtered results) */}\n {viewMode === 'grid' && isShowingAIData && (\n <button\n className={`vpg-reset-data-btn${isLoadingFullData ? ' vpg-loading-btn' : ''}`}\n disabled={isLoadingFullData}\n title=\"Reset to full dataset\"\n onClick={resetToFullData}\n >\n <svg className={`vpg-icon${isLoadingFullData ? ' vpg-spin' : ''}`} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n <span>{isLoadingFullData ? 'Loading...' : 'Full Data'}</span>\n </button>\n )}\n\n {/* Copy button */}\n {enableClipboard && selectionBounds && viewMode === 'grid' && (\n <button\n className=\"vpg-icon-btn\"\n title=\"Copy selection (Ctrl+C)\"\n onClick={copySelectionToClipboard}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n </button>\n )}\n\n {/* Export button - Grid export is free, Pivot export requires Pro */}\n {enableExport && viewMode === 'grid' && (\n <button\n className=\"vpg-export-btn\"\n title=\"Export to CSV\"\n onClick={handleExport}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n Export\n </button>\n )}\n {enableExport && viewMode === 'pivot' && pivotIsConfigured && (\n <button\n className={`vpg-export-btn ${!isPro ? 'vpg-export-btn-disabled' : ''}`}\n disabled={!isPro}\n title={isPro ? 'Export Pivot to CSV' : 'Export Pivot to CSV (Pro feature)'}\n onClick={() => isPro && handleExport()}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n Export Pivot\n {!isPro ? ' (Pro)' : ''}\n </button>\n )}\n </div>\n </div>\n\n {/* AI Analyst View - always render if enabled, use CSS to hide for state preservation */}\n {showAIAnalyst && aiAnalyst && (\n <div className=\"vpg-ai-view\" style={{ display: viewMode === 'ai' ? undefined : 'none' }}>\n <AIAnalyst\n ref={aiAnalystRef}\n config={aiAnalyst}\n theme={currentTheme}\n onDataLoaded={handleAIDataLoaded}\n onConversationUpdate={handleAIConversationUpdate}\n onQueryExecuted={handleAIQueryExecuted}\n onError={handleAIError}\n />\n </div>\n )}\n\n {/* Grid View */}\n {viewMode === 'grid' && (\n <div ref={tableContainerRef} className=\"vpg-grid-container\" tabIndex={0}>\n {loading && (\n <div className=\"vpg-loading\">\n <div className=\"vpg-spinner\" />\n <span>Loading data...</span>\n </div>\n )}\n\n {!loading && displayData.length === 0 && (\n <div className=\"vpg-empty\">\n <div className=\"vpg-empty-icon\">\n <svg className=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n </div>\n <span>No data available</span>\n </div>\n )}\n\n {!loading && displayData.length > 0 && filteredRowCount === 0 && (\n <div className=\"vpg-empty\">\n <div className=\"vpg-empty-icon vpg-warning\">\n <svg className=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n </div>\n <span>No matching records</span>\n <button className=\"vpg-clear-link\" onClick={clearAllFilters}>\n Clear all filters\n </button>\n </div>\n )}\n\n {!loading && filteredRowCount > 0 && (\n <div className=\"vpg-table-wrapper\">\n <table className=\"vpg-table\" style={{ minWidth: `${totalTableWidth}px` }}>\n <thead>\n <tr>\n {columnKeys.map(colId => (\n <th\n key={colId}\n className={`vpg-header-cell ${hasActiveFilter(colId) ? 'vpg-has-filter' : ''} ${getSortDirection(colId) !== null ? 'vpg-is-sorted' : ''} ${activeFilterColumn === colId ? 'vpg-is-active' : ''}`}\n style={{\n width: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n }}\n onClick={(e) => {\n const target = e.target as HTMLElement\n if (target.closest('.vpg-dropdown-arrow')) {\n openFilterDropdown(colId, e)\n }\n }}\n >\n <div className=\"vpg-header-content\">\n <span className=\"vpg-header-text\">{colId}</span>\n <div className=\"vpg-header-icons\">\n {getSortDirection(colId) && (\n <span className=\"vpg-sort-indicator\">\n {getSortDirection(colId) === 'asc'\n ? (\n <svg\n className=\"vpg-icon-sm\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )\n : (\n <svg\n className=\"vpg-icon-sm\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )}\n </span>\n )}\n {hasActiveFilter(colId) && (\n <span className=\"vpg-filter-indicator\">\n <svg\n className=\"vpg-icon-xs\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </span>\n )}\n <span className=\"vpg-dropdown-arrow\" title=\"Filter & Sort\">\n <svg\n className=\"vpg-icon-sm\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </span>\n </div>\n </div>\n {enableColumnResize && (\n <div\n className=\"vpg-resize-handle\"\n onMouseDown={e => startColumnResize(colId, e)}\n />\n )}\n </th>\n ))}\n </tr>\n </thead>\n\n <tbody ref={tableBodyRef}>\n {paginatedRows.map((row, rowIndex) => (\n <tr key={row.id} className=\"vpg-row\">\n {columnKeys.map((colId, colIndex) => (\n <td\n key={colId}\n className={`vpg-cell ${isCellSelected(rowIndex, colIndex) ? 'vpg-selected' : ''} ${getColumnStats(colId).type === 'number' ? 'vpg-is-number' : ''}`}\n data-row={rowIndex}\n data-col={colIndex}\n style={{\n width: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n }}\n onMouseDown={e => handleMouseDown(rowIndex, colIndex, e)}\n onMouseEnter={() => handleMouseEnter(rowIndex, colIndex)}\n >\n {formatCellValueDisplay(row.original[colId], colId)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* Pivot View */}\n {viewMode === 'pivot' && (\n <div className=\"vpg-pivot-container\">\n {showPivotConfig && canUsePivot && (\n <div className=\"vpg-pivot-config-panel\">\n <PivotConfig\n availableFields={pivotAvailableFields}\n rowFields={pivotRowFields}\n columnFields={pivotColumnFields}\n valueFields={pivotValueFields}\n showRowTotals={pivotShowRowTotals}\n showColumnTotals={pivotShowColumnTotals}\n calculatedFields={pivotCalculatedFields}\n onShowRowTotalsChange={setPivotShowRowTotals}\n onShowColumnTotalsChange={setPivotShowColumnTotals}\n onClearConfig={clearPivotConfig}\n onAutoSuggest={autoSuggestConfig}\n onDragStart={(field, _e) => setDraggingField(field)}\n onDragEnd={() => setDraggingField(null)}\n onUpdateAggregation={updateValueFieldAggregation}\n onAddRowField={addRowField}\n onRemoveRowField={removeRowField}\n onAddColumnField={addColumnField}\n onRemoveColumnField={removeColumnField}\n onAddValueField={addValueField}\n onRemoveValueField={removeValueField}\n onAddCalculatedField={addCalculatedField}\n onRemoveCalculatedField={removeCalculatedField}\n onUpdateCalculatedField={addCalculatedField}\n />\n </div>\n )}\n\n <div className={`vpg-pivot-main ${!showPivotConfig ? 'vpg-full-width' : ''}`}>\n <PivotSkeleton\n rowFields={pivotRowFields}\n columnFields={pivotColumnFields}\n valueFields={pivotValueFields}\n calculatedFields={pivotCalculatedFields}\n isConfigured={pivotIsConfigured}\n draggingField={draggingField}\n pivotResult={pivotResult}\n fontSize={currentFontSize}\n activeFilters={activeFilterInfo}\n totalRowCount={totalRowCount}\n filteredRowCount={filteredRowCount}\n onAddRowField={addRowField}\n onRemoveRowField={removeRowField}\n onAddColumnField={addColumnField}\n onRemoveColumnField={removeColumnField}\n onAddValueField={addValueField}\n onRemoveValueField={removeValueField}\n onUpdateAggregation={updateValueFieldAggregation}\n onReorderRowFields={setRowFields}\n onReorderColumnFields={setColumnFields}\n />\n </div>\n </div>\n )}\n\n {/* Chart View */}\n {viewMode === 'chart' && (\n <div className=\"vpg-chart-view\">\n {/* Filter indicator for chart */}\n {activeFilterInfo && activeFilterInfo.length > 0 && (\n <div className=\"vpg-chart-filter-bar\">\n <svg className=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\" clipRule=\"evenodd\" />\n </svg>\n <span>\n Chart showing\n {filteredRowCount.toLocaleString()}\n {' '}\n of\n {totalRowCount.toLocaleString()}\n {' '}\n records\n </span>\n <button className=\"vpg-chart-clear-filters\" onClick={clearAllFilters}>\n Clear filters\n </button>\n </div>\n )}\n <ChartBuilder\n data={filteredDataForPivot}\n theme={currentTheme}\n onConfigChange={handleChartConfigChange}\n />\n </div>\n )}\n\n {/* Footer */}\n <div className=\"vpg-footer\">\n <div className=\"vpg-footer-left\">\n {viewMode === 'grid'\n ? (\n enablePagination\n ? (\n <>\n <span>\n {((currentPage - 1) * pageSize + 1).toLocaleString()}\n -\n {Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()}\n </span>\n <span className=\"vpg-separator\">of</span>\n <span>{totalSearchedRows.toLocaleString()}</span>\n {totalSearchedRows !== totalRowCount && (\n <span className=\"vpg-filtered-note\">\n (\n {totalRowCount.toLocaleString()}\n {' '}\n total)\n </span>\n )}\n </>\n )\n : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount\n ? (\n <span>\n {totalRowCount.toLocaleString()}\n {' '}\n records\n </span>\n )\n : (\n <>\n <span className=\"vpg-filtered-count\">{totalSearchedRows.toLocaleString()}</span>\n <span className=\"vpg-separator\">of</span>\n <span>{totalRowCount.toLocaleString()}</span>\n <span className=\"vpg-separator\">records</span>\n </>\n )\n )\n : viewMode === 'pivot'\n ? (\n <>\n <span className=\"vpg-pivot-label\">Pivot Table</span>\n <span className=\"vpg-separator\">•</span>\n <span>\n {totalRowCount.toLocaleString()}\n {' '}\n source records\n </span>\n </>\n )\n : (\n <>\n <span className=\"vpg-chart-label\">Chart Builder</span>\n <span className=\"vpg-separator\">•</span>\n <span>\n {totalRowCount.toLocaleString()}\n {' '}\n records\n </span>\n </>\n )}\n </div>\n\n {/* Pagination controls */}\n {enablePagination && viewMode === 'grid' && totalPages > 1 && (\n <div className=\"vpg-pagination\">\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage(1)}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 19l-7-7 7-7m8 14l-7-7 7-7\"\n />\n </svg>\n </button>\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage(p => Math.max(1, p - 1))}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 19l-7-7 7-7\"\n />\n </svg>\n </button>\n <span className=\"vpg-page-info\">\n Page\n {' '}\n {currentPage}\n {' '}\n of\n {' '}\n {totalPages}\n </span>\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === totalPages}\n onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 5l7 7-7 7\"\n />\n </svg>\n </button>\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === totalPages}\n onClick={() => setCurrentPage(totalPages)}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 5l7 7-7 7M5 5l7 7-7 7\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {viewMode === 'grid' && selectionStats && selectionStats.count > 1 && (\n <div className=\"vpg-selection-stats\">\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Count:</span>\n <span className=\"vpg-stat-value\">{selectionStats.count}</span>\n </span>\n {selectionStats.numericCount > 0 && (\n <>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Sum:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.sum)}</span>\n </span>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Avg:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.avg)}</span>\n </span>\n </>\n )}\n </div>\n )}\n\n <div className=\"vpg-footer-right\">\n {isDemo\n ? (\n <div className=\"vpg-demo-banner\">\n <span className=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features enabled</span>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener noreferrer\">\n Get License →\n </a>\n </div>\n )\n : showWatermark\n ? (\n <span className=\"vpg-watermark-inline\">\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener noreferrer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" />\n </svg>\n Powered by TinyPivot\n </a>\n </span>\n )\n : null}\n </div>\n </div>\n\n {/* Vertical Resize Handle */}\n {enableVerticalResize && (\n <div className=\"vpg-vertical-resize-handle\" onMouseDown={startVerticalResize}>\n <div className=\"vpg-resize-grip\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n )}\n\n {/* Filter Dropdown Portal */}\n {activeFilterColumn && typeof document !== 'undefined'\n && createPortal(\n <div\n className=\"vpg-filter-portal\"\n style={{\n position: 'fixed',\n top: `${filterDropdownPosition.top}px`,\n left: `${filterDropdownPosition.left}px`,\n maxHeight: `${filterDropdownPosition.maxHeight}px`,\n zIndex: 9999,\n }}\n >\n <ColumnFilter\n columnId={activeFilterColumn}\n columnName={activeFilterColumn}\n stats={getColumnStats(activeFilterColumn)}\n selectedValues={getColumnFilterValues(activeFilterColumn)}\n sortDirection={getSortDirection(activeFilterColumn)}\n numericRange={getNumericRangeFilter(activeFilterColumn)}\n onFilter={values => handleFilter(activeFilterColumn, values)}\n onRangeFilter={range => handleRangeFilter(activeFilterColumn, range)}\n onSort={dir => handleSort(activeFilterColumn, dir)}\n onClose={closeFilterDropdown}\n />\n </div>,\n document.body,\n )}\n </div>\n )\n}\n","import type { ColumnFilterValue, ColumnStats, NumericRange } from '@smallwebco/tinypivot-core'\nimport { formatCellValue, getColumnUniqueValues, isNumericRange } from '@smallwebco/tinypivot-core'\nimport {\n type ColumnDef,\n type ColumnFiltersState,\n type FilterFn,\n getCoreRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n type SortingState,\n useReactTable,\n type VisibilityState,\n} from '@tanstack/react-table'\n/**\n * Excel-like Grid Hook for React\n * Provides Excel-like filtering, sorting, and data manipulation functionality\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react'\n\n// Re-export for convenience\nexport { formatCellValue, getColumnUniqueValues, isNumericRange }\n\nexport interface ExcelGridOptions<T> {\n data: T[]\n columns?: string[]\n enableSorting?: boolean\n enableFiltering?: boolean\n pageSize?: number\n}\n\n/**\n * Combined filter function for Excel-style filtering and numeric range filtering\n */\nconst multiSelectFilter: FilterFn<unknown> = (row, columnId, filterValue: ColumnFilterValue | undefined) => {\n if (!filterValue)\n return true\n\n // Handle numeric range filter\n if (isNumericRange(filterValue)) {\n const cellValue = row.getValue(columnId)\n if (cellValue === null || cellValue === undefined || cellValue === '') {\n return false // Exclude null/empty values from numeric range filtering\n }\n const num = typeof cellValue === 'number' ? cellValue : Number.parseFloat(String(cellValue))\n if (Number.isNaN(num))\n return false\n\n const { min, max } = filterValue\n if (min !== null && num < min)\n return false\n if (max !== null && num > max)\n return false\n return true\n }\n\n // Handle multi-select array filter\n if (Array.isArray(filterValue) && filterValue.length > 0) {\n const cellValue = row.getValue(columnId)\n const cellString\n = cellValue === null || cellValue === undefined || cellValue === ''\n ? '(blank)'\n : String(cellValue)\n return filterValue.includes(cellString)\n }\n\n return true\n}\n\n/**\n * Excel-like grid hook\n */\nexport function useExcelGrid<T extends Record<string, unknown>>(options: ExcelGridOptions<T>) {\n const { data, enableSorting = true, enableFiltering = true } = options\n\n // State\n const [sorting, setSorting] = useState<SortingState>([])\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])\n const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})\n const [globalFilter, setGlobalFilter] = useState('')\n\n // Column statistics cache\n const [columnStatsCache, setColumnStatsCache] = useState<Record<string, ColumnStats>>({})\n\n const dataSignature = useMemo(\n () => `${Date.now()}-${Math.random().toString(36).slice(2)}`,\n [data],\n )\n\n // Compute columns from data\n const columnKeys = useMemo(() => {\n if (data.length === 0)\n return []\n return Object.keys(data[0] as Record<string, unknown>)\n }, [data])\n\n // Get column stats (memoized)\n const getColumnStats = useCallback(\n (columnKey: string): ColumnStats => {\n const cacheKey = `${columnKey}-${dataSignature}`\n if (!columnStatsCache[cacheKey]) {\n const stats = getColumnUniqueValues(data, columnKey)\n setColumnStatsCache(prev => ({ ...prev, [cacheKey]: stats }))\n return stats\n }\n return columnStatsCache[cacheKey]\n },\n [data, columnStatsCache, dataSignature],\n )\n\n // Clear stats cache\n const clearStatsCache = useCallback(() => {\n setColumnStatsCache({})\n }, [])\n\n useEffect(() => {\n clearStatsCache()\n }, [dataSignature, clearStatsCache])\n\n // Create column definitions dynamically\n const columnDefs = useMemo<ColumnDef<T, unknown>[]>(() => {\n return columnKeys.map((key) => {\n const stats = getColumnStats(key)\n\n return {\n id: key,\n accessorKey: key,\n header: key,\n cell: info => formatCellValue(info.getValue(), stats.type),\n filterFn: multiSelectFilter,\n meta: {\n type: stats.type,\n uniqueCount: stats.uniqueValues.length,\n },\n } as ColumnDef<T, unknown>\n })\n }, [columnKeys, getColumnStats])\n\n // Create table instance\n const table = useReactTable({\n data,\n columns: columnDefs,\n state: {\n sorting,\n columnFilters,\n columnVisibility,\n globalFilter,\n },\n onSortingChange: setSorting,\n onColumnFiltersChange: setColumnFilters,\n onColumnVisibilityChange: setColumnVisibility,\n onGlobalFilterChange: setGlobalFilter,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: enableSorting ? getSortedRowModel() : undefined,\n getFilteredRowModel: enableFiltering ? getFilteredRowModel() : undefined,\n filterFns: {\n multiSelect: multiSelectFilter,\n },\n enableSorting,\n enableFilters: enableFiltering,\n })\n\n // Computed properties\n const filteredRowCount = table.getFilteredRowModel().rows.length\n const totalRowCount = data.length\n\n // Active filters (handles both array values and numeric ranges)\n const activeFilters = useMemo(() => {\n return columnFilters.map((f) => {\n const filterValue = f.value as ColumnFilterValue | undefined\n\n // Handle numeric range\n if (filterValue && isNumericRange(filterValue)) {\n return {\n column: f.id,\n type: 'range' as const,\n range: filterValue,\n values: [] as string[],\n }\n }\n\n // Handle value array\n return {\n column: f.id,\n type: 'values' as const,\n values: Array.isArray(filterValue) ? filterValue : [],\n range: null as NumericRange | null,\n }\n })\n }, [columnFilters])\n\n // Check if column has active filter (handles both array and numeric range)\n const hasActiveFilter = useCallback(\n (columnId: string): boolean => {\n const column = table.getColumn(columnId)\n if (!column)\n return false\n const filterValue = column.getFilterValue() as ColumnFilterValue | undefined\n if (!filterValue)\n return false\n\n // Check for numeric range\n if (isNumericRange(filterValue)) {\n return filterValue.min !== null || filterValue.max !== null\n }\n\n // Check for value array\n return Array.isArray(filterValue) && filterValue.length > 0\n },\n [table],\n )\n\n // Set column filter (value-based)\n const setColumnFilter = useCallback(\n (columnId: string, values: string[]) => {\n const column = table.getColumn(columnId)\n if (column) {\n // Let the table's onColumnFiltersChange handler update the state\n // Do NOT manually call setColumnFilters after - it causes a race condition\n // where the stale state overwrites the pending update\n column.setFilterValue(values.length === 0 ? undefined : values)\n }\n },\n [table],\n )\n\n // Set numeric range filter\n const setNumericRangeFilter = useCallback(\n (columnId: string, range: NumericRange | null) => {\n const column = table.getColumn(columnId)\n if (column) {\n if (!range || (range.min === null && range.max === null)) {\n column.setFilterValue(undefined)\n }\n else {\n column.setFilterValue(range)\n }\n }\n },\n [table],\n )\n\n // Get numeric range filter for a column\n const getNumericRangeFilter = useCallback(\n (columnId: string): NumericRange | null => {\n const column = table.getColumn(columnId)\n if (!column)\n return null\n const filterValue = column.getFilterValue() as ColumnFilterValue | undefined\n if (filterValue && isNumericRange(filterValue)) {\n return filterValue\n }\n return null\n },\n [table],\n )\n\n // Clear all filters\n const clearAllFilters = useCallback(() => {\n table.resetColumnFilters()\n setGlobalFilter('')\n // Force sync columnFilters state\n setColumnFilters([])\n }, [table])\n\n // Get filter values for a specific column\n const getColumnFilterValues = useCallback(\n (columnId: string): string[] => {\n const column = table.getColumn(columnId)\n if (!column)\n return []\n const filterValue = column.getFilterValue()\n return Array.isArray(filterValue) ? filterValue : []\n },\n [table],\n )\n\n // Toggle column sort\n const toggleSort = useCallback((columnId: string) => {\n setSorting((prev) => {\n const current = prev.find(s => s.id === columnId)\n if (!current) {\n return [{ id: columnId, desc: false }]\n }\n else if (!current.desc) {\n return [{ id: columnId, desc: true }]\n }\n else {\n return []\n }\n })\n }, [])\n\n // Get sort direction for column\n const getSortDirection = useCallback(\n (columnId: string): 'asc' | 'desc' | null => {\n const sort = sorting.find(s => s.id === columnId)\n if (!sort)\n return null\n return sort.desc ? 'desc' : 'asc'\n },\n [sorting],\n )\n\n return {\n // Table instance\n table,\n\n // State\n sorting,\n columnFilters,\n columnVisibility,\n globalFilter,\n columnKeys,\n setSorting,\n setColumnFilters,\n setGlobalFilter,\n\n // Computed\n filteredRowCount,\n totalRowCount,\n activeFilters,\n\n // Methods\n getColumnStats,\n clearStatsCache,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n // Numeric range filters\n setNumericRangeFilter,\n getNumericRangeFilter,\n }\n}\n","import type { ExportOptions, PaginationOptions, PivotExportData, PivotValueField, SelectionBounds } from '@smallwebco/tinypivot-core'\nimport {\n copyToClipboard as coreCopyToClipboard,\n exportPivotToCSV as coreExportPivotToCSV,\n exportToCSV as coreExportToCSV,\n formatSelectionForClipboard as coreFormatSelection,\n} from '@smallwebco/tinypivot-core'\n/**\n * Grid Features Hook for React\n * Provides CSV export, clipboard, pagination, and other utility features\n */\nimport { useCallback, useMemo, useState } from 'react'\n\n// Re-export core functions\nexport function exportToCSV<T extends Record<string, unknown>>(\n data: T[],\n columns: string[],\n options?: ExportOptions,\n): void {\n coreExportToCSV(data, columns, options)\n}\n\nexport function exportPivotToCSV(\n pivotData: PivotExportData,\n rowFields: string[],\n columnFields: string[],\n valueFields: PivotValueField[],\n options?: ExportOptions,\n): void {\n coreExportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options)\n}\n\nexport function copyToClipboard(\n text: string,\n onSuccess?: () => void,\n onError?: (err: Error) => void,\n): void {\n coreCopyToClipboard(text, onSuccess, onError)\n}\n\nexport function formatSelectionForClipboard<T extends Record<string, unknown>>(\n rows: T[],\n columns: string[],\n selectionBounds: SelectionBounds,\n): string {\n return coreFormatSelection(rows, columns, selectionBounds)\n}\n\n/**\n * Pagination hook\n */\nexport function usePagination<T>(data: T[], options: PaginationOptions = {}) {\n const [pageSize, setPageSize] = useState(options.pageSize ?? 50)\n const [currentPage, setCurrentPage] = useState(options.currentPage ?? 1)\n\n const totalPages = useMemo(\n () => Math.max(1, Math.ceil(data.length / pageSize)),\n [data.length, pageSize],\n )\n\n const paginatedData = useMemo(() => {\n const start = (currentPage - 1) * pageSize\n const end = start + pageSize\n return data.slice(start, end)\n }, [data, currentPage, pageSize])\n\n const startIndex = useMemo(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize])\n const endIndex = useMemo(\n () => Math.min(currentPage * pageSize, data.length),\n [currentPage, pageSize, data.length],\n )\n\n const goToPage = useCallback(\n (page: number) => {\n setCurrentPage(Math.max(1, Math.min(page, totalPages)))\n },\n [totalPages],\n )\n\n const nextPage = useCallback(() => {\n if (currentPage < totalPages) {\n setCurrentPage(prev => prev + 1)\n }\n }, [currentPage, totalPages])\n\n const prevPage = useCallback(() => {\n if (currentPage > 1) {\n setCurrentPage(prev => prev - 1)\n }\n }, [currentPage])\n\n const firstPage = useCallback(() => {\n setCurrentPage(1)\n }, [])\n\n const lastPage = useCallback(() => {\n setCurrentPage(totalPages)\n }, [totalPages])\n\n const updatePageSize = useCallback((size: number) => {\n setPageSize(size)\n setCurrentPage(1)\n }, [])\n\n return {\n pageSize,\n currentPage,\n totalPages,\n paginatedData,\n startIndex,\n endIndex,\n goToPage,\n nextPage,\n prevPage,\n firstPage,\n lastPage,\n setPageSize: updatePageSize,\n }\n}\n\n/**\n * Global search/filter hook\n */\nexport function useGlobalSearch<T extends Record<string, unknown>>(data: T[], columns: string[]) {\n const [searchTerm, setSearchTerm] = useState('')\n const [caseSensitive, setCaseSensitive] = useState(false)\n\n const filteredData = useMemo(() => {\n if (!searchTerm.trim()) {\n return data\n }\n\n const term = caseSensitive ? searchTerm.trim() : searchTerm.trim().toLowerCase()\n\n return data.filter((row) => {\n for (const col of columns) {\n const value = row[col]\n if (value === null || value === undefined)\n continue\n\n const strValue = caseSensitive ? String(value) : String(value).toLowerCase()\n\n if (strValue.includes(term)) {\n return true\n }\n }\n return false\n })\n }, [data, columns, searchTerm, caseSensitive])\n\n const clearSearch = useCallback(() => {\n setSearchTerm('')\n }, [])\n\n return {\n searchTerm,\n setSearchTerm,\n caseSensitive,\n setCaseSensitive,\n filteredData,\n clearSearch,\n }\n}\n\n/**\n * Row selection hook\n */\nexport function useRowSelection<T>(data: T[]) {\n const [selectedRowIndices, setSelectedRowIndices] = useState<Set<number>>(new Set())\n\n const selectedRows = useMemo(() => {\n return Array.from(selectedRowIndices)\n .sort((a, b) => a - b)\n .map(idx => data[idx])\n .filter(Boolean)\n }, [data, selectedRowIndices])\n\n const allSelected = useMemo(() => {\n return data.length > 0 && selectedRowIndices.size === data.length\n }, [data.length, selectedRowIndices.size])\n\n const someSelected = useMemo(() => {\n return selectedRowIndices.size > 0 && selectedRowIndices.size < data.length\n }, [data.length, selectedRowIndices.size])\n\n const toggleRow = useCallback((index: number) => {\n setSelectedRowIndices((prev) => {\n const next = new Set(prev)\n if (next.has(index)) {\n next.delete(index)\n }\n else {\n next.add(index)\n }\n return next\n })\n }, [])\n\n const selectRow = useCallback((index: number) => {\n setSelectedRowIndices(prev => new Set([...prev, index]))\n }, [])\n\n const deselectRow = useCallback((index: number) => {\n setSelectedRowIndices((prev) => {\n const next = new Set(prev)\n next.delete(index)\n return next\n })\n }, [])\n\n const selectAll = useCallback(() => {\n setSelectedRowIndices(new Set(data.map((_, idx) => idx)))\n }, [data])\n\n const deselectAll = useCallback(() => {\n setSelectedRowIndices(new Set())\n }, [])\n\n const toggleAll = useCallback(() => {\n if (allSelected) {\n deselectAll()\n }\n else {\n selectAll()\n }\n }, [allSelected, selectAll, deselectAll])\n\n const isSelected = useCallback(\n (index: number): boolean => {\n return selectedRowIndices.has(index)\n },\n [selectedRowIndices],\n )\n\n const selectRange = useCallback((startIndex: number, endIndex: number) => {\n const min = Math.min(startIndex, endIndex)\n const max = Math.max(startIndex, endIndex)\n setSelectedRowIndices((prev) => {\n const next = new Set(prev)\n for (let i = min; i <= max; i++) {\n next.add(i)\n }\n return next\n })\n }, [])\n\n return {\n selectedRowIndices,\n selectedRows,\n allSelected,\n someSelected,\n toggleRow,\n selectRow,\n deselectRow,\n selectAll,\n deselectAll,\n toggleAll,\n isSelected,\n selectRange,\n }\n}\n\n/**\n * Column resizing hook\n */\nexport function useColumnResize(\n initialWidths: Record<string, number>,\n minWidth = 60,\n maxWidth = 600,\n) {\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>({ ...initialWidths })\n const [isResizing, setIsResizing] = useState(false)\n const [resizingColumn, setResizingColumn] = useState<string | null>(null)\n\n const startResize = useCallback(\n (columnId: string, event: React.MouseEvent) => {\n setIsResizing(true)\n setResizingColumn(columnId)\n const startX = event.clientX\n const startWidth = columnWidths[columnId] || 150\n\n const handleMouseMove = (e: MouseEvent) => {\n const diff = e.clientX - startX\n const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + diff))\n setColumnWidths(prev => ({\n ...prev,\n [columnId]: newWidth,\n }))\n }\n\n const handleMouseUp = () => {\n setIsResizing(false)\n setResizingColumn(null)\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n },\n [columnWidths, minWidth, maxWidth],\n )\n\n const resetColumnWidth = useCallback(\n (columnId: string) => {\n if (initialWidths[columnId]) {\n setColumnWidths(prev => ({\n ...prev,\n [columnId]: initialWidths[columnId],\n }))\n }\n },\n [initialWidths],\n )\n\n const resetAllWidths = useCallback(() => {\n setColumnWidths({ ...initialWidths })\n }, [initialWidths])\n\n return {\n columnWidths,\n setColumnWidths,\n isResizing,\n resizingColumn,\n startResize,\n resetColumnWidth,\n resetAllWidths,\n }\n}\n","import type { LicenseInfo } from '@smallwebco/tinypivot-core'\nimport {\n canUseAIAnalyst as coreCanUseAIAnalyst,\n canUseCharts as coreCanUseCharts,\n canUsePivot as coreCanUsePivot,\n configureLicenseSecret as coreConfigureLicenseSecret,\n isPro as coreIsPro,\n shouldShowWatermark as coreShouldShowWatermark,\n getDemoLicenseInfo,\n getFreeLicenseInfo,\n logProRequired,\n validateLicenseKey,\n} from '@smallwebco/tinypivot-core'\n/**\n * License Management Hook for React\n * Wraps core license logic with React state management\n */\nimport { useCallback, useMemo, useState } from 'react'\n\n// Global state (shared across all hook instances)\nlet globalLicenseInfo: LicenseInfo = getFreeLicenseInfo()\nlet globalDemoMode = false\nconst listeners = new Set<() => void>()\n\nfunction notifyListeners() {\n listeners.forEach(listener => listener())\n}\n\n/**\n * Set the license key for the library\n */\nexport async function setLicenseKey(key: string): Promise<void> {\n globalLicenseInfo = await validateLicenseKey(key)\n\n if (!globalLicenseInfo.isValid) {\n console.warn('[TinyPivot] License validation failed. Check the console for environment details. Running in free mode.')\n }\n else if (globalLicenseInfo.type !== 'free') {\n console.info(`[TinyPivot] Pro license activated (${globalLicenseInfo.type})`)\n }\n\n notifyListeners()\n}\n\n/**\n * Enable demo mode - requires the correct demo secret\n * Returns true if activation succeeded, false if secret was invalid\n */\nexport async function enableDemoMode(secret: string): Promise<boolean> {\n const demoLicense = await getDemoLicenseInfo(secret)\n if (!demoLicense) {\n console.warn('[TinyPivot] Demo mode activation failed - invalid secret')\n return false\n }\n globalDemoMode = true\n globalLicenseInfo = demoLicense\n console.info('[TinyPivot] Demo mode enabled - all Pro features unlocked for evaluation')\n notifyListeners()\n return true\n}\n\n/**\n * Configure the license secret\n */\nexport function configureLicenseSecret(secret: string): void {\n coreConfigureLicenseSecret(secret)\n}\n\n/**\n * Hook for accessing license information\n */\nexport function useLicense() {\n const [, forceUpdate] = useState({})\n\n // Subscribe to global state changes\n useState(() => {\n const update = () => forceUpdate({})\n listeners.add(update)\n return () => listeners.delete(update)\n })\n\n const isDemo = globalDemoMode\n const licenseInfo = globalLicenseInfo\n\n const isPro = useMemo(\n () => globalDemoMode || coreIsPro(licenseInfo),\n [licenseInfo],\n )\n\n const canUsePivot = useMemo(\n () => globalDemoMode || coreCanUsePivot(licenseInfo),\n [licenseInfo],\n )\n\n const canUseAdvancedAggregations = useMemo(\n () => globalDemoMode || licenseInfo.features.advancedAggregations,\n [licenseInfo],\n )\n\n const canUsePercentageMode = useMemo(\n () => globalDemoMode || licenseInfo.features.percentageMode,\n [licenseInfo],\n )\n\n const canUseCharts = useMemo(\n () => globalDemoMode || coreCanUseCharts(licenseInfo),\n [licenseInfo],\n )\n\n const canUseAIAnalyst = useMemo(\n () => globalDemoMode || coreCanUseAIAnalyst(licenseInfo),\n [licenseInfo],\n )\n\n const showWatermark = useMemo(\n () => coreShouldShowWatermark(licenseInfo, globalDemoMode),\n [licenseInfo],\n )\n\n const requirePro = useCallback((feature: string): boolean => {\n if (!isPro) {\n logProRequired(feature)\n return false\n }\n return true\n }, [isPro])\n\n return {\n licenseInfo,\n isDemo,\n isPro,\n canUsePivot,\n canUseAdvancedAggregations,\n canUsePercentageMode,\n canUseCharts,\n canUseAIAnalyst,\n showWatermark,\n requirePro,\n }\n}\n","import type {\n AggregationFunction,\n CalculatedField,\n FieldStats,\n PivotConfig,\n PivotResult,\n PivotValueField,\n} from '@smallwebco/tinypivot-core'\nimport {\n computeAvailableFields,\n computePivotResult,\n generateStorageKey,\n getAggregationLabel,\n getUnassignedFields,\n isConfigValidForFields,\n isPivotConfigured,\n loadCalculatedFields,\n loadPivotConfig,\n saveCalculatedFields,\n savePivotConfig,\n} from '@smallwebco/tinypivot-core'\n/**\n * Pivot Table Hook for React\n * Wraps core pivot logic with React state management\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useLicense } from './useLicense'\n\n// Re-export for convenience\nexport { getAggregationLabel }\n\ninterface UsePivotTableReturn {\n // State\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n showRowTotals: boolean\n showColumnTotals: boolean\n calculatedFields: CalculatedField[]\n\n // Computed\n availableFields: FieldStats[]\n unassignedFields: FieldStats[]\n isConfigured: boolean\n pivotResult: PivotResult | null\n\n // Actions\n addRowField: (field: string) => void\n removeRowField: (field: string) => void\n addColumnField: (field: string) => void\n removeColumnField: (field: string) => void\n addValueField: (field: string, aggregation?: AggregationFunction) => void\n removeValueField: (field: string, aggregation?: AggregationFunction) => void\n updateValueFieldAggregation: (\n field: string,\n oldAgg: AggregationFunction,\n newAgg: AggregationFunction\n ) => void\n clearConfig: () => void\n setShowRowTotals: (value: boolean) => void\n setShowColumnTotals: (value: boolean) => void\n autoSuggestConfig: () => void\n setRowFields: (fields: string[]) => void\n setColumnFields: (fields: string[]) => void\n addCalculatedField: (field: CalculatedField) => void\n removeCalculatedField: (id: string) => void\n}\n\n/**\n * Main pivot table hook\n */\nexport function usePivotTable(data: Record<string, unknown>[]): UsePivotTableReturn {\n const { canUsePivot, requirePro } = useLicense()\n\n // Configuration state\n const [rowFields, setRowFieldsState] = useState<string[]>([])\n const [columnFields, setColumnFieldsState] = useState<string[]>([])\n const [valueFields, setValueFields] = useState<PivotValueField[]>([])\n const [showRowTotals, setShowRowTotals] = useState(true)\n const [showColumnTotals, setShowColumnTotals] = useState(true)\n const [calculatedFields, setCalculatedFields] = useState<CalculatedField[]>(() => loadCalculatedFields())\n const [currentStorageKey, setCurrentStorageKey] = useState<string | null>(null)\n\n // Compute available fields from data\n const availableFields = useMemo((): FieldStats[] => {\n return computeAvailableFields(data)\n }, [data])\n\n // Get fields that haven't been assigned yet\n const unassignedFields = useMemo(() => {\n return getUnassignedFields(availableFields, rowFields, columnFields, valueFields)\n }, [availableFields, rowFields, columnFields, valueFields])\n\n // Check if pivot is configured\n const isConfigured = useMemo(() => {\n return isPivotConfigured({\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n })\n }, [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals])\n\n // Build pivot result\n const pivotResult = useMemo((): PivotResult | null => {\n if (!isConfigured)\n return null\n if (!canUsePivot)\n return null\n\n return computePivotResult(data, {\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n calculatedFields,\n })\n }, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields])\n\n // Load/save config from storage\n useEffect(() => {\n if (data.length === 0)\n return\n\n const newKeys = Object.keys(data[0])\n const storageKey = generateStorageKey(newKeys)\n\n if (storageKey !== currentStorageKey) {\n setCurrentStorageKey(storageKey)\n\n const savedConfig = loadPivotConfig(storageKey)\n if (savedConfig && isConfigValidForFields(savedConfig, newKeys)) {\n setRowFieldsState(savedConfig.rowFields)\n setColumnFieldsState(savedConfig.columnFields)\n setValueFields(savedConfig.valueFields)\n setShowRowTotals(savedConfig.showRowTotals)\n setShowColumnTotals(savedConfig.showColumnTotals)\n if (savedConfig.calculatedFields) {\n setCalculatedFields(savedConfig.calculatedFields)\n }\n }\n else {\n // Validate current config\n const currentConfig: PivotConfig = {\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n }\n if (!isConfigValidForFields(currentConfig, newKeys)) {\n setRowFieldsState([])\n setColumnFieldsState([])\n setValueFields([])\n }\n }\n }\n }, [data])\n\n // Save config when it changes\n useEffect(() => {\n if (!currentStorageKey)\n return\n\n const config: PivotConfig = {\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n calculatedFields,\n }\n savePivotConfig(currentStorageKey, config)\n }, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields])\n\n // Actions - pivot is free with sum aggregation, Pro required for other aggregations\n const addRowField = useCallback(\n (field: string) => {\n if (!rowFields.includes(field)) {\n setRowFieldsState(prev => [...prev, field])\n }\n },\n [rowFields],\n )\n\n const removeRowField = useCallback((field: string) => {\n setRowFieldsState(prev => prev.filter(f => f !== field))\n }, [])\n\n const setRowFields = useCallback((fields: string[]) => {\n setRowFieldsState(fields)\n }, [])\n\n const addColumnField = useCallback(\n (field: string) => {\n if (!columnFields.includes(field)) {\n setColumnFieldsState(prev => [...prev, field])\n }\n },\n [columnFields],\n )\n\n const removeColumnField = useCallback((field: string) => {\n setColumnFieldsState(prev => prev.filter(f => f !== field))\n }, [])\n\n const setColumnFields = useCallback((fields: string[]) => {\n setColumnFieldsState(fields)\n }, [])\n\n const addValueField = useCallback(\n (field: string, aggregation: AggregationFunction = 'sum') => {\n // Pro required for non-sum aggregations\n if (aggregation !== 'sum' && !requirePro(`${aggregation} aggregation`)) {\n return\n }\n setValueFields((prev) => {\n if (prev.some(v => v.field === field && v.aggregation === aggregation)) {\n return prev\n }\n return [...prev, { field, aggregation }]\n })\n },\n [requirePro],\n )\n\n const removeValueField = useCallback((field: string, aggregation?: AggregationFunction) => {\n setValueFields((prev) => {\n if (aggregation) {\n return prev.filter(v => !(v.field === field && v.aggregation === aggregation))\n }\n return prev.filter(v => v.field !== field)\n })\n }, [])\n\n const updateValueFieldAggregation = useCallback(\n (field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction) => {\n setValueFields(prev =>\n prev.map((v) => {\n if (v.field === field && v.aggregation === oldAgg) {\n return { ...v, aggregation: newAgg }\n }\n return v\n }),\n )\n },\n [],\n )\n\n const clearConfig = useCallback(() => {\n setRowFieldsState([])\n setColumnFieldsState([])\n setValueFields([])\n }, [])\n\n const autoSuggestConfig = useCallback(() => {\n if (!requirePro('Pivot Table - Auto Suggest'))\n return\n if (availableFields.length === 0)\n return\n\n const categoricalFields = availableFields.filter(f => !f.isNumeric && f.uniqueCount < 50)\n const numericFields = availableFields.filter(f => f.isNumeric)\n\n if (categoricalFields.length > 0 && numericFields.length > 0) {\n setRowFieldsState([categoricalFields[0].field])\n setValueFields([{ field: numericFields[0].field, aggregation: 'sum' }])\n }\n }, [availableFields, requirePro])\n\n // Calculated field management\n const addCalculatedField = useCallback((field: CalculatedField) => {\n setCalculatedFields((prev) => {\n const existing = prev.findIndex(f => f.id === field.id)\n let updated: CalculatedField[]\n if (existing >= 0) {\n updated = [...prev.slice(0, existing), field, ...prev.slice(existing + 1)]\n }\n else {\n updated = [...prev, field]\n }\n saveCalculatedFields(updated)\n return updated\n })\n }, [])\n\n const removeCalculatedField = useCallback((id: string) => {\n setCalculatedFields((prev) => {\n const updated = prev.filter(f => f.id !== id)\n saveCalculatedFields(updated)\n return updated\n })\n // Also remove from value fields if it was being used\n setValueFields(prev => prev.filter(v => v.field !== `calc:${id}`))\n }, [])\n\n return {\n // State\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n calculatedFields,\n\n // Computed\n availableFields,\n unassignedFields,\n isConfigured,\n pivotResult,\n\n // Actions\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig,\n setShowRowTotals,\n setShowColumnTotals,\n autoSuggestConfig,\n setRowFields,\n setColumnFields,\n addCalculatedField,\n removeCalculatedField,\n }\n}\n","import type { AggregationFunction, CalculatedField, FieldStats, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { AGGREGATION_OPTIONS, getAggregationSymbol } from '@smallwebco/tinypivot-core'\n/**\n * Pivot Table Configuration Panel for React\n * Draggable fields with aggregation selection\n */\nimport React, { useCallback, useMemo, useState } from 'react'\nimport { useLicense } from '../hooks/useLicense'\nimport { CalculatedFieldModal } from './CalculatedFieldModal'\n\n// Check if an aggregation requires Pro license (everything except sum)\nfunction aggregationRequiresPro(agg: AggregationFunction): boolean {\n return agg !== 'sum'\n}\n\n// Extended field stats for calculated fields\ninterface ExtendedFieldStats extends FieldStats {\n isCalculated?: boolean\n calcId?: string\n calcName?: string\n calcFormula?: string\n}\n\ninterface PivotConfigProps {\n availableFields: FieldStats[]\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n showRowTotals: boolean\n showColumnTotals: boolean\n calculatedFields?: CalculatedField[]\n onShowRowTotalsChange: (value: boolean) => void\n onShowColumnTotalsChange: (value: boolean) => void\n onClearConfig: () => void\n onAutoSuggest: () => void\n onDragStart: (field: string, event: React.DragEvent) => void\n onDragEnd: () => void\n onUpdateAggregation: (field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction) => void\n onAddRowField: (field: string) => void\n onRemoveRowField: (field: string) => void\n onAddColumnField: (field: string) => void\n onRemoveColumnField: (field: string) => void\n onAddValueField: (field: string, aggregation: AggregationFunction) => void\n onRemoveValueField: (field: string, aggregation: AggregationFunction) => void\n onAddCalculatedField?: (field: CalculatedField) => void\n onRemoveCalculatedField?: (id: string) => void\n onUpdateCalculatedField?: (field: CalculatedField) => void\n}\n\nfunction getFieldIcon(type: FieldStats['type'], isCalculated?: boolean): string {\n if (isCalculated)\n return 'ƒ'\n switch (type) {\n case 'number':\n return '#'\n case 'date':\n return '📅'\n case 'boolean':\n return '✓'\n default:\n return 'Aa'\n }\n}\n\nexport function PivotConfig({\n availableFields,\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n calculatedFields,\n onShowRowTotalsChange,\n onShowColumnTotalsChange,\n onClearConfig,\n onAutoSuggest: _onAutoSuggest,\n onDragStart,\n onDragEnd,\n onUpdateAggregation,\n onRemoveRowField,\n onRemoveColumnField,\n onRemoveValueField,\n onAddRowField,\n onAddColumnField,\n onAddCalculatedField,\n onRemoveCalculatedField,\n onUpdateCalculatedField,\n}: PivotConfigProps) {\n const [fieldSearch, setFieldSearch] = useState('')\n const [showCalcModal, setShowCalcModal] = useState(false)\n const [editingCalcField, setEditingCalcField] = useState<CalculatedField | null>(null)\n const { canUseAdvancedAggregations } = useLicense()\n\n // Check if an aggregation is available based on license\n const isAggregationAvailable = useCallback((agg: AggregationFunction): boolean => {\n return !aggregationRequiresPro(agg) || canUseAdvancedAggregations\n }, [canUseAdvancedAggregations])\n\n // Get only numeric field names for calculated field formulas\n const numericFieldNames = useMemo(() =>\n availableFields\n .filter(f => f.isNumeric)\n .map(f => f.field), [availableFields])\n\n // Convert calculated fields to virtual FieldStats for display\n const calculatedFieldsAsStats = useMemo((): ExtendedFieldStats[] => {\n if (!calculatedFields)\n return []\n return calculatedFields.map(calc => ({\n field: `calc:${calc.id}`,\n type: 'number' as const,\n uniqueCount: 0,\n isNumeric: true,\n isCalculated: true,\n calcId: calc.id,\n calcName: calc.name,\n calcFormula: calc.formula,\n }))\n }, [calculatedFields])\n\n // Combined available fields (data fields + calculated fields)\n const allAvailableFields = useMemo((): ExtendedFieldStats[] => [\n ...availableFields.map(f => ({ ...f, isCalculated: false })),\n ...calculatedFieldsAsStats,\n ], [availableFields, calculatedFieldsAsStats])\n\n // Assigned fields\n const assignedFields = useMemo(() => {\n const rowSet = new Set(rowFields)\n const colSet = new Set(columnFields)\n const valueMap = new Map(valueFields.map(v => [v.field, v]))\n\n return allAvailableFields\n .filter(f => rowSet.has(f.field) || colSet.has(f.field) || valueMap.has(f.field))\n .map(f => ({\n ...f,\n assignedTo: rowSet.has(f.field)\n ? ('row' as const)\n : colSet.has(f.field)\n ? ('column' as const)\n : ('value' as const),\n valueConfig: valueMap.get(f.field),\n }))\n }, [allAvailableFields, rowFields, columnFields, valueFields])\n\n // Unassigned fields (including unassigned calculated fields)\n const unassignedFields = useMemo(() => {\n const rowSet = new Set(rowFields)\n const colSet = new Set(columnFields)\n const valSet = new Set(valueFields.map(v => v.field))\n\n return allAvailableFields.filter(\n f => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field),\n )\n }, [allAvailableFields, rowFields, columnFields, valueFields])\n\n const filteredUnassignedFields = useMemo(() => {\n if (!fieldSearch.trim())\n return unassignedFields\n const search = fieldSearch.toLowerCase().trim()\n return unassignedFields.filter((f) => {\n const fieldName = f.field.toLowerCase()\n const displayName = f.isCalculated && f.calcName ? f.calcName.toLowerCase() : ''\n return fieldName.includes(search) || displayName.includes(search)\n })\n }, [unassignedFields, fieldSearch])\n\n const assignedCount = assignedFields.length\n\n // Get display name for field (handles calculated fields)\n const getFieldDisplayName = useCallback((field: ExtendedFieldStats): string => {\n if (field.isCalculated && field.calcName) {\n return field.calcName\n }\n return field.field\n }, [])\n\n const handleDragStart = useCallback(\n (field: string, event: React.DragEvent) => {\n event.dataTransfer?.setData('text/plain', field)\n event.dataTransfer!.effectAllowed = 'move'\n onDragStart(field, event)\n },\n [onDragStart],\n )\n\n const handleAggregationChange = useCallback(\n (field: string, currentAgg: AggregationFunction, newAgg: AggregationFunction) => {\n // Prevent changing to Pro aggregations without license\n if (!isAggregationAvailable(newAgg)) {\n console.warn(`[TinyPivot] \"${newAgg}\" aggregation requires a Pro license. Visit https://tiny-pivot.com/#pricing to upgrade.`)\n return\n }\n onUpdateAggregation(field, currentAgg, newAgg)\n },\n [onUpdateAggregation, isAggregationAvailable],\n )\n\n const toggleRowColumn = useCallback(\n (field: string, currentAssignment: 'row' | 'column') => {\n if (currentAssignment === 'row') {\n onRemoveRowField(field)\n onAddColumnField(field)\n }\n else {\n onRemoveColumnField(field)\n onAddRowField(field)\n }\n },\n [onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField],\n )\n\n const removeField = useCallback(\n (field: string, assignedTo: 'row' | 'column' | 'value', valueConfig?: PivotValueField) => {\n if (assignedTo === 'row') {\n onRemoveRowField(field)\n }\n else if (assignedTo === 'column') {\n onRemoveColumnField(field)\n }\n else if (valueConfig) {\n onRemoveValueField(field, valueConfig.aggregation)\n }\n },\n [onRemoveRowField, onRemoveColumnField, onRemoveValueField],\n )\n\n // Handle totals toggle (toggle both row and column together)\n const handleTotalsToggle = useCallback((checked: boolean) => {\n onShowRowTotalsChange(checked)\n onShowColumnTotalsChange(checked)\n }, [onShowRowTotalsChange, onShowColumnTotalsChange])\n\n // Calculated field modal handlers\n const openCalcModal = useCallback((field?: CalculatedField) => {\n setEditingCalcField(field || null)\n setShowCalcModal(true)\n }, [])\n\n const handleSaveCalcField = useCallback((field: CalculatedField) => {\n if (editingCalcField && onUpdateCalculatedField) {\n onUpdateCalculatedField(field)\n }\n else if (onAddCalculatedField) {\n onAddCalculatedField(field)\n }\n setShowCalcModal(false)\n setEditingCalcField(null)\n }, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField])\n\n const handleCloseCalcModal = useCallback(() => {\n setShowCalcModal(false)\n setEditingCalcField(null)\n }, [])\n\n return (\n <div className=\"vpg-pivot-config\">\n {/* Header */}\n <div className=\"vpg-config-header\">\n <h3 className=\"vpg-config-title\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 10h16M4 14h16M4 18h16\"\n />\n </svg>\n Fields\n </h3>\n <div className=\"vpg-header-actions\">\n {assignedCount > 0 && (\n <button\n className=\"vpg-action-btn vpg-clear-btn\"\n title=\"Clear all\"\n onClick={onClearConfig}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n\n {/* Assigned Fields */}\n {assignedCount > 0 && (\n <div className=\"vpg-assigned-section\">\n <div className=\"vpg-section-label\">Active</div>\n <div className=\"vpg-assigned-list\">\n {assignedFields.map(field => (\n <div\n key={field.field}\n className={`vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? ' vpg-type-calc' : ''}`}\n title={field.isCalculated ? field.calcFormula : field.field}\n draggable\n onDragStart={e => handleDragStart(field.field, e)}\n onDragEnd={onDragEnd}\n >\n <div className=\"vpg-item-main\">\n <span className={`vpg-item-badge ${field.assignedTo}${field.isCalculated ? ' calc' : ''}`}>\n {field.isCalculated\n ? 'ƒ'\n : field.assignedTo === 'row'\n ? 'R'\n : field.assignedTo === 'column'\n ? 'C'\n : getAggregationSymbol(field.valueConfig?.aggregation || 'sum')}\n </span>\n <span className=\"vpg-item-name\">{getFieldDisplayName(field)}</span>\n </div>\n\n <div className=\"vpg-item-actions\">\n {(field.assignedTo === 'row' || field.assignedTo === 'column') && (\n <button\n className=\"vpg-toggle-btn\"\n title={field.assignedTo === 'row' ? 'Move to Columns' : 'Move to Rows'}\n onClick={(e) => {\n e.stopPropagation()\n toggleRowColumn(field.field, field.assignedTo as 'row' | 'column')\n }}\n >\n <svg\n className=\"vpg-icon-xs\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4\"\n />\n </svg>\n </button>\n )}\n\n {field.assignedTo === 'value' && field.valueConfig && (\n <select\n className=\"vpg-agg-select\"\n value={field.valueConfig.aggregation}\n onChange={(e) => {\n e.stopPropagation()\n handleAggregationChange(\n field.field,\n field.valueConfig!.aggregation,\n e.target.value as AggregationFunction,\n )\n }}\n onClick={e => e.stopPropagation()}\n >\n {AGGREGATION_OPTIONS.map(agg => (\n <option\n key={agg.value}\n value={agg.value}\n disabled={aggregationRequiresPro(agg.value) && !canUseAdvancedAggregations}\n >\n {agg.symbol}\n {' '}\n {agg.label}\n {aggregationRequiresPro(agg.value) && !canUseAdvancedAggregations ? ' (Pro)' : ''}\n </option>\n ))}\n </select>\n )}\n\n <button\n className=\"vpg-remove-btn\"\n title=\"Remove\"\n onClick={(e) => {\n e.stopPropagation()\n removeField(field.field, field.assignedTo, field.valueConfig)\n }}\n >\n ×\n </button>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Unassigned Fields */}\n <div className=\"vpg-unassigned-section\">\n <div className=\"vpg-section-header\">\n <div className=\"vpg-section-label\">\n Available\n {' '}\n <span className=\"vpg-count\">{unassignedFields.length}</span>\n </div>\n </div>\n\n {/* Field Search */}\n <div className=\"vpg-field-search\">\n <svg className=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <input\n type=\"text\"\n value={fieldSearch}\n onChange={e => setFieldSearch(e.target.value)}\n placeholder=\"Search fields...\"\n className=\"vpg-search-input\"\n />\n {fieldSearch && (\n <button className=\"vpg-clear-search\" onClick={() => setFieldSearch('')}>\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n\n <div className=\"vpg-field-list\">\n {filteredUnassignedFields.map(field => (\n <div\n key={field.field}\n className={`vpg-field-item${field.isNumeric && !field.isCalculated ? ' vpg-is-numeric' : ''}${field.isCalculated ? ' vpg-is-calculated' : ''}`}\n title={field.isCalculated ? field.calcFormula : field.field}\n draggable\n onDragStart={e => handleDragStart(field.field, e)}\n onDragEnd={onDragEnd}\n >\n <span className={`vpg-field-type-icon${field.isCalculated ? ' vpg-calc-type' : ''}`} title={field.type}>\n {getFieldIcon(field.type, field.isCalculated)}\n </span>\n <span className=\"vpg-field-name\">{getFieldDisplayName(field)}</span>\n {field.isCalculated\n ? (\n <>\n <button\n className=\"vpg-field-edit\"\n title=\"Edit calculated field\"\n onClick={(e) => {\n e.stopPropagation()\n const calcField = calculatedFields?.find(c => c.id === field.calcId)\n if (calcField)\n openCalcModal(calcField)\n }}\n >\n ✎\n </button>\n <button\n className=\"vpg-field-delete\"\n title=\"Delete calculated field\"\n onClick={(e) => {\n e.stopPropagation()\n if (field.calcId && onRemoveCalculatedField) {\n onRemoveCalculatedField(field.calcId)\n }\n }}\n >\n ×\n </button>\n </>\n )\n : (\n <span className=\"vpg-unique-count\">{field.uniqueCount}</span>\n )}\n </div>\n ))}\n {filteredUnassignedFields.length === 0 && fieldSearch && (\n <div className=\"vpg-empty-hint\">\n No fields match \"\n {fieldSearch}\n \"\n </div>\n )}\n {unassignedFields.length === 0 && <div className=\"vpg-empty-hint\">All fields assigned</div>}\n </div>\n </div>\n\n {/* Options */}\n <div className=\"vpg-options-section\">\n <label className=\"vpg-option-toggle\">\n <input\n type=\"checkbox\"\n checked={showRowTotals}\n onChange={e => handleTotalsToggle(e.target.checked)}\n />\n <span>Totals</span>\n </label>\n <button className=\"vpg-calc-btn\" onClick={() => openCalcModal()} title=\"Add calculated field (e.g. Profit Margin %)\">\n <span className=\"vpg-calc-icon\">ƒ</span>\n <span>+ Calc</span>\n </button>\n </div>\n\n {/* Calculated Field Modal */}\n <CalculatedFieldModal\n show={showCalcModal}\n availableFields={numericFieldNames}\n existingField={editingCalcField}\n onClose={handleCloseCalcModal}\n onSave={handleSaveCalcField}\n />\n </div>\n )\n}\n","import type { AggregationFunction, CalculatedField, PivotResult, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { getAggregationLabel, getAggregationSymbol } from '@smallwebco/tinypivot-core'\n/**\n * Pivot Table Skeleton + Data Display for React\n * Visual layout for pivot configuration and results\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useLicense } from '../hooks/useLicense'\n\ninterface ActiveFilter {\n column: string\n valueCount: number\n values?: string[]\n displayText?: string\n isRange?: boolean\n}\n\ninterface PivotSkeletonProps {\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n calculatedFields?: CalculatedField[]\n isConfigured: boolean\n draggingField: string | null\n pivotResult: PivotResult | null\n fontSize?: 'xs' | 'sm' | 'base'\n activeFilters?: ActiveFilter[] | null\n totalRowCount?: number\n filteredRowCount?: number\n onAddRowField: (field: string) => void\n onRemoveRowField: (field: string) => void\n onAddColumnField: (field: string) => void\n onRemoveColumnField: (field: string) => void\n onAddValueField: (field: string, aggregation: AggregationFunction) => void\n onRemoveValueField: (field: string, aggregation: AggregationFunction) => void\n onUpdateAggregation: (field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction) => void\n onReorderRowFields: (fields: string[]) => void\n onReorderColumnFields: (fields: string[]) => void\n}\n\nexport function PivotSkeleton({\n rowFields,\n columnFields,\n valueFields,\n calculatedFields,\n isConfigured,\n draggingField,\n pivotResult,\n fontSize = 'xs',\n activeFilters,\n totalRowCount,\n filteredRowCount,\n onAddRowField,\n onRemoveRowField,\n onAddColumnField,\n onRemoveColumnField,\n onAddValueField,\n onRemoveValueField,\n onReorderRowFields,\n onReorderColumnFields,\n}: PivotSkeletonProps) {\n const { showWatermark, canUsePivot, isDemo } = useLicense()\n\n // Helper to get display name for value fields (resolves calc IDs to names)\n const getValueFieldDisplayName = useCallback((field: string): string => {\n if (field.startsWith('calc:')) {\n const calcId = field.replace('calc:', '')\n const calcField = calculatedFields?.find(c => c.id === calcId)\n return calcField?.name || field\n }\n return field\n }, [calculatedFields])\n\n // Helper to check if field is a calculated field\n const isCalculatedField = useCallback((field: string): boolean => {\n return field.startsWith('calc:')\n }, [])\n\n // Drag state\n const [dragOverArea, setDragOverArea] = useState<'row' | 'column' | 'value' | null>(null)\n\n // Reorder drag state\n const [reorderDragSource, setReorderDragSource] = useState<{ zone: 'row' | 'column', index: number } | null>(null)\n const [reorderDropTarget, setReorderDropTarget] = useState<{ zone: 'row' | 'column', index: number } | null>(null)\n\n // Sorting\n type SortTarget = 'row' | number\n const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc')\n const [sortTarget, setSortTarget] = useState<SortTarget>('row')\n\n const toggleSort = useCallback((target: SortTarget = 'row') => {\n if (sortTarget === target) {\n setSortDirection(prev => (prev === 'asc' ? 'desc' : 'asc'))\n }\n else {\n setSortTarget(target)\n setSortDirection('asc')\n }\n }, [sortTarget])\n\n // Selection state for cell selection and copy\n const [selectedCell, setSelectedCell] = useState<{ row: number, col: number } | null>(null)\n const [selectionStart, setSelectionStart] = useState<{ row: number, col: number } | null>(null)\n const [selectionEnd, setSelectionEnd] = useState<{ row: number, col: number } | null>(null)\n const [isSelecting, setIsSelecting] = useState(false)\n const [showCopyToast, setShowCopyToast] = useState(false)\n const [copyToastMessage, setCopyToastMessage] = useState('')\n\n const selectionBounds = useMemo(() => {\n if (!selectionStart || !selectionEnd)\n return null\n return {\n minRow: Math.min(selectionStart.row, selectionEnd.row),\n maxRow: Math.max(selectionStart.row, selectionEnd.row),\n minCol: Math.min(selectionStart.col, selectionEnd.col),\n maxCol: Math.max(selectionStart.col, selectionEnd.col),\n }\n }, [selectionStart, selectionEnd])\n\n const handleCellMouseDown = useCallback(\n (rowIndex: number, colIndex: number, event: React.MouseEvent) => {\n event.preventDefault()\n\n if (event.shiftKey && selectedCell) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n else {\n setSelectedCell({ row: rowIndex, col: colIndex })\n setSelectionStart({ row: rowIndex, col: colIndex })\n setSelectionEnd({ row: rowIndex, col: colIndex })\n setIsSelecting(true)\n }\n },\n [selectedCell],\n )\n\n const handleCellMouseEnter = useCallback(\n (rowIndex: number, colIndex: number) => {\n if (isSelecting) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n },\n [isSelecting],\n )\n\n const isCellSelected = useCallback(\n (rowIndex: number, colIndex: number): boolean => {\n if (!selectionBounds) {\n return selectedCell?.row === rowIndex && selectedCell?.col === colIndex\n }\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol\n },\n [selectionBounds, selectedCell],\n )\n\n // Mouse up handler\n useEffect(() => {\n const handleMouseUp = () => setIsSelecting(false)\n document.addEventListener('mouseup', handleMouseUp)\n return () => document.removeEventListener('mouseup', handleMouseUp)\n }, [])\n\n // Sorted row indices\n const sortedRowIndices = useMemo(() => {\n if (!pivotResult)\n return []\n\n const indices = pivotResult.rowHeaders.map((_, i) => i)\n const headers = pivotResult.rowHeaders\n const data = pivotResult.data\n\n indices.sort((a, b) => {\n let cmp: number\n\n if (sortTarget === 'row') {\n const aHeader = headers[a]?.join(' / ') || ''\n const bHeader = headers[b]?.join(' / ') || ''\n cmp = aHeader.localeCompare(bHeader, undefined, { numeric: true, sensitivity: 'base' })\n }\n else {\n const colIdx = sortTarget as number\n const aVal = data[a]?.[colIdx]?.value ?? null\n const bVal = data[b]?.[colIdx]?.value ?? null\n\n if (aVal === null && bVal === null)\n cmp = 0\n else if (aVal === null)\n cmp = 1\n else if (bVal === null)\n cmp = -1\n else cmp = aVal - bVal\n }\n\n return sortDirection === 'asc' ? cmp : -cmp\n })\n\n return indices\n }, [pivotResult, sortTarget, sortDirection])\n\n // Copy selection to clipboard\n const copySelectionToClipboard = useCallback(() => {\n if (!selectionBounds || !pivotResult)\n return\n\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n const lines: string[] = []\n\n for (let r = minRow; r <= maxRow; r++) {\n const sortedIdx = sortedRowIndices[r]\n if (sortedIdx === undefined)\n continue\n\n const rowValues: string[] = []\n for (let c = minCol; c <= maxCol; c++) {\n const cell = pivotResult.data[sortedIdx]?.[c]\n rowValues.push(cell?.formattedValue ?? '')\n }\n lines.push(rowValues.join('\\t'))\n }\n\n const text = lines.join('\\n')\n\n navigator.clipboard.writeText(text).then(() => {\n const cellCount = (maxRow - minRow + 1) * (maxCol - minCol + 1)\n setCopyToastMessage(`Copied ${cellCount} cell${cellCount > 1 ? 's' : ''}`)\n setShowCopyToast(true)\n setTimeout(() => setShowCopyToast(false), 2000)\n }).catch((err) => {\n console.error('Copy failed:', err)\n })\n }, [selectionBounds, pivotResult, sortedRowIndices])\n\n // Keyboard handler for copy\n useEffect(() => {\n const handleKeydown = (event: KeyboardEvent) => {\n if (!selectionBounds)\n return\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'c') {\n event.preventDefault()\n copySelectionToClipboard()\n return\n }\n\n if (event.key === 'Escape') {\n setSelectedCell(null)\n setSelectionStart(null)\n setSelectionEnd(null)\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n return () => document.removeEventListener('keydown', handleKeydown)\n }, [selectionBounds, copySelectionToClipboard])\n\n // Selection statistics for footer\n const selectionStats = useMemo(() => {\n if (!selectionBounds || !pivotResult)\n return null\n\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n const values: number[] = []\n let count = 0\n\n for (let r = minRow; r <= maxRow; r++) {\n const sortedIdx = sortedRowIndices[r]\n if (sortedIdx === undefined)\n continue\n\n for (let c = minCol; c <= maxCol; c++) {\n const cell = pivotResult.data[sortedIdx]?.[c]\n count++\n if (cell?.value !== null && cell?.value !== undefined && typeof cell.value === 'number') {\n values.push(cell.value)\n }\n }\n }\n\n if (count <= 1)\n return null\n\n const sum = values.reduce((a, b) => a + b, 0)\n const avg = values.length > 0 ? sum / values.length : 0\n\n return {\n count,\n numericCount: values.length,\n sum,\n avg,\n }\n }, [selectionBounds, pivotResult, sortedRowIndices])\n\n const formatStatValue = useCallback((val: number): string => {\n if (Math.abs(val) >= 1_000_000)\n return `${(val / 1_000_000).toFixed(2)}M`\n if (Math.abs(val) >= 1_000)\n return `${(val / 1_000).toFixed(2)}K`\n return val.toFixed(2)\n }, [])\n\n // Column headers\n const columnHeaderCells = useMemo(() => {\n if (!pivotResult || pivotResult.headers.length === 0) {\n return [\n valueFields.map(vf => ({\n label: `${getValueFieldDisplayName(vf.field)} (${getAggregationLabel(vf.aggregation)})`,\n colspan: 1,\n })),\n ]\n }\n\n const result: Array<Array<{ label: string, colspan: number }>> = []\n\n for (let level = 0; level < pivotResult.headers.length; level++) {\n const headerRow = pivotResult.headers[level]\n const cells: Array<{ label: string, colspan: number }> = []\n\n let i = 0\n while (i < headerRow.length) {\n const value = headerRow[i]\n let colspan = 1\n\n while (i + colspan < headerRow.length && headerRow[i + colspan] === value) {\n colspan++\n }\n\n cells.push({ label: value, colspan })\n i += colspan\n }\n\n result.push(cells)\n }\n\n return result\n }, [pivotResult, valueFields])\n\n // Filter status\n const hasActiveFilters = activeFilters && activeFilters.length > 0\n const filterSummary = useMemo(() => {\n if (!activeFilters || activeFilters.length === 0)\n return ''\n return activeFilters.map(f => f.column).join(', ')\n }, [activeFilters])\n\n // Detailed filter tooltip\n const [showFilterTooltip, setShowFilterTooltip] = useState(false)\n const filterTooltipDetails = useMemo(() => {\n if (!activeFilters || activeFilters.length === 0)\n return []\n return activeFilters.map((f) => {\n // Handle range filters\n if (f.isRange && f.displayText) {\n return {\n column: f.column,\n displayText: f.displayText,\n isRange: true,\n values: [] as string[],\n remaining: 0,\n }\n }\n // Handle value filters\n const values = f.values || []\n const maxDisplay = 5\n const displayValues = values.slice(0, maxDisplay)\n const remaining = values.length - maxDisplay\n return {\n column: f.column,\n values: displayValues,\n remaining: remaining > 0 ? remaining : 0,\n isRange: false,\n }\n })\n }, [activeFilters])\n\n // Drag handlers\n const handleDragOver = useCallback(\n (area: 'row' | 'column' | 'value', event: React.DragEvent) => {\n event.preventDefault()\n event.dataTransfer!.dropEffect = 'move'\n setDragOverArea(area)\n },\n [],\n )\n\n const handleDragLeave = useCallback(() => {\n setDragOverArea(null)\n }, [])\n\n const handleDrop = useCallback(\n (area: 'row' | 'column' | 'value', event: React.DragEvent) => {\n event.preventDefault()\n const field = event.dataTransfer?.getData('text/plain')\n\n if (!field || field.startsWith('reorder:')) {\n setDragOverArea(null)\n return\n }\n\n if (rowFields.includes(field))\n onRemoveRowField(field)\n if (columnFields.includes(field))\n onRemoveColumnField(field)\n const existingValue = valueFields.find(v => v.field === field)\n if (existingValue)\n onRemoveValueField(field, existingValue.aggregation)\n\n switch (area) {\n case 'row':\n onAddRowField(field)\n break\n case 'column':\n onAddColumnField(field)\n break\n case 'value':\n onAddValueField(field, 'sum')\n break\n }\n setDragOverArea(null)\n },\n [rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField],\n )\n\n // Reorder handlers for chips within zones\n const handleChipDragStart = useCallback(\n (zone: 'row' | 'column', index: number, event: React.DragEvent) => {\n setReorderDragSource({ zone, index })\n event.dataTransfer!.effectAllowed = 'move'\n event.dataTransfer!.setData('text/plain', `reorder:${zone}:${index}`)\n // Clear any zone drag-over state\n requestAnimationFrame(() => {\n setDragOverArea(null)\n })\n },\n [],\n )\n\n const handleChipDragEnd = useCallback(() => {\n setReorderDragSource(null)\n setReorderDropTarget(null)\n }, [])\n\n const handleChipDragOver = useCallback(\n (zone: 'row' | 'column', index: number, event: React.DragEvent) => {\n event.preventDefault()\n // Only handle reorder within same zone\n if (reorderDragSource && reorderDragSource.zone === zone) {\n event.dataTransfer!.dropEffect = 'move'\n setReorderDropTarget({ zone, index })\n }\n },\n [reorderDragSource],\n )\n\n const handleChipDragLeave = useCallback(() => {\n setReorderDropTarget(null)\n }, [])\n\n const handleChipDrop = useCallback(\n (zone: 'row' | 'column', targetIndex: number, event: React.DragEvent) => {\n event.preventDefault()\n event.stopPropagation()\n\n if (!reorderDragSource || reorderDragSource.zone !== zone) {\n return\n }\n\n const sourceIndex = reorderDragSource.index\n if (sourceIndex === targetIndex) {\n setReorderDragSource(null)\n setReorderDropTarget(null)\n return\n }\n\n // Create reordered array\n const fields = zone === 'row' ? [...rowFields] : [...columnFields]\n const [movedField] = fields.splice(sourceIndex, 1)\n fields.splice(targetIndex, 0, movedField)\n\n // Emit reorder event\n if (zone === 'row') {\n onReorderRowFields(fields)\n }\n else {\n onReorderColumnFields(fields)\n }\n\n setReorderDragSource(null)\n setReorderDropTarget(null)\n },\n [reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields],\n )\n\n const isChipDragSource = useCallback(\n (zone: 'row' | 'column', index: number): boolean => {\n return reorderDragSource?.zone === zone && reorderDragSource?.index === index\n },\n [reorderDragSource],\n )\n\n const isChipDropTarget = useCallback(\n (zone: 'row' | 'column', index: number): boolean => {\n return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index\n },\n [reorderDropTarget],\n )\n\n const currentFontSize = fontSize\n\n // Calculate width per row header column\n const rowHeaderWidth = 180\n const rowHeaderColWidth = useMemo(() => {\n const numCols = Math.max(rowFields.length, 1)\n return Math.max(rowHeaderWidth / numCols, 80)\n }, [rowFields.length])\n\n // Calculate left offset for each row header column (for sticky positioning)\n const getRowHeaderLeftOffset = useCallback((fieldIdx: number): number => {\n return fieldIdx * rowHeaderColWidth\n }, [rowHeaderColWidth])\n\n return (\n <div\n className={`vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? 'vpg-is-dragging' : ''}`}\n >\n {/* Copy Toast */}\n {showCopyToast && (\n <div className=\"vpg-toast\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n {copyToastMessage}\n </div>\n )}\n\n {/* Header Bar */}\n <div className=\"vpg-skeleton-header\">\n <div className=\"vpg-skeleton-title\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n <span>Pivot Table</span>\n </div>\n\n <div className=\"vpg-header-right\">\n {hasActiveFilters && (\n <div\n className=\"vpg-filter-indicator\"\n onMouseEnter={() => setShowFilterTooltip(true)}\n onMouseLeave={() => setShowFilterTooltip(false)}\n >\n <svg\n className=\"vpg-filter-icon\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n <span className=\"vpg-filter-text\">\n Filtered:\n {' '}\n <strong>{filterSummary}</strong>\n {filteredRowCount !== undefined && totalRowCount !== undefined && (\n <span className=\"vpg-filter-count\">\n (\n {filteredRowCount.toLocaleString()}\n {' '}\n of\n {' '}\n {totalRowCount.toLocaleString()}\n {' '}\n rows)\n </span>\n )}\n </span>\n\n {/* Tooltip */}\n {showFilterTooltip && (\n <div className=\"vpg-filter-tooltip\">\n <div className=\"vpg-tooltip-header\">Active Filters</div>\n {filterTooltipDetails.map(filter => (\n <div key={filter.column} className=\"vpg-tooltip-filter\">\n <div className=\"vpg-tooltip-column\">{filter.column}</div>\n <div className=\"vpg-tooltip-values\">\n {filter.isRange\n ? (\n <span className=\"vpg-tooltip-value vpg-range-value\">{filter.displayText}</span>\n )\n : (\n <>\n {filter.values.map((val, idx) => (\n <span key={idx} className=\"vpg-tooltip-value\">\n {val}\n </span>\n ))}\n {filter.remaining > 0 && (\n <span className=\"vpg-tooltip-more\">\n +\n {filter.remaining}\n {' '}\n more\n </span>\n )}\n </>\n )}\n </div>\n </div>\n ))}\n {filteredRowCount !== undefined && totalRowCount !== undefined && (\n <div className=\"vpg-tooltip-summary\">\n Showing\n {' '}\n {filteredRowCount.toLocaleString()}\n {' '}\n of\n {' '}\n {totalRowCount.toLocaleString()}\n {' '}\n rows\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {isConfigured && (\n <div className=\"vpg-config-summary\">\n <span className=\"vpg-summary-badge vpg-rows\">\n {rowFields.length}\n {' '}\n row\n {rowFields.length !== 1 ? 's' : ''}\n </span>\n <span className=\"vpg-summary-badge vpg-cols\">\n {columnFields.length}\n {' '}\n col\n {columnFields.length !== 1 ? 's' : ''}\n </span>\n <span className=\"vpg-summary-badge vpg-vals\">\n {valueFields.length}\n {' '}\n val\n {valueFields.length !== 1 ? 's' : ''}\n </span>\n </div>\n )}\n </div>\n </div>\n\n {/* License Required Message */}\n {!canUsePivot ? (\n <div className=\"vpg-pro-required\">\n <div className=\"vpg-pro-content\">\n <svg className=\"vpg-pro-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <h3>Pro Feature</h3>\n <p>Pivot Table functionality requires a Pro license.</p>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener noreferrer\" className=\"vpg-pro-link\">\n Get Pro License →\n </a>\n </div>\n </div>\n ) : (\n <>\n {/* Config Bar */}\n <div className=\"vpg-config-bar\">\n {/* Row drop zone */}\n <div\n className={`vpg-drop-zone vpg-row-zone ${dragOverArea === 'row' ? 'vpg-drag-over' : ''}`}\n onDragOver={e => handleDragOver('row', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('row', e)}\n >\n <div className=\"vpg-zone-header\">\n <span className=\"vpg-zone-icon vpg-row-icon\">↓</span>\n <span className=\"vpg-zone-label\">Rows</span>\n </div>\n <div className=\"vpg-zone-chips\">\n {rowFields.map((field, idx) => (\n <div\n key={field}\n className={`vpg-mini-chip vpg-row-chip ${isChipDragSource('row', idx) ? 'vpg-chip-dragging' : ''} ${isChipDropTarget('row', idx) ? 'vpg-chip-drop-target' : ''}`}\n draggable\n onDragStart={e => handleChipDragStart('row', idx, e)}\n onDragEnd={handleChipDragEnd}\n onDragOver={e => handleChipDragOver('row', idx, e)}\n onDragLeave={handleChipDragLeave}\n onDrop={e => handleChipDrop('row', idx, e)}\n >\n <span className=\"vpg-drag-handle\">⋮⋮</span>\n <span className=\"vpg-mini-name\">{field}</span>\n <button\n className=\"vpg-mini-remove\"\n onClick={(e) => { e.stopPropagation(); onRemoveRowField(field) }}\n >\n ×\n </button>\n </div>\n ))}\n {rowFields.length === 0 && <span className=\"vpg-zone-hint\">Drop here</span>}\n </div>\n </div>\n\n {/* Column drop zone */}\n <div\n className={`vpg-drop-zone vpg-column-zone ${dragOverArea === 'column' ? 'vpg-drag-over' : ''}`}\n onDragOver={e => handleDragOver('column', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('column', e)}\n >\n <div className=\"vpg-zone-header\">\n <span className=\"vpg-zone-icon vpg-column-icon\">→</span>\n <span className=\"vpg-zone-label\">Columns</span>\n </div>\n <div className=\"vpg-zone-chips\">\n {columnFields.map((field, idx) => (\n <div\n key={field}\n className={`vpg-mini-chip vpg-column-chip ${isChipDragSource('column', idx) ? 'vpg-chip-dragging' : ''} ${isChipDropTarget('column', idx) ? 'vpg-chip-drop-target' : ''}`}\n draggable\n onDragStart={e => handleChipDragStart('column', idx, e)}\n onDragEnd={handleChipDragEnd}\n onDragOver={e => handleChipDragOver('column', idx, e)}\n onDragLeave={handleChipDragLeave}\n onDrop={e => handleChipDrop('column', idx, e)}\n >\n <span className=\"vpg-drag-handle\">⋮⋮</span>\n <span className=\"vpg-mini-name\">{field}</span>\n <button\n className=\"vpg-mini-remove\"\n onClick={(e) => { e.stopPropagation(); onRemoveColumnField(field) }}\n >\n ×\n </button>\n </div>\n ))}\n {columnFields.length === 0 && <span className=\"vpg-zone-hint\">Drop here</span>}\n </div>\n </div>\n\n {/* Values drop zone */}\n <div\n className={`vpg-drop-zone vpg-value-zone ${dragOverArea === 'value' ? 'vpg-drag-over' : ''}`}\n onDragOver={e => handleDragOver('value', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('value', e)}\n >\n <div className=\"vpg-zone-header\">\n <span className=\"vpg-zone-icon vpg-value-icon\">Σ</span>\n <span className=\"vpg-zone-label\">Values</span>\n </div>\n <div className=\"vpg-zone-chips\">\n {valueFields.map(vf => (\n <div\n key={`${vf.field}-${vf.aggregation}`}\n className={`vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? ' vpg-calc-chip' : ''}`}\n >\n <span className=\"vpg-agg-symbol\">{isCalculatedField(vf.field) ? 'ƒ' : getAggregationSymbol(vf.aggregation)}</span>\n <span className=\"vpg-mini-name\">{getValueFieldDisplayName(vf.field)}</span>\n <button\n className=\"vpg-mini-remove\"\n onClick={() => onRemoveValueField(vf.field, vf.aggregation)}\n >\n ×\n </button>\n </div>\n ))}\n {valueFields.length === 0 && <span className=\"vpg-zone-hint\">Drop numeric</span>}\n </div>\n </div>\n </div>\n\n {/* Placeholder when not configured */}\n {(!isConfigured || !pivotResult) && (\n <div className=\"vpg-placeholder\">\n <div className=\"vpg-placeholder-content\">\n <svg\n className=\"vpg-placeholder-icon\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n <span className=\"vpg-placeholder-text\">\n {valueFields.length === 0\n ? (\n <>\n Add a\n {' '}\n <strong>Values</strong>\n {' '}\n field to see your pivot table\n </>\n )\n : rowFields.length === 0 && columnFields.length === 0\n ? (\n <>\n Add\n {' '}\n <strong>Row</strong>\n {' '}\n or\n {' '}\n <strong>Column</strong>\n {' '}\n fields to group your data\n </>\n )\n : (\n 'Your pivot table will appear here'\n )}\n </span>\n </div>\n </div>\n )}\n\n {/* Data Table */}\n {isConfigured && pivotResult && (\n <div className=\"vpg-table-container\">\n <table className=\"vpg-pivot-table\">\n <thead>\n {columnHeaderCells.map((headerRow, levelIdx) => (\n <tr key={`header-${levelIdx}`} className=\"vpg-column-header-row\">\n {levelIdx === 0 && (rowFields.length > 0 ? rowFields : ['Rows']).map((field, fieldIdx) => (\n <th\n key={`row-header-${fieldIdx}`}\n className=\"vpg-row-header-label\"\n rowSpan={columnHeaderCells.length}\n style={{ width: `${rowHeaderColWidth}px`, minWidth: '80px', left: `${getRowHeaderLeftOffset(fieldIdx)}px` }}\n onClick={() => toggleSort('row')}\n >\n <div className=\"vpg-header-content\">\n <span>{field}</span>\n {(fieldIdx === rowFields.length - 1 || rowFields.length === 0) && (\n <span className={`vpg-sort-indicator ${sortTarget === 'row' ? 'active' : ''}`}>\n {sortTarget === 'row' ? (sortDirection === 'asc' ? '↑' : '↓') : '⇅'}\n </span>\n )}\n </div>\n </th>\n ))}\n {headerRow.map((cell, idx) => (\n <th\n key={idx}\n className=\"vpg-column-header-cell\"\n colSpan={cell.colspan}\n onClick={() =>\n levelIdx === columnHeaderCells.length - 1 && toggleSort(idx)}\n >\n <div className=\"vpg-header-content\">\n <span>{cell.label}</span>\n {levelIdx === columnHeaderCells.length - 1 && (\n <span className={`vpg-sort-indicator ${sortTarget === idx ? 'active' : ''}`}>\n {sortTarget === idx\n ? sortDirection === 'asc'\n ? '↑'\n : '↓'\n : '⇅'}\n </span>\n )}\n </div>\n </th>\n ))}\n {pivotResult.rowTotals.length > 0 && levelIdx === 0 && (\n <th className=\"vpg-total-header\" rowSpan={columnHeaderCells.length}>\n Total\n </th>\n )}\n </tr>\n ))}\n </thead>\n\n <tbody>\n {sortedRowIndices.map(sortedIdx => (\n <tr key={sortedIdx} className=\"vpg-data-row\">\n {pivotResult.rowHeaders[sortedIdx].map((val, idx) => (\n <th\n key={`row-${sortedIdx}-${idx}`}\n className=\"vpg-row-header-cell\"\n style={{ width: `${rowHeaderColWidth}px`, minWidth: '80px', left: `${getRowHeaderLeftOffset(idx)}px` }}\n >\n {val}\n </th>\n ))}\n\n {pivotResult.data[sortedIdx].map((cell, colIdx) => {\n const displayRowIdx = sortedRowIndices.indexOf(sortedIdx)\n return (\n <td\n key={colIdx}\n className={`vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? 'selected' : ''} ${cell.value === null ? 'vpg-is-null' : ''}`}\n onMouseDown={e => handleCellMouseDown(displayRowIdx, colIdx, e)}\n onMouseEnter={() => handleCellMouseEnter(displayRowIdx, colIdx)}\n >\n {cell.formattedValue}\n </td>\n )\n })}\n\n {pivotResult.rowTotals[sortedIdx] && (\n <td className=\"vpg-data-cell vpg-total-cell\">\n {pivotResult.rowTotals[sortedIdx].formattedValue}\n </td>\n )}\n </tr>\n ))}\n\n {pivotResult.columnTotals.length > 0 && (\n <tr className=\"vpg-totals-row\">\n <th\n className=\"vpg-row-header-cell vpg-total-label\"\n colSpan={Math.max(rowFields.length, 1)}\n style={{ width: `${rowHeaderWidth}px` }}\n >\n Total\n </th>\n {pivotResult.columnTotals.map((cell, colIdx) => (\n <td key={colIdx} className=\"vpg-data-cell vpg-total-cell\">\n {cell.formattedValue}\n </td>\n ))}\n {pivotResult.rowTotals.length > 0 && (\n <td className=\"vpg-data-cell vpg-grand-total-cell\">\n {pivotResult.grandTotal.formattedValue}\n </td>\n )}\n </tr>\n )}\n </tbody>\n </table>\n </div>\n )}\n\n {/* Footer */}\n {isConfigured && pivotResult && (\n <div className=\"vpg-skeleton-footer\">\n <span className=\"vpg-footer-info\">\n {pivotResult.rowHeaders.length}\n {' '}\n rows ×\n {pivotResult.data[0]?.length || 0}\n {' '}\n columns\n </span>\n\n {selectionStats && selectionStats.count > 1 && (\n <div className=\"vpg-selection-stats\">\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Count:</span>\n <span className=\"vpg-stat-value\">{selectionStats.count}</span>\n </span>\n {selectionStats.numericCount > 0 && (\n <>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Sum:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.sum)}</span>\n </span>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Avg:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.avg)}</span>\n </span>\n </>\n )}\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {/* Watermark / Demo Banner */}\n {showWatermark && canUsePivot && (\n <div className={`vpg-watermark ${isDemo ? 'vpg-demo-mode' : ''}`}>\n {isDemo\n ? (\n <>\n <span className=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features unlocked for evaluation</span>\n <a\n href=\"https://tiny-pivot.com/#pricing\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"vpg-get-pro\"\n >\n Get Pro License →\n </a>\n </>\n )\n : (\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener noreferrer\">\n Powered by TinyPivot\n </a>\n )}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["import_tinypivot_core","import_react","messages","copyToClipboard","formatCellValue","import_tinypivot_core","import_react","import_jsx_runtime","import_tinypivot_core","import_react","import_jsx_runtime","React","chartData","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_react_dom","import_tinypivot_core","import_react","import_tinypivot_core","import_react","coreExportToCSV","coreExportPivotToCSV","coreCopyToClipboard","coreFormatSelection","import_tinypivot_core","import_react","coreConfigureLicenseSecret","coreIsPro","coreCanUsePivot","coreCanUseCharts","coreCanUseAIAnalyst","coreShouldShowWatermark","import_tinypivot_core","import_react","import_tinypivot_core","import_react","import_jsx_runtime","import_tinypivot_core","import_react","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/AIAnalyst.tsx","../src/hooks/useAIAnalyst.ts","../src/components/CalculatedFieldModal.tsx","../src/components/ChartBuilder.tsx","../src/components/ColumnFilter.tsx","../src/components/DateRangeFilter.tsx","../src/components/NumericRangeFilter.tsx","../src/components/DataGrid.tsx","../src/hooks/useExcelGrid.ts","../src/hooks/useGridFeatures.ts","../src/hooks/useLicense.ts","../src/hooks/usePivotTable.ts","../src/components/PivotConfig.tsx","../src/components/PivotSkeleton.tsx"],"sourcesContent":["/**\n * TinyPivot React\n * A powerful Excel-like data grid and pivot table component for React\n *\n * @packageDocumentation\n */\n\n// Components\nexport { AIAnalyst, ColumnFilter, DataGrid, PivotConfig, PivotSkeleton } from './components'\n\n// Hooks\nexport {\n configureLicenseSecret,\n copyToClipboard,\n enableDemoMode,\n exportPivotToCSV,\n exportToCSV,\n formatCellValue,\n formatSelectionForClipboard,\n getAggregationLabel,\n getColumnUniqueValues,\n setLicenseKey,\n useAIAnalyst,\n useColumnResize,\n useExcelGrid,\n useGlobalSearch,\n useLicense,\n usePagination,\n usePivotTable,\n useRowSelection,\n} from './hooks'\nexport type { UseAIAnalystOptions } from './hooks'\n\n// Re-export types from core\nexport type {\n // Pivot Types\n AggregationFunction,\n // AI Data Analyst Types\n AIAnalystConfig,\n AIColumnSchema,\n AIConversation,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIDataSource,\n AIErrorEvent,\n AIMessage,\n AIMessageMetadata,\n AIQueryExecutedEvent,\n\n AITableSchema,\n CellClickEvent,\n\n // Grid Types\n ColumnStats,\n CopyEvent,\n // Component Props Types\n DataGridProps,\n ExportEvent,\n ExportOptions,\n FieldStats,\n // Event Types\n FilterEvent,\n\n GridOptions,\n LicenseInfo,\n\n // License Types\n LicenseType,\n // Feature Types\n PaginationOptions,\n\n PivotCell,\n PivotConfig as PivotConfigType,\n PivotField,\n PivotResult,\n PivotTableProps,\n PivotValueField,\n RowSelectionChangeEvent,\n\n SelectionBounds,\n SelectionChangeEvent,\n SortEvent,\n} from '@smallwebco/tinypivot-core'\n","/**\n * TinyPivot React - AI Data Analyst Component\n * Split-panel layout: 1/4 chat, 3/4 data preview\n * Each query step shows data visually with expandable SQL\n */\nimport type {\n AIAnalystConfig,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIErrorEvent,\n AIMessage,\n AIQueryExecutedEvent,\n AITableSchema,\n} from '@smallwebco/tinypivot-core'\nimport { stripSQLFromContent } from '@smallwebco/tinypivot-core'\nimport React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'\nimport { useAIAnalyst } from '../hooks/useAIAnalyst'\n\ninterface AIAnalystProps {\n config: AIAnalystConfig\n theme?: 'light' | 'dark'\n onDataLoaded?: (payload: AIDataLoadedEvent) => void\n onConversationUpdate?: (payload: AIConversationUpdateEvent) => void\n onQueryExecuted?: (payload: AIQueryExecutedEvent) => void\n onError?: (payload: AIErrorEvent) => void\n onViewResults?: (payload: { data: Record<string, unknown>[], query: string }) => void\n}\n\nexport interface AIAnalystHandle {\n loadFullData: () => Promise<Record<string, unknown>[] | null>\n selectedDataSource: string | undefined\n}\n\nexport const AIAnalyst = forwardRef<AIAnalystHandle, AIAnalystProps>(({\n config,\n theme = 'light',\n onDataLoaded,\n onConversationUpdate,\n onQueryExecuted,\n onError,\n onViewResults,\n}, ref) => {\n const {\n messages,\n hasMessages,\n isLoading,\n isLoadingTables,\n schemas,\n selectedDataSource,\n selectedDataSourceInfo,\n lastLoadedData,\n dataSources,\n selectDataSource,\n sendMessage,\n clearConversation,\n loadFullData,\n } = useAIAnalyst({\n config,\n onDataLoaded,\n onConversationUpdate,\n onQueryExecuted,\n onError,\n })\n\n // Expose methods to parent via ref\n useImperativeHandle(ref, () => ({\n loadFullData,\n selectedDataSource,\n }), [loadFullData, selectedDataSource])\n\n const [inputText, setInputText] = useState('')\n const [searchQuery, setSearchQuery] = useState('')\n const [selectedMessageId, setSelectedMessageId] = useState<string | null>(null)\n const [showSqlPanel, setShowSqlPanel] = useState(false)\n const messagesContainerRef = useRef<HTMLDivElement>(null)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n // Filter data sources by search\n const filteredDataSources = useMemo(() => {\n if (!searchQuery.trim())\n return dataSources\n const q = searchQuery.toLowerCase()\n return dataSources.filter((ds: { name: string, description?: string, table: string }) =>\n ds.name.toLowerCase().includes(q)\n || ds.description?.toLowerCase().includes(q)\n || ds.table.toLowerCase().includes(q),\n )\n }, [dataSources, searchQuery])\n\n // Get schema for selected data source\n const currentSchema: AITableSchema | undefined = useMemo(() => {\n if (!selectedDataSource)\n return undefined\n return schemas.get(selectedDataSource)\n }, [selectedDataSource, schemas])\n\n // Get data for the selected message (or latest)\n const previewData = useMemo(() => {\n if (selectedMessageId) {\n const msg = messages.find((m: AIMessage) => m.id === selectedMessageId)\n if (msg?.metadata?.data) {\n return msg.metadata.data.slice(0, 100)\n }\n }\n if (!lastLoadedData)\n return []\n return lastLoadedData.slice(0, 100)\n }, [selectedMessageId, messages, lastLoadedData])\n\n // Get full data for the selected message\n const fullPreviewData = useMemo(() => {\n if (selectedMessageId) {\n const msg = messages.find((m: AIMessage) => m.id === selectedMessageId)\n if (msg?.metadata?.data) {\n return msg.metadata.data\n }\n }\n return lastLoadedData || []\n }, [selectedMessageId, messages, lastLoadedData])\n\n // Get column keys from preview data\n const previewColumns = useMemo(() => {\n if (previewData.length > 0) {\n return Object.keys(previewData[0])\n }\n if (currentSchema) {\n return currentSchema.columns.map((c: { name: string }) => c.name)\n }\n return []\n }, [previewData, currentSchema])\n\n // Get the selected message's query\n const selectedQuery = useMemo(() => {\n if (selectedMessageId) {\n const msg = messages.find((m: AIMessage) => m.id === selectedMessageId)\n return msg?.metadata?.query || ''\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].metadata?.data) {\n return messages[i].metadata?.query || ''\n }\n }\n return ''\n }, [selectedMessageId, messages])\n\n // Scroll to bottom when messages change and auto-select latest with data\n useEffect(() => {\n if (messagesContainerRef.current) {\n messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight\n }\n const latestWithData = [...messages].reverse().find((m: AIMessage) => m.metadata?.data)\n if (latestWithData) {\n setSelectedMessageId(latestWithData.id)\n }\n }, [messages])\n\n // Auto-resize textarea\n const autoResizeTextarea = useCallback(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`\n }\n }, [])\n\n useEffect(() => {\n autoResizeTextarea()\n }, [inputText, autoResizeTextarea])\n\n const handleSubmit = useCallback((e: React.FormEvent) => {\n e.preventDefault()\n if (!inputText.trim() || isLoading)\n return\n sendMessage(inputText)\n setInputText('')\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n }\n }, [inputText, isLoading, sendMessage])\n\n const handleKeydown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (!inputText.trim() || isLoading)\n return\n sendMessage(inputText)\n setInputText('')\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n }\n }\n }, [inputText, isLoading, sendMessage])\n\n const handleViewResults = useCallback(() => {\n if (fullPreviewData.length > 0) {\n onViewResults?.({ data: fullPreviewData, query: selectedQuery })\n }\n }, [fullPreviewData, selectedQuery, onViewResults])\n\n const selectMessage = useCallback((messageId: string) => {\n const msg = messages.find((m: AIMessage) => m.id === messageId)\n if (msg?.metadata?.data) {\n setSelectedMessageId(messageId)\n }\n }, [messages])\n\n const copyToClipboard = useCallback((text: string) => {\n navigator.clipboard.writeText(text)\n }, [])\n\n const handleClearConversation = useCallback(() => {\n clearConversation()\n setSearchQuery('')\n setSelectedMessageId(null)\n setShowSqlPanel(false)\n }, [clearConversation])\n\n const handleChangeDataSource = useCallback(() => {\n clearConversation()\n setSearchQuery('')\n setSelectedMessageId(null)\n setShowSqlPanel(false)\n }, [clearConversation])\n\n const toggleSqlPanel = useCallback(() => {\n setShowSqlPanel(prev => !prev)\n }, [])\n\n const getColumnTypeIcon = (type: string): string => {\n const t = type.toLowerCase()\n if (t.includes('int') || t.includes('float') || t.includes('decimal') || t.includes('number'))\n return '#'\n if (t.includes('date') || t.includes('time'))\n return 'D'\n if (t.includes('bool'))\n return '?'\n return 'T'\n }\n\n const formatCellValue = (value: unknown): string => {\n if (value === null || value === undefined)\n return ''\n if (typeof value === 'number') {\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n return String(value)\n }\n return String(value)\n }\n\n const getMessageContent = (message: AIMessage): string => {\n // Strip SQL blocks and clean up markdown formatting\n return stripSQLFromContent(message.content)\n .replace(/\\*\\*/g, '')\n .replace(/`([^`]+)`/g, '$1')\n .trim()\n }\n\n const hasQueryResult = (message: AIMessage): boolean => {\n return !!message.metadata?.data && message.metadata.data.length > 0\n }\n\n // Render data source picker (full screen)\n if (!selectedDataSource) {\n return (\n <div className={`vpg-ai-analyst ${theme === 'dark' ? 'vpg-theme-dark' : ''}`}>\n <div className=\"vpg-ai-picker-fullscreen\">\n <div className=\"vpg-ai-picker-content\">\n <div className=\"vpg-ai-picker-header\">\n <div className=\"vpg-ai-icon-lg\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z\" />\n <circle cx=\"7.5\" cy=\"14.5\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"16.5\" cy=\"14.5\" r=\"1.5\" fill=\"currentColor\" />\n </svg>\n </div>\n <h2>AI Data Analyst</h2>\n <p>Select a data source to start exploring with AI</p>\n </div>\n\n {dataSources.length === 0 && !isLoadingTables ? (\n <div className=\"vpg-ai-empty-state\">\n <p>No data sources configured.</p>\n <a\n href=\"https://tinypivot.com/docs/ai-analyst\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"vpg-ai-docs-link\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n View Documentation\n </a>\n </div>\n ) : (\n <>\n <div className=\"vpg-ai-search\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n <input\n type=\"text\"\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n placeholder=\"Search data sources...\"\n className=\"vpg-ai-search-input\"\n />\n </div>\n <div className=\"vpg-ai-datasource-grid\">\n {filteredDataSources.map((ds: { id: string, name: string, description?: string }) => (\n <button\n key={ds.id}\n className=\"vpg-ai-datasource-card\"\n onClick={() => selectDataSource(ds.id)}\n >\n <div className=\"vpg-ai-datasource-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n </div>\n <div className=\"vpg-ai-datasource-info\">\n <span className=\"vpg-ai-datasource-name\">{ds.name}</span>\n {ds.description && (\n <span className=\"vpg-ai-datasource-desc\">{ds.description}</span>\n )}\n </div>\n </button>\n ))}\n </div>\n {filteredDataSources.length === 0 && (\n <div className=\"vpg-ai-no-results\">\n No data sources match \"\n {searchQuery}\n \"\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n )\n }\n\n // Render split layout\n return (\n <div className={`vpg-ai-analyst ${theme === 'dark' ? 'vpg-theme-dark' : ''}`}>\n <div className=\"vpg-ai-split-layout\">\n {/* Left Panel: Chat */}\n <div className=\"vpg-ai-chat-panel\">\n {/* Chat Header */}\n <div className=\"vpg-ai-chat-header\">\n <button\n className=\"vpg-ai-back-btn\"\n title=\"Change data source\"\n onClick={handleChangeDataSource}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n <div className=\"vpg-ai-chat-title\">\n <span className=\"vpg-ai-chat-name\">{selectedDataSourceInfo?.name}</span>\n </div>\n {hasMessages && (\n <button\n className=\"vpg-ai-clear-btn\"\n title=\"Clear conversation\"\n onClick={handleClearConversation}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n </button>\n )}\n </div>\n\n {/* Messages */}\n <div ref={messagesContainerRef} className=\"vpg-ai-messages\">\n {/* Welcome message */}\n {!hasMessages && (\n <div className=\"vpg-ai-welcome\">\n <p>Ask questions about your data</p>\n <div className=\"vpg-ai-suggestions\">\n <button onClick={() => sendMessage('Show me a summary of the data')}>\n Summary\n </button>\n <button onClick={() => sendMessage('Show me the top 10 records')}>\n Top 10\n </button>\n <button onClick={() => sendMessage('What are the trends?')}>\n Trends\n </button>\n </div>\n </div>\n )}\n\n {/* Message list */}\n {messages.map((message: AIMessage) => {\n if (message.role === 'user') {\n return (\n <div key={message.id} className=\"vpg-ai-msg vpg-ai-msg-user\">\n <span>{message.content}</span>\n </div>\n )\n }\n\n if (hasQueryResult(message)) {\n return (\n <div\n key={message.id}\n className={`vpg-ai-msg vpg-ai-msg-result ${selectedMessageId === message.id ? 'vpg-ai-msg-selected' : ''}`}\n onClick={() => selectMessage(message.id)}\n >\n {/* Header with result badge and SQL toggle */}\n <div className=\"vpg-ai-result-header\">\n <div className=\"vpg-ai-result-badge\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <polyline points=\"22 4 12 14.01 9 11.01\" />\n </svg>\n <span>\n {message.metadata?.rowCount?.toLocaleString()}\n {' '}\n rows\n </span>\n </div>\n {/* SQL toggle button - toggles right pane SQL panel */}\n {message.metadata?.query && (\n <button\n className={`vpg-ai-sql-toggle ${showSqlPanel && selectedMessageId === message.id ? 'vpg-ai-sql-expanded' : ''}`}\n title=\"View SQL query\"\n onClick={(e) => {\n e.stopPropagation()\n toggleSqlPanel()\n }}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </svg>\n <span>SQL</span>\n </button>\n )}\n </div>\n {/* Full message content (insight from AI) */}\n <div className=\"vpg-ai-result-content\">\n {getMessageContent(message)}\n </div>\n </div>\n )\n }\n\n // Regular assistant message\n return (\n <div key={message.id} className=\"vpg-ai-msg vpg-ai-msg-assistant\">\n <div className=\"vpg-ai-assistant-content\">{getMessageContent(message)}</div>\n {message.metadata?.error && (\n <div className=\"vpg-ai-msg-error\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n Error\n </div>\n )}\n </div>\n )\n })}\n\n {/* Loading indicator */}\n {isLoading && (\n <div className=\"vpg-ai-msg vpg-ai-msg-loading\">\n <div className=\"vpg-ai-typing\">\n <span />\n <span />\n <span />\n </div>\n </div>\n )}\n </div>\n\n {/* Input Area */}\n <div className=\"vpg-ai-input-area\">\n <form className=\"vpg-ai-input-form\" onSubmit={handleSubmit}>\n <textarea\n ref={textareaRef}\n className=\"vpg-ai-input\"\n placeholder=\"Ask about your data...\"\n disabled={isLoading}\n rows={1}\n value={inputText}\n onChange={e => setInputText(e.target.value)}\n onKeyDown={handleKeydown}\n />\n <button\n type=\"submit\"\n className=\"vpg-ai-send-btn\"\n disabled={!inputText.trim() || isLoading}\n title=\"Send\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n </svg>\n </button>\n </form>\n {/* Input footer with model name and actions */}\n <div className=\"vpg-ai-input-footer\">\n {config.aiModelName && (\n <span className=\"vpg-ai-model-name\">{config.aiModelName}</span>\n )}\n <div className=\"vpg-ai-input-actions\">\n {fullPreviewData.length > 0 && (\n <button\n className=\"vpg-ai-action-btn vpg-ai-action-primary\"\n title=\"View in Grid tab\"\n onClick={handleViewResults}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n View in Grid\n </button>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* Right Panel: Data Scratchpad */}\n <div className=\"vpg-ai-preview-panel\">\n {/* Header with schema */}\n <div className=\"vpg-ai-preview-header\">\n <div className=\"vpg-ai-preview-title-row\">\n <h3>{selectedDataSourceInfo?.name}</h3>\n <div className=\"vpg-ai-preview-meta\">\n {fullPreviewData.length > 0 && (\n <span className=\"vpg-ai-preview-count\">\n {fullPreviewData.length.toLocaleString()}\n {' '}\n rows\n </span>\n )}\n {selectedQuery && (\n <button\n className={`vpg-ai-preview-sql-btn ${showSqlPanel ? 'vpg-ai-sql-active' : ''}`}\n title=\"Toggle SQL query\"\n onClick={toggleSqlPanel}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </svg>\n SQL\n </button>\n )}\n {fullPreviewData.length > 0 && (\n <button\n className=\"vpg-ai-preview-view-btn\"\n title=\"View in Grid\"\n onClick={handleViewResults}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" />\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\" />\n </svg>\n View in Grid\n </button>\n )}\n </div>\n </div>\n {/* Schema chips in preview header */}\n {currentSchema && (\n <div className=\"vpg-ai-schema-bar\">\n {currentSchema.columns.map((col: { name: string, type: string }) => (\n <div\n key={col.name}\n className=\"vpg-ai-schema-chip\"\n title={`${col.name} (${col.type})`}\n >\n <span className=\"vpg-ai-chip-type\">{getColumnTypeIcon(col.type)}</span>\n <span className=\"vpg-ai-chip-name\">{col.name}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* SQL Panel (expandable, above the table) */}\n {showSqlPanel && selectedQuery && (\n <div className=\"vpg-ai-sql-panel\">\n <div className=\"vpg-ai-sql-panel-header\">\n <span className=\"vpg-ai-sql-panel-title\">SQL Query</span>\n <div className=\"vpg-ai-sql-panel-actions\">\n <button\n className=\"vpg-ai-copy-btn\"\n title=\"Copy SQL\"\n onClick={() => copyToClipboard(selectedQuery)}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n </button>\n <button\n className=\"vpg-ai-sql-panel-close\"\n title=\"Close\"\n onClick={() => setShowSqlPanel(false)}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n </div>\n <pre className=\"vpg-ai-sql-panel-code\"><code>{selectedQuery}</code></pre>\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"vpg-ai-preview-loading\">\n <div className=\"vpg-ai-preview-spinner\" />\n <span>Running query...</span>\n </div>\n ) : previewData.length === 0 && currentSchema ? (\n /* Ready state (schema loaded, no data yet) */\n <div className=\"vpg-ai-preview-ready\">\n <div className=\"vpg-ai-preview-ready-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n <path d=\"M3 12c0 1.66 4 3 9 3s9-1.34 9-3\" />\n </svg>\n </div>\n <p>Data source connected</p>\n <span>\n {currentSchema.columns.length}\n {' '}\n columns available\n </span>\n <div className=\"vpg-ai-preview-hint\">\n Ask a question to explore the data\n </div>\n </div>\n ) : previewData.length === 0 ? (\n /* No schema loaded yet */\n <div className=\"vpg-ai-preview-empty\">\n <div className=\"vpg-ai-preview-empty-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </div>\n <p>Loading data source...</p>\n </div>\n ) : (\n /* Data table */\n <div className=\"vpg-ai-preview-table-container\">\n <table className=\"vpg-ai-preview-table\">\n <thead>\n <tr>\n {previewColumns.map((col: string) => (\n <th key={col}>{col}</th>\n ))}\n </tr>\n </thead>\n <tbody>\n {previewData.map((row: Record<string, unknown>, idx: number) => (\n <tr key={idx}>\n {previewColumns.map((col: string) => (\n <td key={col}>{formatCellValue(row[col])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {fullPreviewData.length > 100 && (\n <div className=\"vpg-ai-preview-more\">\n Showing 100 of\n {' '}\n {fullPreviewData.length.toLocaleString()}\n {' '}\n rows.\n <button onClick={handleViewResults}>View all in Grid</button>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n})\n","/**\n * TinyPivot React - AI Analyst Hook\n * Manages AI conversation state and data fetching\n */\nimport type {\n AIAnalystConfig,\n AIConversation,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIDataSource,\n AIErrorEvent,\n AIProxyResponse,\n AIQueryExecutedEvent,\n AITableSchema,\n ListTablesResponse,\n SchemaResponse,\n} from '@smallwebco/tinypivot-core'\nimport {\n addMessageToConversation,\n buildSystemPrompt,\n createAssistantMessage,\n createConversation,\n createUserMessage,\n extractSQLFromResponse,\n findDemoResponse,\n getDefaultDemoResponse,\n getDemoSchema,\n getInitialDemoData,\n getMessagesForAPI,\n setConversationDataSource,\n validateSQLSafety,\n} from '@smallwebco/tinypivot-core'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nexport interface UseAIAnalystOptions {\n config: AIAnalystConfig\n onDataLoaded?: (event: AIDataLoadedEvent) => void\n onConversationUpdate?: (event: AIConversationUpdateEvent) => void\n onQueryExecuted?: (event: AIQueryExecutedEvent) => void\n onError?: (event: AIErrorEvent) => void\n}\n\nexport function useAIAnalyst(options: UseAIAnalystOptions) {\n const { config, onDataLoaded, onConversationUpdate, onQueryExecuted, onError } = options\n\n // Use refs to avoid stale closures in callbacks\n const configRef = useRef(config)\n configRef.current = config\n\n // LocalStorage key for persistence\n const storageKey = config.persistToLocalStorage\n ? `tinypivot-ai-conversation-${config.sessionId || 'default'}`\n : null\n\n // Load initial conversation from localStorage if enabled\n const loadFromStorage = useCallback((): AIConversation => {\n if (storageKey && typeof window !== 'undefined') {\n try {\n const stored = localStorage.getItem(storageKey)\n if (stored) {\n const parsed = JSON.parse(stored)\n if (parsed.id && Array.isArray(parsed.messages)) {\n return parsed as AIConversation\n }\n }\n }\n catch (e) {\n console.warn('[TinyPivot] Failed to load conversation from localStorage:', e)\n }\n }\n return createConversation(config.sessionId)\n }, [storageKey, config.sessionId])\n\n // Save conversation to localStorage if enabled\n const saveToStorage = useCallback((conv: AIConversation) => {\n if (storageKey && typeof window !== 'undefined') {\n try {\n // Custom replacer to handle BigInt values (common in DuckDB results)\n const replacer = (_key: string, value: unknown) => {\n if (typeof value === 'bigint') {\n return Number(value)\n }\n return value\n }\n localStorage.setItem(storageKey, JSON.stringify(conv, replacer))\n }\n catch (e) {\n console.warn('[TinyPivot] Failed to save conversation to localStorage:', e)\n }\n }\n }, [storageKey])\n\n // State\n const [conversation, setConversation] = useState<AIConversation>(() => loadFromStorage())\n const [schemas, setSchemas] = useState<Map<string, AITableSchema>>(new Map())\n const [allSchemas, setAllSchemas] = useState<AITableSchema[]>([]) // All table schemas for JOINs\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [lastLoadedData, setLastLoadedData] = useState<Record<string, unknown>[] | null>(null)\n\n // Dynamic data sources (discovered from endpoint)\n const [discoveredDataSources, setDiscoveredDataSources] = useState<AIDataSource[]>([])\n const [isLoadingTables, setIsLoadingTables] = useState(false)\n\n // Get effective data sources (config or discovered)\n const effectiveDataSources = useMemo<AIDataSource[]>(() => {\n if (config.dataSources && config.dataSources.length > 0) {\n return config.dataSources\n }\n return discoveredDataSources\n }, [config.dataSources, discoveredDataSources])\n\n // Save to storage whenever conversation changes\n useEffect(() => {\n saveToStorage(conversation)\n }, [conversation, saveToStorage])\n\n // Computed values\n const selectedDataSource = conversation.dataSourceId\n const selectedDataSourceInfo = useMemo(\n () => effectiveDataSources.find((ds: AIDataSource) => ds.id === conversation.dataSourceId),\n [effectiveDataSources, conversation.dataSourceId],\n )\n const messages = conversation.messages\n const hasMessages = conversation.messages.length > 0\n\n /**\n * Fetch schemas for ALL tables at once (enables JOINs)\n */\n const fetchAllSchemas = useCallback(async () => {\n if (!configRef.current.endpoint)\n return\n\n try {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'get-all-schemas' }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch all schemas: ${response.statusText}`)\n }\n\n const data: SchemaResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n // Store all schemas for JOIN support\n setAllSchemas(data.schemas)\n\n // Also populate the individual schemas map\n setSchemas((prev) => {\n const newMap = new Map(prev)\n for (const schema of data.schemas) {\n newMap.set(schema.table, schema)\n }\n return newMap\n })\n }\n catch (err) {\n // Schema fetch is optional - continue without it\n console.warn('[TinyPivot] Failed to fetch all schemas:', err)\n }\n }, [])\n\n /**\n * Fetch available tables from endpoint (auto-discovery mode)\n */\n const fetchTables = useCallback(async () => {\n if (!configRef.current.endpoint)\n return\n\n setIsLoadingTables(true)\n try {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'list-tables' }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch tables: ${response.statusText}`)\n }\n\n const data: ListTablesResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n // Convert to AIDataSource format\n setDiscoveredDataSources(data.tables.map((t: { name: string, description?: string }) => ({\n id: t.name,\n table: t.name,\n name: t.name.charAt(0).toUpperCase() + t.name.slice(1), // Capitalize\n description: t.description,\n })))\n\n // Fetch all schemas for JOIN support\n await fetchAllSchemas()\n }\n catch (err) {\n console.warn('[TinyPivot] Failed to fetch tables:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to fetch tables',\n type: 'network',\n })\n }\n finally {\n setIsLoadingTables(false)\n }\n }, [onError, fetchAllSchemas])\n\n // Initialize: fetch tables if using endpoint\n useEffect(() => {\n if (configRef.current.endpoint && (!config.dataSources || config.dataSources.length === 0)) {\n fetchTables()\n }\n }, [fetchTables, config.dataSources])\n\n /**\n * Fetch schema from the unified endpoint\n */\n const fetchSchema = useCallback(async (dataSource: AIDataSource) => {\n if (!configRef.current.endpoint)\n return\n\n try {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'get-schema',\n tables: [dataSource.table],\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch schema: ${response.statusText}`)\n }\n\n const data: SchemaResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n if (data.schemas.length > 0) {\n setSchemas(prev => new Map(prev).set(dataSource.id, data.schemas[0]))\n }\n }\n catch (err) {\n // Schema fetch is optional - continue without it\n console.warn('Failed to fetch schema:', err)\n }\n }, [])\n\n /**\n * Fetch sample data (first 100 rows) from the unified endpoint\n */\n const fetchSampleData = useCallback(async (dataSource: AIDataSource) => {\n if (!configRef.current.endpoint)\n return\n\n try {\n const sql = `SELECT * FROM ${dataSource.table} LIMIT 100`\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'query',\n sql,\n table: dataSource.table,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch sample data: ${response.statusText}`)\n }\n\n const result = await response.json()\n\n if (result.error) {\n throw new Error(result.error)\n }\n\n if (result.data && result.data.length > 0) {\n setLastLoadedData(result.data)\n onDataLoaded?.({\n data: result.data,\n query: sql,\n dataSourceId: dataSource.id,\n rowCount: result.data.length,\n })\n }\n }\n catch (err) {\n // Sample data fetch is optional - continue without it\n console.warn('Failed to fetch sample data:', err)\n }\n }, [onDataLoaded])\n\n /**\n * Select a data source and fetch its schema\n */\n const selectDataSource = useCallback(async (dataSourceId: string) => {\n const dataSource = effectiveDataSources.find(ds => ds.id === dataSourceId)\n if (!dataSource) {\n setError(`Data source \"${dataSourceId}\" not found`)\n return\n }\n\n // Update conversation\n setConversation((prev) => {\n const updated = setConversationDataSource(prev, dataSourceId)\n const withMessage = addMessageToConversation(\n updated,\n createAssistantMessage(\n `I'm now connected to **${dataSource.name}**. ${dataSource.description || ''}\\n\\nWhat would you like to know about this data?`,\n ),\n )\n onConversationUpdate?.({ conversation: withMessage })\n return withMessage\n })\n\n // Load data source if custom loader is provided (demo mode)\n if (configRef.current.dataSourceLoader) {\n try {\n const { data, schema } = await configRef.current.dataSourceLoader(dataSourceId)\n if (schema) {\n setSchemas(prev => new Map(prev).set(dataSourceId, schema))\n }\n // Store the loaded data for the data source\n if (data && data.length > 0) {\n setLastLoadedData(data)\n onDataLoaded?.({\n data,\n query: `SELECT * FROM ${dataSource.table} LIMIT 100`,\n dataSourceId,\n rowCount: data.length,\n })\n }\n }\n catch (err) {\n console.warn('Failed to load data source:', err)\n }\n }\n // Fetch schema (demo mode uses mock schemas)\n else if (configRef.current.demoMode) {\n const demoSchema = getDemoSchema(dataSourceId)\n if (demoSchema) {\n setSchemas(prev => new Map(prev).set(dataSourceId, demoSchema))\n }\n // Load initial sample data for the preview\n const initialData = getInitialDemoData(dataSourceId)\n if (initialData) {\n setLastLoadedData(initialData)\n onDataLoaded?.({\n data: initialData,\n query: `SELECT * FROM ${dataSource.table} LIMIT 10`,\n dataSourceId,\n rowCount: initialData.length,\n })\n }\n }\n // Use endpoint for schema discovery and sample data\n else if (configRef.current.endpoint) {\n await fetchSchema(dataSource)\n await fetchSampleData(dataSource)\n }\n }, [effectiveDataSources, fetchSchema, fetchSampleData, onConversationUpdate, onDataLoaded])\n\n /**\n * Call the AI endpoint\n */\n const callAIEndpoint = useCallback(async (\n userInput: string,\n currentConversation: AIConversation,\n currentSchemas: Map<string, AITableSchema>,\n currentDataSources: AIDataSource[],\n currentAllSchemas: AITableSchema[],\n ): Promise<string> => {\n if (!configRef.current.endpoint) {\n throw new Error('No endpoint configured. Set `endpoint` in AI analyst config.')\n }\n\n const dataSourceId = currentConversation.dataSourceId\n\n // Build system prompt using effective data sources\n // Pass allSchemas to enable JOINs with related tables\n const systemPrompt = buildSystemPrompt(\n currentDataSources,\n currentSchemas,\n dataSourceId,\n currentAllSchemas.length > 0 ? currentAllSchemas : undefined,\n )\n\n // Get conversation messages for API\n const apiMessages = getMessagesForAPI(currentConversation)\n\n // Add system prompt and current user message\n const messages = [\n { role: 'user' as const, content: systemPrompt },\n { role: 'assistant' as const, content: 'I understand. I\\'m ready to help you analyze the data.' },\n ...apiMessages.slice(0, -1), // Exclude the just-added user message\n { role: 'user' as const, content: userInput },\n ]\n\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'chat', messages }),\n })\n\n if (!response.ok) {\n throw new Error(`AI request failed: ${response.statusText}`)\n }\n\n const data: AIProxyResponse = await response.json()\n\n if (data.error) {\n throw new Error(data.error)\n }\n\n return data.content\n }, [])\n\n /**\n * Execute a SQL query and update the specified message with results\n * @param sql The SQL query to execute\n * @param currentConversation Current conversation state\n * @param currentDataSources Available data sources\n * @param messageId Optional message ID to update with results (instead of adding new message)\n */\n const executeQuery = useCallback(async (\n sql: string,\n currentConversation: AIConversation,\n currentDataSources: AIDataSource[],\n messageId?: string,\n ) => {\n const dataSourceId = currentConversation.dataSourceId\n if (!dataSourceId)\n return\n\n const dataSource = currentDataSources.find((ds: { id: string }) => ds.id === dataSourceId)\n if (!dataSource)\n return\n\n const startTime = Date.now()\n\n try {\n let data: { data?: Record<string, unknown>[], rowCount?: number, truncated?: boolean, error?: string, success?: boolean }\n\n // Use custom query executor if provided (demo mode)\n if (configRef.current.queryExecutor) {\n const result = await configRef.current.queryExecutor(sql, dataSource.table)\n data = {\n data: result.data,\n rowCount: result.rowCount,\n truncated: result.truncated,\n error: result.error,\n success: !result.error,\n }\n }\n // Use unified endpoint\n else if (configRef.current.endpoint) {\n const response = await fetch(configRef.current.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'query',\n sql,\n table: dataSource.table,\n }),\n })\n\n data = await response.json()\n }\n else {\n throw new Error('No query executor or endpoint configured')\n }\n\n const duration = Date.now() - startTime\n\n if (!data.success || data.error) {\n // Add error message\n setConversation((prev: AIConversation) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `The query failed: ${data.error || 'Unknown error'}. Would you like me to try a different approach?`,\n { error: data.error, query: sql },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n onQueryExecuted?.({\n query: sql,\n rowCount: 0,\n duration,\n dataSourceId,\n success: false,\n error: data.error,\n })\n\n onError?.({\n message: data.error || 'Query failed',\n query: sql,\n type: 'query',\n })\n return\n }\n\n // Success - load data\n if (data.data) {\n setLastLoadedData(data.data)\n\n // Update the existing message with data, or add a new one if no messageId\n if (messageId) {\n // Find and update the existing message's metadata with the data\n setConversation((prev: AIConversation) => {\n const updatedMessages = prev.messages.map((msg) => {\n if (msg.id === messageId) {\n return {\n ...msg,\n metadata: {\n ...msg.metadata,\n data: data.data,\n rowCount: data.rowCount,\n truncated: data.truncated,\n },\n }\n }\n return msg\n })\n const updated = {\n ...prev,\n messages: updatedMessages,\n updatedAt: Date.now(),\n }\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n else {\n // Fallback: add a new message (shouldn't happen in normal flow)\n const truncatedNote = data.truncated\n ? ` (limited to ${configRef.current.maxRows || 10000} rows)`\n : ''\n\n setConversation((prev: AIConversation) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `Retrieved **${data.rowCount} rows**${truncatedNote}.`,\n { query: sql, rowCount: data.rowCount, data: data.data },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n\n onDataLoaded?.({\n data: data.data,\n query: sql,\n dataSourceId,\n rowCount: data.rowCount || data.data.length,\n })\n\n onQueryExecuted?.({\n query: sql,\n rowCount: data.rowCount || data.data.length,\n duration,\n dataSourceId,\n success: true,\n })\n }\n }\n catch (err) {\n const duration = Date.now() - startTime\n const errorMsg = err instanceof Error ? err.message : 'Query execution failed'\n\n setConversation((prev: AIConversation) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `Failed to execute query: ${errorMsg}`,\n { error: errorMsg, query: sql },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n onQueryExecuted?.({\n query: sql,\n rowCount: 0,\n duration,\n dataSourceId,\n success: false,\n error: errorMsg,\n })\n\n onError?.({\n message: errorMsg,\n query: sql,\n type: 'network',\n })\n }\n }, [onConversationUpdate, onDataLoaded, onQueryExecuted, onError])\n\n /**\n * Handle demo mode responses\n */\n const handleDemoResponse = useCallback(async (\n userInput: string,\n currentConversation: AIConversation,\n ) => {\n // Simulate loading delay\n await new Promise(resolve => setTimeout(resolve, 800))\n\n const dataSourceId = currentConversation.dataSourceId\n\n if (!dataSourceId) {\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n 'Please select a data source first by clicking one of the options above.',\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n return\n }\n\n // Find matching demo response\n const demoTrigger = findDemoResponse(dataSourceId, userInput)\n\n if (demoTrigger) {\n // Add AI response\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(demoTrigger.response, {\n query: demoTrigger.query,\n rowCount: demoTrigger.mockData?.length,\n }),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n // Load mock data\n if (demoTrigger.mockData) {\n setLastLoadedData(demoTrigger.mockData)\n\n onDataLoaded?.({\n data: demoTrigger.mockData,\n query: demoTrigger.query || '',\n dataSourceId,\n rowCount: demoTrigger.mockData.length,\n })\n\n onQueryExecuted?.({\n query: demoTrigger.query || '',\n rowCount: demoTrigger.mockData.length,\n duration: 150, // Fake duration\n dataSourceId,\n success: true,\n })\n }\n }\n else {\n // Use default response\n const defaultResponse = getDefaultDemoResponse(dataSourceId)\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(defaultResponse),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n }, [onConversationUpdate, onDataLoaded, onQueryExecuted])\n\n /**\n * Send a message to the AI\n */\n const sendMessage = useCallback(async (content: string) => {\n if (!content.trim())\n return\n if (isLoading)\n return\n\n setError(null)\n setIsLoading(true)\n\n // Add user message\n let updatedConversation: AIConversation\n setConversation((prev) => {\n updatedConversation = addMessageToConversation(prev, createUserMessage(content))\n onConversationUpdate?.({ conversation: updatedConversation })\n return updatedConversation\n })\n\n try {\n // Wait for state to update\n await new Promise(resolve => setTimeout(resolve, 0))\n\n // Get current state\n const currentConv = updatedConversation!\n\n // Handle demo mode\n if (configRef.current.demoMode) {\n await handleDemoResponse(content, currentConv)\n return\n }\n\n // Check if data source is selected\n if (!currentConv.dataSourceId) {\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n 'Please select a data source first by clicking one of the options above.',\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n return\n }\n\n // Call AI endpoint\n const aiResponse = await callAIEndpoint(content, currentConv, schemas, effectiveDataSources, allSchemas)\n\n // Check if AI wants to run a query\n const sqlQuery = extractSQLFromResponse(aiResponse)\n\n if (sqlQuery) {\n // Validate SQL\n const validation = validateSQLSafety(sqlQuery)\n if (!validation.valid) {\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `I generated an invalid query: ${validation.error}. Let me try again with a corrected approach.`,\n { error: validation.error },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n return\n }\n\n // Create the AI message and capture its ID for updating with query results\n const aiMessage = createAssistantMessage(aiResponse, { query: sqlQuery })\n\n setConversation((prev) => {\n const updated = addMessageToConversation(prev, aiMessage)\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n // Execute query and update the same message with data\n await executeQuery(sqlQuery, currentConv, effectiveDataSources, aiMessage.id)\n }\n else {\n // Just add AI response\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(aiResponse),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n }\n }\n catch (err) {\n const errorMsg = err instanceof Error ? err.message : 'An error occurred'\n setError(errorMsg)\n\n setConversation((prev) => {\n const updated = addMessageToConversation(\n prev,\n createAssistantMessage(\n `Sorry, I encountered an error: ${errorMsg}. Please try again.`,\n { error: errorMsg },\n ),\n )\n onConversationUpdate?.({ conversation: updated })\n return updated\n })\n\n onError?.({\n message: errorMsg,\n type: 'ai',\n })\n }\n finally {\n setIsLoading(false)\n }\n }, [isLoading, schemas, effectiveDataSources, callAIEndpoint, executeQuery, handleDemoResponse, onConversationUpdate, onError])\n\n /**\n * Load full data for the currently selected data source\n * Returns the full dataset (not limited) for displaying in the grid\n */\n const loadFullData = useCallback(async (): Promise<Record<string, unknown>[] | null> => {\n const dataSourceId = conversation.dataSourceId\n if (!dataSourceId) {\n return null\n }\n\n const dataSource = effectiveDataSources.find(ds => ds.id === dataSourceId)\n if (!dataSource) {\n return null\n }\n\n const currentConfig = configRef.current\n\n // Use custom data source loader if provided\n if (currentConfig.dataSourceLoader) {\n try {\n const { data } = await currentConfig.dataSourceLoader(dataSourceId)\n if (data && data.length > 0) {\n return data\n }\n }\n catch (err) {\n console.warn('Failed to load full data:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to load full data',\n type: 'network',\n })\n }\n return null\n }\n\n // Use query executor to get all data\n if (currentConfig.queryExecutor) {\n try {\n const result = await currentConfig.queryExecutor(\n `SELECT * FROM ${dataSource.table}`,\n dataSource.table,\n )\n if (result.data && result.data.length > 0) {\n return result.data\n }\n }\n catch (err) {\n console.warn('Failed to load full data via query:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to load full data',\n type: 'network',\n })\n }\n return null\n }\n\n // Use endpoint query action\n if (currentConfig.endpoint) {\n try {\n const response = await fetch(currentConfig.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'query',\n sql: `SELECT * FROM ${dataSource.table}`,\n table: dataSource.table,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to load data: ${response.statusText}`)\n }\n\n const data = await response.json()\n if (data.data && data.data.length > 0) {\n return data.data\n }\n }\n catch (err) {\n console.warn('Failed to load full data from endpoint:', err)\n onError?.({\n message: err instanceof Error ? err.message : 'Failed to load full data',\n type: 'network',\n })\n }\n return null\n }\n\n // Demo mode - get initial data\n if (currentConfig.demoMode) {\n const initialData = getInitialDemoData(dataSourceId)\n return initialData || null\n }\n\n return null\n }, [conversation.dataSourceId, effectiveDataSources, onError])\n\n /**\n * Clear the conversation\n */\n const clearConversation = useCallback(() => {\n const newConv = createConversation(configRef.current.sessionId)\n setConversation(newConv)\n setError(null)\n setLastLoadedData(null)\n onConversationUpdate?.({ conversation: newConv })\n }, [onConversationUpdate])\n\n /**\n * Export conversation for persistence\n */\n const exportConversation = useCallback((): AIConversation => {\n return { ...conversation }\n }, [conversation])\n\n /**\n * Import a conversation\n */\n const importConversation = useCallback((conv: AIConversation) => {\n setConversation(conv)\n onConversationUpdate?.({ conversation: conv })\n }, [onConversationUpdate])\n\n return {\n // State\n conversation,\n messages,\n hasMessages,\n schemas,\n isLoading,\n isLoadingTables,\n error,\n lastLoadedData,\n selectedDataSource,\n selectedDataSourceInfo,\n /** Available data sources (either from config or auto-discovered) */\n dataSources: effectiveDataSources,\n\n // Actions\n selectDataSource,\n sendMessage,\n clearConversation,\n exportConversation,\n importConversation,\n /** Refresh table list from endpoint */\n fetchTables,\n /** Load full data for the currently selected data source */\n loadFullData,\n }\n}\n","import type { CalculatedField } from '@smallwebco/tinypivot-core'\nimport { validateSimpleFormula } from '@smallwebco/tinypivot-core'\n/**\n * Calculated Field Modal for React\n * UI for creating custom calculated fields with formulas\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\ninterface CalculatedFieldModalProps {\n show: boolean\n availableFields: string[]\n existingField?: CalculatedField | null\n onClose: () => void\n onSave: (field: CalculatedField) => void\n}\n\nexport function CalculatedFieldModal({\n show,\n availableFields,\n existingField,\n onClose,\n onSave,\n}: CalculatedFieldModalProps) {\n // Form state\n const [name, setName] = useState('')\n const [formula, setFormula] = useState('')\n const [formatAs, setFormatAs] = useState<'number' | 'percent' | 'currency'>('number')\n const [decimals, setDecimals] = useState(2)\n const [error, setError] = useState<string | null>(null)\n\n // Reset form when modal opens\n useEffect(() => {\n if (show) {\n if (existingField) {\n setName(existingField.name)\n setFormula(existingField.formula)\n setFormatAs(existingField.formatAs || 'number')\n setDecimals(existingField.decimals ?? 2)\n }\n else {\n setName('')\n setFormula('')\n setFormatAs('number')\n setDecimals(2)\n }\n setError(null)\n }\n }, [show, existingField])\n\n // Validate formula on change\n const validationError = useMemo(() => {\n if (!formula.trim())\n return null\n return validateSimpleFormula(formula, availableFields)\n }, [formula, availableFields])\n\n // Insert field into formula\n const insertField = useCallback((field: string) => {\n setFormula((prev) => {\n if (prev.trim() && !prev.endsWith(' ')) {\n return `${prev} ${field}`\n }\n return prev + field\n })\n }, [])\n\n // Insert operator into formula\n const insertOperator = useCallback((op: string) => {\n setFormula((prev) => {\n if (prev.trim() && !prev.endsWith(' ')) {\n return `${prev} ${op} `\n }\n return `${prev + op} `\n })\n }, [])\n\n // Save calculated field\n const handleSave = useCallback(() => {\n if (!name.trim()) {\n setError('Name is required')\n return\n }\n\n const validationResult = validateSimpleFormula(formula, availableFields)\n if (validationResult) {\n setError(validationResult)\n return\n }\n\n const field: CalculatedField = {\n id: existingField?.id || `calc_${Date.now()}`,\n name: name.trim(),\n formula: formula.trim(),\n formatAs,\n decimals,\n }\n\n onSave(field)\n onClose()\n }, [name, formula, formatAs, decimals, existingField, availableFields, onSave, onClose])\n\n // Handle overlay click\n const handleOverlayClick = useCallback((e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose()\n }\n }, [onClose])\n\n if (!show)\n return null\n\n const modalContent = (\n <div className=\"vpg-modal-overlay\" onClick={handleOverlayClick}>\n <div className=\"vpg-modal\">\n <div className=\"vpg-modal-header\">\n <h3>\n {existingField ? 'Edit' : 'Create'}\n {' '}\n Calculated Field\n </h3>\n <button className=\"vpg-modal-close\" onClick={onClose}>×</button>\n </div>\n\n <div className=\"vpg-modal-body\">\n {/* Name */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label\">Name</label>\n <input\n type=\"text\"\n className=\"vpg-input\"\n placeholder=\"e.g., Profit Margin %\"\n value={name}\n onChange={e => setName(e.target.value)}\n />\n </div>\n\n {/* Formula */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label\">Formula</label>\n <textarea\n className=\"vpg-textarea\"\n placeholder=\"e.g., revenue / units\"\n rows={2}\n value={formula}\n onChange={e => setFormula(e.target.value)}\n />\n <div className=\"vpg-formula-hint\">Use field names with math operators: + - * / ( )</div>\n {validationError && <div className=\"vpg-error\">{validationError}</div>}\n </div>\n\n {/* Quick Insert: Operators */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label-small\">Operators</label>\n <div className=\"vpg-button-group\">\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('+')}>+</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('-')}>−</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('*')}>×</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('/')}>÷</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator('(')}>(</button>\n <button className=\"vpg-insert-btn vpg-op-btn\" onClick={() => insertOperator(')')}>)</button>\n </div>\n </div>\n\n {/* Quick Insert: Fields (numeric only) */}\n <div className=\"vpg-form-group\">\n <label className=\"vpg-label-small\">Insert Field</label>\n {availableFields.length > 0\n ? (\n <div className=\"vpg-button-group vpg-field-buttons\">\n {availableFields.map(field => (\n <button\n key={field}\n className=\"vpg-insert-btn vpg-field-btn\"\n onClick={() => insertField(field)}\n >\n {field}\n </button>\n ))}\n </div>\n )\n : (\n <div className=\"vpg-no-fields\">No numeric fields available</div>\n )}\n </div>\n\n {/* Format Options */}\n <div className=\"vpg-form-row\">\n <div className=\"vpg-form-group vpg-form-group-half\">\n <label className=\"vpg-label\">Format As</label>\n <select\n className=\"vpg-select\"\n value={formatAs}\n onChange={e => setFormatAs(e.target.value as 'number' | 'percent' | 'currency')}\n >\n <option value=\"number\">Number</option>\n <option value=\"percent\">Percentage</option>\n <option value=\"currency\">Currency ($)</option>\n </select>\n </div>\n <div className=\"vpg-form-group vpg-form-group-half\">\n <label className=\"vpg-label\">Decimals</label>\n <input\n type=\"number\"\n className=\"vpg-input\"\n min={0}\n max={6}\n value={decimals}\n onChange={e => setDecimals(Number(e.target.value))}\n />\n </div>\n </div>\n\n {/* Error */}\n {error && <div className=\"vpg-error vpg-error-box\">{error}</div>}\n </div>\n\n <div className=\"vpg-modal-footer\">\n <button className=\"vpg-btn vpg-btn-secondary\" onClick={onClose}>Cancel</button>\n <button className=\"vpg-btn vpg-btn-primary\" onClick={handleSave}>\n {existingField ? 'Update' : 'Add'}\n {' '}\n Field\n </button>\n </div>\n </div>\n </div>\n )\n\n // Guard for SSR\n if (typeof document === 'undefined')\n return null\n return createPortal(modalContent, document.body)\n}\n","import type {\n ChartAggregation,\n ChartConfig,\n ChartFieldInfo,\n ChartType,\n} from '@smallwebco/tinypivot-core'\n/**\n * TinyPivot React - Chart Builder Component\n * Drag-and-drop chart configuration with ApexCharts rendering\n */\nimport type { ApexOptions } from 'apexcharts'\nimport {\n analyzeFieldsForChart,\n CHART_AGGREGATIONS,\n CHART_COLORS,\n CHART_TYPES,\n createDefaultChartConfig,\n getChartGuidance,\n isChartConfigValid,\n processChartData,\n processChartDataForHeatmap,\n processChartDataForPie,\n processChartDataForScatter,\n} from '@smallwebco/tinypivot-core'\nimport React, { Suspense, useCallback, useEffect, useMemo, useState } from 'react'\n\n// Lazy load ApexCharts to avoid SSR issues (window not defined in Node.js)\nconst Chart = React.lazy(() => import('react-apexcharts'))\n\ninterface ChartBuilderProps {\n data: Record<string, unknown>[]\n theme?: 'light' | 'dark'\n onConfigChange?: (config: ChartConfig) => void\n}\n\nexport function ChartBuilder({\n data,\n theme = 'light',\n onConfigChange,\n}: ChartBuilderProps) {\n // Chart configuration state\n const [chartConfig, setChartConfig] = useState<ChartConfig>(createDefaultChartConfig())\n\n // Drag state\n const [draggingField, setDraggingField] = useState<ChartFieldInfo | null>(null)\n const [dragOverZone, setDragOverZone] = useState<string | null>(null)\n\n // Field analysis\n const fieldInfos = useMemo(() => analyzeFieldsForChart(data), [data])\n\n // Separate fields by role\n const dimensions = useMemo(\n () => fieldInfos.filter(f => f.role === 'dimension' || f.role === 'temporal'),\n [fieldInfos],\n )\n const measures = useMemo(\n () => fieldInfos.filter(f => f.role === 'measure'),\n [fieldInfos],\n )\n\n // Current guidance message\n const guidance = useMemo(() => getChartGuidance(chartConfig), [chartConfig])\n\n // Check if chart is ready to render\n const chartIsValid = useMemo(() => isChartConfigValid(chartConfig), [chartConfig])\n\n // Get currently selected chart type info\n const selectedChartType = useMemo(\n () => CHART_TYPES.find(ct => ct.type === chartConfig.type),\n [chartConfig.type],\n )\n\n // Check if scatter/bubble needs numeric fields\n const isScatterType = useMemo(\n () => ['scatter', 'bubble'].includes(chartConfig.type),\n [chartConfig.type],\n )\n const isHeatmapType = useMemo(\n () => chartConfig.type === 'heatmap',\n [chartConfig.type],\n )\n\n // Dynamic zone labels based on chart type\n const zoneLabels = useMemo(() => {\n const type = chartConfig.type\n switch (type) {\n case 'scatter':\n case 'bubble':\n return {\n xAxis: 'X-Axis (measure)',\n xAxisPlaceholder: 'Drop a measure',\n yAxis: 'Y-Axis (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: 'Color by (optional)',\n seriesPlaceholder: 'Group points by dimension',\n showSize: type === 'bubble',\n showSeries: true,\n }\n case 'heatmap':\n return {\n xAxis: 'X-Axis (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Y-Axis (dimension)',\n yAxisPlaceholder: 'Drop a dimension',\n series: 'Value / Intensity',\n seriesPlaceholder: 'Drop a measure for color intensity',\n showSize: false,\n showSeries: true,\n }\n case 'pie':\n case 'donut':\n return {\n xAxis: 'Slices (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Values (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: '',\n seriesPlaceholder: '',\n showSize: false,\n showSeries: false,\n }\n case 'radar':\n return {\n xAxis: 'Axes (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Values (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: 'Compare by (optional)',\n seriesPlaceholder: 'Group by dimension',\n showSize: false,\n showSeries: true,\n }\n default: // bar, line, area\n return {\n xAxis: 'X-Axis (dimension)',\n xAxisPlaceholder: 'Drop a dimension',\n yAxis: 'Y-Axis (measure)',\n yAxisPlaceholder: 'Drop a measure',\n series: 'Color / Series (optional)',\n seriesPlaceholder: 'Group by dimension',\n showSize: false,\n showSeries: true,\n }\n }\n }, [chartConfig.type])\n\n // Drag handlers\n const handleDragStart = useCallback((field: ChartFieldInfo, event: React.DragEvent) => {\n setDraggingField(field)\n event.dataTransfer?.setData('text/plain', field.field)\n }, [])\n\n const handleDragEnd = useCallback(() => {\n setDraggingField(null)\n setDragOverZone(null)\n }, [])\n\n const handleDragOver = useCallback((zone: string, event: React.DragEvent) => {\n event.preventDefault()\n setDragOverZone(zone)\n }, [])\n\n const handleDragLeave = useCallback(() => {\n setDragOverZone(null)\n }, [])\n\n const handleDrop = useCallback((zone: string, event: React.DragEvent) => {\n event.preventDefault()\n setDragOverZone(null)\n\n if (!draggingField)\n return\n\n const field = draggingField\n const chartField = {\n field: field.field,\n label: field.label,\n role: field.role,\n aggregation: field.role === 'measure' ? 'sum' as ChartAggregation : undefined,\n }\n\n let newConfig = { ...chartConfig }\n switch (zone) {\n case 'xAxis':\n newConfig = { ...newConfig, xAxis: chartField }\n break\n case 'yAxis':\n newConfig = { ...newConfig, yAxis: chartField }\n break\n case 'series':\n newConfig = { ...newConfig, seriesField: chartField }\n break\n case 'size':\n newConfig = { ...newConfig, sizeField: chartField }\n break\n case 'color':\n newConfig = { ...newConfig, colorField: chartField }\n break\n }\n\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, draggingField, onConfigChange])\n\n const removeField = useCallback((zone: string) => {\n let newConfig = { ...chartConfig }\n switch (zone) {\n case 'xAxis':\n newConfig = { ...newConfig, xAxis: undefined }\n break\n case 'yAxis':\n newConfig = { ...newConfig, yAxis: undefined }\n break\n case 'series':\n newConfig = { ...newConfig, seriesField: undefined }\n break\n case 'size':\n newConfig = { ...newConfig, sizeField: undefined }\n break\n case 'color':\n newConfig = { ...newConfig, colorField: undefined }\n break\n }\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, onConfigChange])\n\n const selectChartType = useCallback((type: ChartType) => {\n const newConfig = { ...chartConfig, type }\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, onConfigChange])\n\n const updateAggregation = useCallback((zone: string, aggregation: ChartAggregation) => {\n let field\n switch (zone) {\n case 'xAxis':\n field = chartConfig.xAxis\n break\n case 'yAxis':\n field = chartConfig.yAxis\n break\n case 'size':\n field = chartConfig.sizeField\n break\n case 'color':\n field = chartConfig.colorField\n break\n default:\n return\n }\n if (!field)\n return\n\n const updated = { ...field, aggregation }\n let newConfig = { ...chartConfig }\n switch (zone) {\n case 'xAxis':\n newConfig = { ...newConfig, xAxis: updated }\n break\n case 'yAxis':\n newConfig = { ...newConfig, yAxis: updated }\n break\n case 'size':\n newConfig = { ...newConfig, sizeField: updated }\n break\n case 'color':\n newConfig = { ...newConfig, colorField: updated }\n break\n }\n setChartConfig(newConfig)\n onConfigChange?.(newConfig)\n }, [chartConfig, onConfigChange])\n\n // Chart rendering helpers\n type ApexChartType = 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'heatmap' | 'bubble'\n\n const getApexChartType = useCallback((type: ChartType): ApexChartType => {\n const mapping: Record<ChartType, ApexChartType> = {\n bar: 'bar',\n line: 'line',\n area: 'area',\n pie: 'pie',\n donut: 'donut',\n radar: 'radar',\n scatter: 'scatter',\n bubble: 'bubble',\n heatmap: 'heatmap',\n }\n return mapping[type] || 'bar'\n }, [])\n\n const formatValue = useCallback((val: unknown, format?: string, decimals?: number): string => {\n // Handle non-number values (ApexCharts sometimes passes strings or undefined)\n if (val === null || val === undefined)\n return ''\n if (typeof val !== 'number')\n return String(val)\n if (Number.isNaN(val))\n return ''\n\n const dec = decimals ?? 0\n if (format === 'percent') {\n return `${val.toFixed(dec)}%`\n }\n if (format === 'currency') {\n return `$${val.toLocaleString(undefined, { minimumFractionDigits: dec, maximumFractionDigits: dec })}`\n }\n if (Math.abs(val) >= 1000) {\n return val.toLocaleString(undefined, { maximumFractionDigits: dec })\n }\n return val.toFixed(dec)\n }, [])\n\n // Chart options\n const chartOptions = useMemo<ApexOptions>(() => {\n const isDark = theme === 'dark'\n const config = chartConfig\n const options = config.options || {}\n\n const baseOptions: ApexOptions = {\n chart: {\n type: getApexChartType(config.type),\n background: 'transparent',\n foreColor: isDark ? '#e2e8f0' : '#334155',\n toolbar: {\n show: true,\n tools: {\n download: true,\n selection: false,\n zoom: options.enableZoom ?? false,\n zoomin: options.enableZoom ?? false,\n zoomout: options.enableZoom ?? false,\n pan: false,\n reset: options.enableZoom ?? false,\n },\n export: {\n csv: { filename: 'chart-data' },\n svg: { filename: 'chart' },\n png: { filename: 'chart' },\n },\n },\n animations: {\n enabled: options.animated ?? true,\n speed: 400,\n dynamicAnimation: { enabled: true, speed: 300 },\n },\n fontFamily: 'system-ui, -apple-system, sans-serif',\n },\n colors: options.colors || CHART_COLORS,\n theme: {\n mode: isDark ? 'dark' : 'light',\n },\n grid: {\n show: options.showGrid ?? true,\n borderColor: isDark ? '#334155' : '#e2e8f0',\n },\n legend: {\n show: options.showLegend ?? true,\n position: options.legendPosition || 'top',\n },\n dataLabels: {\n enabled: options.showDataLabels ?? false,\n },\n tooltip: {\n theme: isDark ? 'dark' : 'light',\n style: {\n fontSize: '12px',\n },\n },\n stroke: {\n curve: 'smooth',\n width: config.type === 'line' ? 3 : config.type === 'area' ? 2 : 0,\n },\n fill: {\n opacity: config.type === 'area' ? 0.4 : 1,\n },\n }\n\n // Add axis titles\n if (config.xAxis) {\n baseOptions.xaxis = {\n ...baseOptions.xaxis,\n title: { text: options.xAxisTitle || config.xAxis.label },\n labels: {\n style: { colors: isDark ? '#94a3b8' : '#64748b' },\n },\n }\n }\n\n if (config.yAxis && !['pie', 'donut', 'radar'].includes(config.type)) {\n baseOptions.yaxis = {\n title: { text: options.yAxisTitle || config.yAxis.label },\n labels: {\n style: { colors: isDark ? '#94a3b8' : '#64748b' },\n formatter: (val: number) => formatValue(val, options.valueFormat, options.decimals),\n },\n }\n }\n\n // Chart title\n if (options.title) {\n baseOptions.title = {\n text: options.title,\n style: {\n fontSize: '16px',\n fontWeight: '600',\n color: isDark ? '#e2e8f0' : '#334155',\n },\n }\n }\n\n // Stacking\n if (options.stacked && ['bar', 'area'].includes(config.type)) {\n baseOptions.chart!.stacked = true\n }\n\n // Pie/Donut specific\n if (config.type === 'pie' || config.type === 'donut') {\n baseOptions.plotOptions = {\n pie: {\n donut: {\n size: config.type === 'donut' ? '55%' : '0%',\n labels: {\n show: config.type === 'donut',\n total: {\n show: true,\n label: 'Total',\n formatter: (w) => {\n const total = w.globals.seriesTotals.reduce((a: number, b: number) => a + b, 0)\n return formatValue(total, options.valueFormat, options.decimals)\n },\n },\n },\n },\n },\n }\n }\n\n // Radar specific\n if (config.type === 'radar') {\n baseOptions.plotOptions = {\n radar: {\n polygons: {\n strokeColors: isDark ? '#334155' : '#e2e8f0',\n fill: { colors: isDark ? ['#1e293b', '#0f172a'] : ['#f8fafc', '#f1f5f9'] },\n },\n },\n }\n }\n\n return baseOptions\n }, [chartConfig, theme, getApexChartType, formatValue])\n\n const chartSeries = useMemo(() => {\n const config = chartConfig\n\n if (!chartIsValid)\n return []\n\n // Process based on chart type\n if (config.type === 'pie' || config.type === 'donut') {\n const chartData = processChartDataForPie(data, config)\n return chartData.series[0]?.data || []\n }\n\n if (config.type === 'scatter' || config.type === 'bubble') {\n const scatterData = processChartDataForScatter(data, config)\n return scatterData.series\n }\n\n if (config.type === 'heatmap') {\n const heatmapData = processChartDataForHeatmap(data, config)\n return heatmapData.series\n }\n\n // Standard charts (bar, line, area, etc.)\n const chartData = processChartData(data, config)\n return chartData.series\n }, [data, chartConfig, chartIsValid])\n\n const chartLabels = useMemo(() => {\n const config = chartConfig\n\n if (!chartIsValid)\n return []\n\n if (config.type === 'pie' || config.type === 'donut') {\n const chartData = processChartDataForPie(data, config)\n return chartData.categories\n }\n\n const chartData = processChartData(data, config)\n return chartData.categories\n }, [data, chartConfig, chartIsValid])\n\n // Update xaxis categories in options\n const chartOptionsWithCategories = useMemo<ApexOptions>(() => {\n const options = { ...chartOptions }\n const config = chartConfig\n\n // Heatmap, scatter, bubble have x values in data itself\n if (!['pie', 'donut', 'scatter', 'bubble', 'heatmap'].includes(config.type)) {\n options.xaxis = {\n ...options.xaxis,\n categories: chartLabels,\n }\n }\n\n if (config.type === 'pie' || config.type === 'donut') {\n options.labels = chartLabels\n }\n\n // Heatmap specific options\n if (config.type === 'heatmap') {\n options.chart = {\n ...options.chart,\n type: 'heatmap',\n }\n options.xaxis = {\n ...options.xaxis,\n type: 'category',\n }\n options.dataLabels = {\n enabled: true,\n style: {\n colors: ['#fff'],\n fontSize: '10px',\n },\n formatter: (val: unknown) => {\n if (val === null || val === undefined)\n return ''\n if (typeof val !== 'number')\n return String(val)\n if (val >= 1000000)\n return `${(val / 1000000).toFixed(1)}M`\n if (val >= 1000)\n return `${(val / 1000).toFixed(0)}K`\n return Math.round(val).toLocaleString()\n },\n }\n options.plotOptions = {\n heatmap: {\n shadeIntensity: 0.5,\n radius: 2,\n enableShades: true,\n colorScale: {\n inverse: false,\n },\n },\n }\n // Use a single color that varies by intensity\n options.colors = ['#6366f1']\n // Disable legend for heatmap (color scale is self-explanatory)\n options.legend = { show: false }\n }\n\n return options\n }, [chartOptions, chartConfig, chartLabels])\n\n // Icons for chart types (inline SVG paths)\n const getChartIcon = useCallback((type: ChartType): string => {\n const icons: Record<ChartType, string> = {\n bar: 'M3 3v18h18V3H3zm4 14H5v-6h2v6zm4 0H9V7h2v10zm4 0h-2V9h2v8zm4 0h-2v-4h2v4z',\n line: 'M3.5 18.5l6-6 4 4 8-8M14.5 8.5h6v6',\n area: 'M3 17l6-6 4 4 8-8v10H3z',\n pie: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8v8l5.66 5.66C14.28 19.04 13.18 20 12 20z',\n donut: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z',\n scatter: 'M7 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm-3 4a2 2 0 1 0 0-4 2 2 0 0 0 0 4z',\n bubble: 'M7 14a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm5-5a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z',\n heatmap: 'M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z',\n radar: 'M12 2L4 6v6c0 5.55 3.84 10.74 8 12 4.16-1.26 8-6.45 8-12V6l-8-4zm0 3.18l6 3v5.09c0 4.08-2.76 7.91-6 9.14V5.18z',\n }\n return icons[type] || icons.bar\n }, [])\n\n // Emit initial config on mount\n useEffect(() => {\n onConfigChange?.(chartConfig)\n // Only run on mount - intentionally not including dependencies\n }, [])\n\n return (\n <div className=\"vpg-chart-builder\">\n {/* Chart Type Selector */}\n <div className=\"vpg-chart-type-bar\">\n {CHART_TYPES.map(ct => (\n <button\n key={ct.type}\n className={`vpg-chart-type-btn ${chartConfig.type === ct.type ? 'active' : ''}`}\n title={ct.description}\n onClick={() => selectChartType(ct.type)}\n >\n <svg className=\"vpg-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d={getChartIcon(ct.type)} />\n </svg>\n <span className=\"vpg-chart-type-label\">{ct.label.replace(' Chart', '')}</span>\n </button>\n ))}\n </div>\n\n <div className=\"vpg-chart-builder-content\">\n {/* Field Lists */}\n <div className=\"vpg-chart-fields-panel\">\n <div className=\"vpg-chart-fields-section\">\n <h4 className=\"vpg-chart-fields-title\">\n <svg className=\"vpg-icon-sm\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M4 6h16M4 12h10M4 18h6\" />\n </svg>\n Dimensions\n <span className=\"vpg-chart-fields-hint\">(text/date)</span>\n </h4>\n <div className=\"vpg-chart-fields-list\">\n {dimensions.map(field => (\n <div\n key={field.field}\n className=\"vpg-chart-field-chip vpg-field-dimension\"\n draggable\n onDragStart={e => handleDragStart(field, e)}\n onDragEnd={handleDragEnd}\n >\n <span className=\"vpg-field-name\">{field.label}</span>\n <span className=\"vpg-field-type\">{field.role === 'temporal' ? 'date' : 'text'}</span>\n </div>\n ))}\n {dimensions.length === 0 && (\n <div className=\"vpg-chart-fields-empty\">\n No dimension fields detected\n </div>\n )}\n </div>\n </div>\n\n <div className=\"vpg-chart-fields-section\">\n <h4 className=\"vpg-chart-fields-title\">\n <svg className=\"vpg-icon-sm\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M16 8v8M12 11v5M8 14v2M4 4v16h16\" />\n </svg>\n Measures\n <span className=\"vpg-chart-fields-hint\">(numbers)</span>\n </h4>\n <div className=\"vpg-chart-fields-list\">\n {measures.map(field => (\n <div\n key={field.field}\n className=\"vpg-chart-field-chip vpg-field-measure\"\n draggable\n onDragStart={e => handleDragStart(field, e)}\n onDragEnd={handleDragEnd}\n >\n <span className=\"vpg-field-name\">{field.label}</span>\n <span className=\"vpg-field-type\">#</span>\n </div>\n ))}\n {measures.length === 0 && (\n <div className=\"vpg-chart-fields-empty\">\n No numeric fields detected\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Drop Zones */}\n <div className=\"vpg-chart-config-panel\">\n {/* X-Axis */}\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">{zoneLabels.xAxis}</label>\n <div\n className={`vpg-chart-drop-zone ${dragOverZone === 'xAxis' ? 'drag-over' : ''} ${chartConfig.xAxis ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver('xAxis', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('xAxis', e)}\n >\n {chartConfig.xAxis\n ? (\n <>\n <span className=\"vpg-zone-field-name\">{chartConfig.xAxis.label}</span>\n {isScatterType && chartConfig.xAxis.role === 'measure' && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.xAxis.aggregation || 'sum'}\n onChange={e => updateAggregation('xAxis', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField('xAxis')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">{zoneLabels.xAxisPlaceholder}</span>\n )}\n </div>\n </div>\n\n {/* Y-Axis */}\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">{zoneLabels.yAxis}</label>\n <div\n className={`vpg-chart-drop-zone ${dragOverZone === 'yAxis' ? 'drag-over' : ''} ${chartConfig.yAxis ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver('yAxis', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('yAxis', e)}\n >\n {chartConfig.yAxis\n ? (\n <>\n <span className=\"vpg-zone-field-name\">{chartConfig.yAxis.label}</span>\n {chartConfig.yAxis.role === 'measure' && !isHeatmapType && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.yAxis.aggregation || 'sum'}\n onChange={e => updateAggregation('yAxis', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField('yAxis')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">{zoneLabels.yAxisPlaceholder}</span>\n )}\n </div>\n </div>\n\n {/* Series / Color (conditional) */}\n {zoneLabels.showSeries && (\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">{zoneLabels.series}</label>\n <div\n className={`vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === 'series' ? 'drag-over' : ''} ${(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver(isHeatmapType ? 'color' : 'series', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop(isHeatmapType ? 'color' : 'series', e)}\n >\n {(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField)\n ? (\n <>\n <span className=\"vpg-zone-field-name\">\n {isHeatmapType ? chartConfig.colorField?.label : chartConfig.seriesField?.label}\n </span>\n {isHeatmapType && chartConfig.colorField?.role === 'measure' && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.colorField?.aggregation || 'sum'}\n onChange={e => updateAggregation('color', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField(isHeatmapType ? 'color' : 'series')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">{zoneLabels.seriesPlaceholder}</span>\n )}\n </div>\n </div>\n )}\n\n {/* Size (for bubble charts) */}\n {zoneLabels.showSize && (\n <div className=\"vpg-chart-drop-zone-wrapper\">\n <label className=\"vpg-chart-zone-label\">Size (number)</label>\n <div\n className={`vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === 'size' ? 'drag-over' : ''} ${chartConfig.sizeField ? 'has-field' : ''}`}\n onDragOver={e => handleDragOver('size', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('size', e)}\n >\n {chartConfig.sizeField\n ? (\n <>\n <span className=\"vpg-zone-field-name\">{chartConfig.sizeField.label}</span>\n {chartConfig.sizeField.role === 'measure' && (\n <select\n className=\"vpg-zone-aggregation\"\n value={chartConfig.sizeField.aggregation || 'sum'}\n onChange={e => updateAggregation('size', e.target.value as ChartAggregation)}\n >\n {CHART_AGGREGATIONS.map(agg => (\n <option key={agg.value} value={agg.value}>\n {agg.symbol}\n </option>\n ))}\n </select>\n )}\n <button className=\"vpg-zone-remove-btn\" onClick={() => removeField('size')}>\n <svg className=\"vpg-icon-xs\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n )\n : (\n <span className=\"vpg-zone-placeholder\">Drop a number for bubble size</span>\n )}\n </div>\n </div>\n )}\n\n {/* Guidance */}\n <div className=\"vpg-chart-guidance\">\n <svg className=\"vpg-icon-sm\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4M12 8h.01\" />\n </svg>\n <span>{guidance}</span>\n </div>\n </div>\n\n {/* Chart Preview */}\n <div className=\"vpg-chart-preview-panel\">\n {chartIsValid\n ? (\n <div className=\"vpg-chart-container\">\n <Suspense fallback={(\n <div className=\"vpg-chart-loading\">\n <div className=\"vpg-chart-spinner\" />\n <span>Loading chart...</span>\n </div>\n )}\n >\n <Chart\n key={`${chartConfig.type}-${JSON.stringify(chartConfig.xAxis)}-${JSON.stringify(chartConfig.yAxis)}`}\n type={getApexChartType(chartConfig.type)}\n options={chartOptionsWithCategories}\n series={chartSeries}\n height=\"100%\"\n />\n </Suspense>\n </div>\n )\n : (\n <div className=\"vpg-chart-empty-state\">\n <svg className=\"vpg-icon-lg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d={getChartIcon(chartConfig.type)} />\n </svg>\n <h3>Build your chart</h3>\n <p>Drag fields from the left panel to configure your visualization</p>\n <div className=\"vpg-chart-hint\">\n <strong>{selectedChartType?.label}</strong>\n :\n {' '}\n {selectedChartType?.description}\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import type { ColumnStats, DateFormat, DateRange, NumberFormat, NumericRange } from '@smallwebco/tinypivot-core'\n/**\n * Column Filter Dropdown Component for React\n * Shows unique values with checkboxes, search, and sort controls\n * For numeric and date columns, also provides a range filter option\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { DateRangeFilter } from './DateRangeFilter'\nimport { NumericRangeFilter } from './NumericRangeFilter'\n\ntype FilterMode = 'values' | 'range'\n\ninterface ColumnFilterProps {\n columnId: string\n columnName: string\n stats: ColumnStats\n selectedValues: string[]\n sortDirection: 'asc' | 'desc' | null\n /** Current numeric range filter (if any) */\n numericRange?: NumericRange | null\n /** Current date range filter (if any) */\n dateRange?: DateRange | null\n /** Number display format */\n numberFormat?: NumberFormat\n /** Date display format */\n dateFormat?: DateFormat\n onFilter: (values: string[]) => void\n onSort: (direction: 'asc' | 'desc' | null) => void\n onClose: () => void\n /** Called when a numeric range filter is applied */\n onRangeFilter?: (range: NumericRange | null) => void\n /** Called when a date range filter is applied */\n onDateRangeFilter?: (range: DateRange | null) => void\n}\n\nexport function ColumnFilter({\n columnName,\n stats,\n selectedValues,\n sortDirection,\n numericRange,\n dateRange,\n numberFormat,\n dateFormat,\n onFilter,\n onSort,\n onClose,\n onRangeFilter,\n onDateRangeFilter,\n}: ColumnFilterProps) {\n const [searchQuery, setSearchQuery] = useState('')\n const [localSelected, setLocalSelected] = useState<Set<string>>(new Set(selectedValues))\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Filter mode (values vs range) - available for numeric and date columns\n const isNumericColumn = stats.type === 'number'\n && stats.numericMin !== undefined\n && stats.numericMax !== undefined\n\n const isDateColumn = stats.type === 'date'\n && stats.dateMin !== undefined\n && stats.dateMax !== undefined\n\n // Determine initial mode based on existing filters\n const [filterMode, setFilterMode] = useState<FilterMode>(\n numericRange || dateRange ? 'range' : 'values',\n )\n\n // Local range for the numeric filter\n const [localRange, setLocalRange] = useState<NumericRange | null>(numericRange ?? null)\n\n // Local date range for the date filter\n const [localDateRange, setLocalDateRange] = useState<DateRange | null>(dateRange ?? null)\n\n // Include blank option if there are null values\n const hasBlankValues = stats.nullCount > 0\n\n // Filtered unique values based on search\n const filteredValues = useMemo(() => {\n const values = stats.uniqueValues\n if (!searchQuery)\n return values\n\n const query = searchQuery.toLowerCase()\n return values.filter(v => v.toLowerCase().includes(query))\n }, [stats.uniqueValues, searchQuery])\n\n // All values including blank\n const allValues = useMemo(() => {\n const values = [...filteredValues]\n if (hasBlankValues && (!searchQuery || '(blank)'.includes(searchQuery.toLowerCase()))) {\n values.unshift('(blank)')\n }\n return values\n }, [filteredValues, hasBlankValues, searchQuery])\n\n // Check states (kept for potential future use)\n const _isAllSelected = useMemo(\n () => allValues.every(v => localSelected.has(v)),\n [allValues, localSelected],\n )\n\n // Toggle single value\n const toggleValue = useCallback((value: string) => {\n setLocalSelected((prev) => {\n const next = new Set(prev)\n if (next.has(value)) {\n next.delete(value)\n }\n else {\n next.add(value)\n }\n return next\n })\n }, [])\n\n // Select all visible\n const selectAll = useCallback(() => {\n setLocalSelected((prev) => {\n const next = new Set(prev)\n for (const value of allValues) {\n next.add(value)\n }\n return next\n })\n }, [allValues])\n\n // Clear all\n const clearAll = useCallback(() => {\n setLocalSelected(new Set())\n }, [])\n\n // Apply filter\n const applyFilter = useCallback(() => {\n if (localSelected.size === 0) {\n onFilter([])\n }\n else {\n onFilter(Array.from(localSelected))\n }\n onClose()\n }, [localSelected, onFilter, onClose])\n\n // Sort handlers\n const sortAscending = useCallback(() => {\n onSort(sortDirection === 'asc' ? null : 'asc')\n }, [sortDirection, onSort])\n\n const sortDescending = useCallback(() => {\n onSort(sortDirection === 'desc' ? null : 'desc')\n }, [sortDirection, onSort])\n\n // Clear filter only\n const clearFilter = useCallback(() => {\n setLocalSelected(new Set())\n onFilter([])\n onClose()\n }, [onFilter, onClose])\n\n // Handle range filter change from the NumericRangeFilter component\n const handleRangeChange = useCallback((range: NumericRange | null) => {\n setLocalRange(range)\n }, [])\n\n // Apply the range filter\n const applyRangeFilter = useCallback(() => {\n onRangeFilter?.(localRange)\n onClose()\n }, [localRange, onRangeFilter, onClose])\n\n // Clear range filter\n const clearRangeFilter = useCallback(() => {\n setLocalRange(null)\n onRangeFilter?.(null)\n onClose()\n }, [onRangeFilter, onClose])\n\n // Handle date range filter change from the DateRangeFilter component\n const handleDateRangeChange = useCallback((range: DateRange | null) => {\n setLocalDateRange(range)\n }, [])\n\n // Apply the date range filter\n const applyDateRangeFilter = useCallback(() => {\n onDateRangeFilter?.(localDateRange)\n onClose()\n }, [localDateRange, onDateRangeFilter, onClose])\n\n // Clear date range filter\n const clearDateRangeFilter = useCallback(() => {\n setLocalDateRange(null)\n onDateRangeFilter?.(null)\n onClose()\n }, [onDateRangeFilter, onClose])\n\n // Click outside handler\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n onClose()\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [onClose])\n\n // Keyboard handling\n useEffect(() => {\n const handleKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose()\n }\n else if (event.key === 'Enter' && event.ctrlKey) {\n applyFilter()\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n return () => document.removeEventListener('keydown', handleKeydown)\n }, [onClose, applyFilter])\n\n // Focus search on mount\n useEffect(() => {\n searchInputRef.current?.focus()\n }, [])\n\n // Sync with props\n useEffect(() => {\n setLocalSelected(new Set(selectedValues))\n }, [selectedValues])\n\n // Sync numeric range with props\n useEffect(() => {\n setLocalRange(numericRange ?? null)\n if (numericRange) {\n setFilterMode('range')\n }\n }, [numericRange])\n\n // Sync date range with props\n useEffect(() => {\n setLocalDateRange(dateRange ?? null)\n if (dateRange) {\n setFilterMode('range')\n }\n }, [dateRange])\n\n return (\n <div ref={dropdownRef} className=\"vpg-filter-dropdown\">\n {/* Header */}\n <div className=\"vpg-filter-header\">\n <span className=\"vpg-filter-title\">{columnName}</span>\n <span className=\"vpg-filter-count\">\n {stats.uniqueValues.length.toLocaleString()}\n {' '}\n unique\n </span>\n </div>\n\n {/* Sort Controls */}\n <div className=\"vpg-sort-controls\">\n <button\n className={`vpg-sort-btn ${sortDirection === 'asc' ? 'active' : ''}`}\n title={isDateColumn ? 'Sort Old to New' : isNumericColumn ? 'Sort Low to High' : 'Sort A to Z'}\n onClick={sortAscending}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12\"\n />\n </svg>\n <span>{isDateColumn ? 'Old\\u2192New' : isNumericColumn ? '1\\u21929' : 'A\\u2192Z'}</span>\n </button>\n <button\n className={`vpg-sort-btn ${sortDirection === 'desc' ? 'active' : ''}`}\n title={isDateColumn ? 'Sort New to Old' : isNumericColumn ? 'Sort High to Low' : 'Sort Z to A'}\n onClick={sortDescending}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4\"\n />\n </svg>\n <span>{isDateColumn ? 'New\\u2192Old' : isNumericColumn ? '9\\u21921' : 'Z\\u2192A'}</span>\n </button>\n </div>\n\n <div className=\"vpg-divider\" />\n\n {/* Filter Mode Tabs (for numeric and date columns) */}\n {(isNumericColumn || isDateColumn) && (\n <div className=\"vpg-filter-tabs\">\n <button\n className={`vpg-tab-btn ${filterMode === 'values' ? 'active' : ''}`}\n onClick={() => setFilterMode('values')}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"\n />\n </svg>\n Values\n </button>\n <button\n className={`vpg-tab-btn ${filterMode === 'range' ? 'active' : ''}`}\n onClick={() => setFilterMode('range')}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01\"\n />\n </svg>\n Range\n </button>\n </div>\n )}\n\n {/* Values Filter Mode */}\n {((!isNumericColumn && !isDateColumn) || filterMode === 'values') && (\n <>\n {/* Search */}\n <div className=\"vpg-search-container\">\n <svg className=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n placeholder=\"Search values...\"\n className=\"vpg-search-input\"\n />\n {searchQuery && (\n <button className=\"vpg-clear-search\" onClick={() => setSearchQuery('')}>\n &times;\n </button>\n )}\n </div>\n\n {/* Select All / Clear All */}\n <div className=\"vpg-bulk-actions\">\n <button className=\"vpg-bulk-btn\" onClick={selectAll}>\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Select All\n </button>\n <button className=\"vpg-bulk-btn\" onClick={clearAll}>\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Clear All\n </button>\n </div>\n\n {/* Values List */}\n <div className=\"vpg-values-list\">\n {allValues.map(value => (\n <label\n key={value}\n className={`vpg-value-item ${localSelected.has(value) ? 'selected' : ''}`}\n >\n <input\n type=\"checkbox\"\n checked={localSelected.has(value)}\n onChange={() => toggleValue(value)}\n className=\"vpg-value-checkbox\"\n />\n <span className={`vpg-value-text ${value === '(blank)' ? 'vpg-blank' : ''}`}>\n {value}\n </span>\n </label>\n ))}\n\n {allValues.length === 0 && <div className=\"vpg-no-results\">No matching values</div>}\n </div>\n\n {/* Footer for Values Mode */}\n <div className=\"vpg-filter-footer\">\n <button className=\"vpg-btn-clear\" onClick={clearFilter}>\n Clear Filter\n </button>\n <button className=\"vpg-btn-apply\" onClick={applyFilter}>\n Apply\n </button>\n </div>\n </>\n )}\n\n {/* Numeric Range Filter Mode */}\n {isNumericColumn && filterMode === 'range' && (\n <>\n <NumericRangeFilter\n dataMin={stats.numericMin!}\n dataMax={stats.numericMax!}\n currentRange={localRange}\n onChange={handleRangeChange}\n numberFormat={numberFormat}\n />\n\n {/* Footer for Range Mode */}\n <div className=\"vpg-filter-footer\">\n <button className=\"vpg-btn-clear\" onClick={clearRangeFilter}>\n Clear Filter\n </button>\n <button className=\"vpg-btn-apply\" onClick={applyRangeFilter}>\n Apply\n </button>\n </div>\n </>\n )}\n\n {/* Date Range Filter Mode */}\n {isDateColumn && filterMode === 'range' && (\n <>\n <DateRangeFilter\n dataMin={stats.dateMin!}\n dataMax={stats.dateMax!}\n currentRange={localDateRange}\n onChange={handleDateRangeChange}\n dateFormat={dateFormat}\n />\n\n {/* Footer for Date Range Mode */}\n <div className=\"vpg-filter-footer\">\n <button className=\"vpg-btn-clear\" onClick={clearDateRangeFilter}>\n Clear Filter\n </button>\n <button className=\"vpg-btn-apply\" onClick={applyDateRangeFilter}>\n Apply\n </button>\n </div>\n </>\n )}\n </div>\n )\n}\n","import type { DateFormat, DateRange } from '@smallwebco/tinypivot-core'\nimport { formatDate, getDatePlaceholder, parseDateInput } from '@smallwebco/tinypivot-core'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\n\ninterface DateRangeFilterProps {\n dataMin: string // ISO date string\n dataMax: string // ISO date string\n currentRange: DateRange | null\n onChange: (range: DateRange | null) => void\n dateFormat?: DateFormat\n}\n\nexport function DateRangeFilter({\n dataMin,\n dataMax,\n currentRange,\n onChange,\n dateFormat = 'iso',\n}: DateRangeFilterProps) {\n const [localMinText, setLocalMinText] = useState('')\n const [localMaxText, setLocalMaxText] = useState('')\n const [minError, setMinError] = useState(false)\n const [maxError, setMaxError] = useState(false)\n\n const formattedMin = useMemo(() => formatDate(dataMin, dateFormat), [dataMin, dateFormat])\n const formattedMax = useMemo(() => formatDate(dataMax, dateFormat), [dataMax, dateFormat])\n\n const isFilterActive = localMinText !== '' || localMaxText !== ''\n\n const emitChange = useCallback(() => {\n const min = localMinText ? parseDateInput(localMinText, dateFormat) : null\n const max = localMaxText ? parseDateInput(localMaxText, dateFormat) : null\n if (min === null && max === null) {\n onChange(null)\n }\n else {\n onChange({ min, max })\n }\n }, [localMinText, localMaxText, dateFormat, onChange])\n\n const handleMinBlur = useCallback(() => {\n if (localMinText === '') {\n setMinError(false)\n emitChange()\n return\n }\n const parsed = parseDateInput(localMinText, dateFormat)\n setMinError(parsed === null)\n if (parsed !== null)\n emitChange()\n }, [localMinText, dateFormat, emitChange])\n\n const handleMaxBlur = useCallback(() => {\n if (localMaxText === '') {\n setMaxError(false)\n emitChange()\n return\n }\n const parsed = parseDateInput(localMaxText, dateFormat)\n setMaxError(parsed === null)\n if (parsed !== null)\n emitChange()\n }, [localMaxText, dateFormat, emitChange])\n\n const clearFilter = useCallback(() => {\n setLocalMinText('')\n setLocalMaxText('')\n setMinError(false)\n setMaxError(false)\n onChange(null)\n }, [onChange])\n\n const setFullRange = useCallback(() => {\n setLocalMinText(formatDate(dataMin, dateFormat))\n setLocalMaxText(formatDate(dataMax, dateFormat))\n setMinError(false)\n setMaxError(false)\n onChange({ min: dataMin, max: dataMax })\n }, [dataMin, dataMax, dateFormat, onChange])\n\n // Sync with props\n useEffect(() => {\n if (currentRange?.min) {\n setLocalMinText(formatDate(currentRange.min, dateFormat))\n }\n else {\n setLocalMinText('')\n }\n if (currentRange?.max) {\n setLocalMaxText(formatDate(currentRange.max, dateFormat))\n }\n else {\n setLocalMaxText('')\n }\n setMinError(false)\n setMaxError(false)\n }, [currentRange, dateFormat])\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent, handler: () => void) => {\n if (e.key === 'Enter')\n handler()\n }, [])\n\n return (\n <div className=\"vpg-range-filter\">\n <div className=\"vpg-range-info\">\n <span className=\"vpg-range-label\">Data range:</span>\n <span className=\"vpg-range-bounds\">\n {formattedMin}\n {' '}\n &ndash;\n {' '}\n {formattedMax}\n </span>\n </div>\n\n <div className=\"vpg-range-inputs\">\n <div className=\"vpg-input-group\">\n <label className=\"vpg-input-label\">From</label>\n <input\n type=\"text\"\n className={`vpg-range-input ${minError ? 'vpg-input-error' : ''}`}\n placeholder={getDatePlaceholder(dateFormat)}\n value={localMinText}\n onChange={e => setLocalMinText(e.target.value)}\n onBlur={handleMinBlur}\n onKeyDown={e => handleKeyDown(e, handleMinBlur)}\n />\n </div>\n <span className=\"vpg-input-separator\">to</span>\n <div className=\"vpg-input-group\">\n <label className=\"vpg-input-label\">To</label>\n <input\n type=\"text\"\n className={`vpg-range-input ${maxError ? 'vpg-input-error' : ''}`}\n placeholder={getDatePlaceholder(dateFormat)}\n value={localMaxText}\n onChange={e => setLocalMaxText(e.target.value)}\n onBlur={handleMaxBlur}\n onKeyDown={e => handleKeyDown(e, handleMaxBlur)}\n />\n </div>\n </div>\n\n <div className=\"vpg-range-actions\">\n <button className=\"vpg-range-btn\" disabled={!isFilterActive} onClick={clearFilter}>\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n Clear\n </button>\n <button className=\"vpg-range-btn\" onClick={setFullRange}>\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4\" />\n </svg>\n Full Range\n </button>\n </div>\n\n {isFilterActive && !minError && !maxError && (\n <div className=\"vpg-filter-summary\">\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\" />\n </svg>\n <span>\n Showing dates\n {localMinText && (\n <strong>\n {' '}\n from\n {' '}\n {localMinText}\n </strong>\n )}\n {localMinText && localMaxText && ' '}\n {localMaxText && (\n <strong>\n to\n {' '}\n {localMaxText}\n </strong>\n )}\n </span>\n </div>\n )}\n </div>\n )\n}\n","import type { NumberFormat, NumericRange } from '@smallwebco/tinypivot-core'\nimport { formatNumber } from '@smallwebco/tinypivot-core'\n/**\n * Numeric Range Filter Component for React\n * Provides an intuitive dual-handle slider and input fields for filtering numeric data\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\n\ninterface NumericRangeFilterProps {\n dataMin: number\n dataMax: number\n currentRange: NumericRange | null\n onChange: (range: NumericRange | null) => void\n numberFormat?: NumberFormat\n}\n\nexport function NumericRangeFilter({\n dataMin,\n dataMax,\n currentRange,\n onChange,\n numberFormat = 'us',\n}: NumericRangeFilterProps) {\n // Local state for the range values\n const [localMin, setLocalMin] = useState<number | null>(currentRange?.min ?? null)\n const [localMax, setLocalMax] = useState<number | null>(currentRange?.max ?? null)\n\n // Calculate step based on data range\n const step = useMemo(() => {\n const range = dataMax - dataMin\n if (range === 0)\n return 1\n if (range <= 1)\n return 0.01\n if (range <= 10)\n return 0.1\n if (range <= 100)\n return 1\n if (range <= 1000)\n return 10\n return 10 ** (Math.floor(Math.log10(range)) - 2)\n }, [dataMin, dataMax])\n\n // Format numbers for display\n const formatValue = useCallback((val: number | null): string => {\n if (val === null)\n return ''\n return formatNumber(val, numberFormat)\n }, [numberFormat])\n\n // Check if filter is active\n const isFilterActive = localMin !== null || localMax !== null\n\n // Calculate slider percentages for visual representation\n const minPercent = useMemo(() => {\n if (localMin === null || dataMax === dataMin)\n return 0\n return ((localMin - dataMin) / (dataMax - dataMin)) * 100\n }, [localMin, dataMin, dataMax])\n\n const maxPercent = useMemo(() => {\n if (localMax === null || dataMax === dataMin)\n return 100\n return ((localMax - dataMin) / (dataMax - dataMin)) * 100\n }, [localMax, dataMin, dataMax])\n\n // Handle min slider change\n const handleMinSlider = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = Number.parseFloat(event.target.value)\n setLocalMin(() => {\n // Ensure min doesn't exceed max\n if (localMax !== null && value > localMax) {\n return localMax\n }\n return value\n })\n }, [localMax])\n\n // Handle max slider change\n const handleMaxSlider = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = Number.parseFloat(event.target.value)\n setLocalMax(() => {\n // Ensure max doesn't go below min\n if (localMin !== null && value < localMin) {\n return localMin\n }\n return value\n })\n }, [localMin])\n\n // Handle slider change complete (emit change)\n const handleSliderChange = useCallback(() => {\n if (localMin === null && localMax === null) {\n onChange(null)\n }\n else {\n onChange({ min: localMin, max: localMax })\n }\n }, [localMin, localMax, onChange])\n\n // Handle min input change\n const handleMinInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value === '' ? null : Number.parseFloat(event.target.value)\n if (value !== null && !Number.isNaN(value)) {\n // Clamp to data bounds\n setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)))\n }\n else if (value === null) {\n setLocalMin(null)\n }\n }, [dataMin, dataMax, localMax])\n\n // Handle max input change\n const handleMaxInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value === '' ? null : Number.parseFloat(event.target.value)\n if (value !== null && !Number.isNaN(value)) {\n // Clamp to data bounds\n setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)))\n }\n else if (value === null) {\n setLocalMax(null)\n }\n }, [dataMin, dataMax, localMin])\n\n // Handle input blur (emit change)\n const handleInputBlur = useCallback(() => {\n if (localMin === null && localMax === null) {\n onChange(null)\n }\n else {\n onChange({ min: localMin, max: localMax })\n }\n }, [localMin, localMax, onChange])\n\n // Clear the filter\n const clearFilter = useCallback(() => {\n setLocalMin(null)\n setLocalMax(null)\n onChange(null)\n }, [onChange])\n\n // Set to full range\n const setFullRange = useCallback(() => {\n setLocalMin(dataMin)\n setLocalMax(dataMax)\n onChange({ min: dataMin, max: dataMax })\n }, [dataMin, dataMax, onChange])\n\n // Sync with props\n useEffect(() => {\n setLocalMin(currentRange?.min ?? null)\n setLocalMax(currentRange?.max ?? null)\n }, [currentRange])\n\n return (\n <div className=\"vpg-range-filter\">\n {/* Data range info */}\n <div className=\"vpg-range-info\">\n <span className=\"vpg-range-label\">Data range:</span>\n <span className=\"vpg-range-bounds\">\n {formatValue(dataMin)}\n {' '}\n –\n {formatValue(dataMax)}\n </span>\n </div>\n\n {/* Dual slider track */}\n <div className=\"vpg-slider-container\">\n <div className=\"vpg-slider-track\">\n <div\n className=\"vpg-slider-fill\"\n style={{\n left: `${minPercent}%`,\n right: `${100 - maxPercent}%`,\n }}\n />\n </div>\n\n {/* Min slider (lower handle) */}\n <input\n type=\"range\"\n className=\"vpg-slider vpg-slider-min\"\n min={dataMin}\n max={dataMax}\n step={step}\n value={localMin ?? dataMin}\n onChange={handleMinSlider}\n onMouseUp={handleSliderChange}\n onTouchEnd={handleSliderChange}\n />\n\n {/* Max slider (upper handle) */}\n <input\n type=\"range\"\n className=\"vpg-slider vpg-slider-max\"\n min={dataMin}\n max={dataMax}\n step={step}\n value={localMax ?? dataMax}\n onChange={handleMaxSlider}\n onMouseUp={handleSliderChange}\n onTouchEnd={handleSliderChange}\n />\n </div>\n\n {/* Input fields for precise entry */}\n <div className=\"vpg-range-inputs\">\n <div className=\"vpg-input-group\">\n <label className=\"vpg-input-label\">Min</label>\n <input\n type=\"number\"\n className=\"vpg-range-input\"\n placeholder={formatValue(dataMin)}\n value={localMin ?? ''}\n step={step}\n onChange={handleMinInput}\n onBlur={handleInputBlur}\n />\n </div>\n <span className=\"vpg-input-separator\">to</span>\n <div className=\"vpg-input-group\">\n <label className=\"vpg-input-label\">Max</label>\n <input\n type=\"number\"\n className=\"vpg-range-input\"\n placeholder={formatValue(dataMax)}\n value={localMax ?? ''}\n step={step}\n onChange={handleMaxInput}\n onBlur={handleInputBlur}\n />\n </div>\n </div>\n\n {/* Quick actions */}\n <div className=\"vpg-range-actions\">\n <button\n className=\"vpg-range-btn\"\n disabled={!isFilterActive}\n onClick={clearFilter}\n >\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Clear\n </button>\n <button className=\"vpg-range-btn\" onClick={setFullRange}>\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4\"\n />\n </svg>\n Full Range\n </button>\n </div>\n\n {/* Current filter display */}\n {isFilterActive && (\n <div className=\"vpg-filter-summary\">\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n <span>\n Showing values\n {' '}\n {localMin !== null && (\n <strong>\n ≥\n {formatValue(localMin)}\n </strong>\n )}\n {localMin !== null && localMax !== null && ' and '}\n {localMax !== null && (\n <strong>\n ≤\n {formatValue(localMax)}\n </strong>\n )}\n </span>\n </div>\n )}\n </div>\n )\n}\n","/**\n * TinyPivot React - Main DataGrid Component\n * Excel-like data grid with optional pivot table functionality\n */\nimport type {\n AIAnalystConfig,\n AIConversationUpdateEvent,\n AIDataLoadedEvent,\n AIErrorEvent,\n AIQueryExecutedEvent,\n ChartConfig,\n DateFormat,\n DateRange,\n NumberFormat,\n} from '@smallwebco/tinypivot-core'\nimport { formatDate as coreFormatDate, formatNumber as coreFormatNumber } from '@smallwebco/tinypivot-core'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useExcelGrid } from '../hooks/useExcelGrid'\nimport {\n copyToClipboard,\n exportPivotToCSV,\n exportToCSV,\n formatSelectionForClipboard,\n} from '../hooks/useGridFeatures'\nimport { useLicense } from '../hooks/useLicense'\nimport { usePivotTable } from '../hooks/usePivotTable'\nimport { AIAnalyst, type AIAnalystHandle } from './AIAnalyst'\nimport { ChartBuilder } from './ChartBuilder'\nimport { ColumnFilter } from './ColumnFilter'\nimport { PivotConfig } from './PivotConfig'\nimport { PivotSkeleton } from './PivotSkeleton'\n\n// Re-export AI types for public API\nexport type { AIAnalystConfig, AIConversationUpdateEvent, AIDataLoadedEvent, AIErrorEvent, AIQueryExecutedEvent }\n\ninterface DataGridProps {\n data: Record<string, unknown>[]\n loading?: boolean\n rowHeight?: number\n headerHeight?: number\n fontSize?: 'xs' | 'sm' | 'base'\n showPivot?: boolean\n enableExport?: boolean\n enableSearch?: boolean\n enablePagination?: boolean\n pageSize?: number\n enableColumnResize?: boolean\n enableClipboard?: boolean\n theme?: 'light' | 'dark' | 'auto'\n stripedRows?: boolean\n exportFilename?: string\n enableVerticalResize?: boolean\n initialHeight?: number\n minHeight?: number\n maxHeight?: number\n /** Number display format */\n numberFormat?: NumberFormat\n /** Date display format */\n dateFormat?: DateFormat\n /** AI Data Analyst configuration (Pro feature, disabled by default) */\n aiAnalyst?: AIAnalystConfig\n onCellClick?: (payload: {\n row: number\n col: number\n value: unknown\n rowData: Record<string, unknown>\n }) => void\n onSelectionChange?: (payload: { cells: Array<{ row: number, col: number }>, values: unknown[] }) => void\n onExport?: (payload: { rowCount: number, filename: string }) => void\n onCopy?: (payload: { text: string, cellCount: number }) => void\n // AI Analyst events\n onAIDataLoaded?: (payload: AIDataLoadedEvent) => void\n onAIConversationUpdate?: (payload: AIConversationUpdateEvent) => void\n onAIQueryExecuted?: (payload: AIQueryExecutedEvent) => void\n onAIError?: (payload: AIErrorEvent) => void\n}\n\nconst MIN_COL_WIDTH = 120\nconst MAX_COL_WIDTH = 350\n\nexport function DataGrid({\n data,\n loading = false,\n fontSize: initialFontSize = 'xs',\n showPivot = true,\n enableExport = true,\n enableSearch = true,\n enablePagination = false,\n pageSize = 50,\n enableColumnResize = true,\n enableClipboard = true,\n theme = 'light',\n stripedRows = true,\n exportFilename = 'data-export.csv',\n enableVerticalResize = true,\n initialHeight = 600,\n minHeight = 300,\n maxHeight = 1200,\n numberFormat = 'us',\n dateFormat = 'iso',\n aiAnalyst,\n onCellClick,\n onExport,\n onCopy,\n onAIDataLoaded,\n onAIConversationUpdate,\n onAIQueryExecuted,\n onAIError,\n}: DataGridProps) {\n const { showWatermark, canUsePivot, canUseCharts, canUseAIAnalyst, isDemo, isPro } = useLicense()\n\n // Check if AI Analyst should be shown (enabled in config + licensed)\n const showAIAnalyst = aiAnalyst?.enabled && canUseAIAnalyst\n\n // Theme handling\n const currentTheme = useMemo(() => {\n if (theme === 'auto') {\n return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n return theme\n }, [theme])\n\n // State\n const [currentFontSize, setCurrentFontSize] = useState(initialFontSize)\n const [globalSearchTerm, setGlobalSearchTerm] = useState('')\n const [showSearchInput, setShowSearchInput] = useState(false)\n const [currentPage, setCurrentPage] = useState(1)\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>({})\n const [resizingColumnId, setResizingColumnId] = useState<string | null>(null)\n const [resizeStartX, setResizeStartX] = useState(0)\n const [resizeStartWidth, setResizeStartWidth] = useState(0)\n const [gridHeight, setGridHeight] = useState(initialHeight)\n const [isResizingVertically, setIsResizingVertically] = useState(false)\n const [verticalResizeStartY, setVerticalResizeStartY] = useState(0)\n const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState(0)\n const [showCopyToast, setShowCopyToast] = useState(false)\n const [copyToastMessage, setCopyToastMessage] = useState('')\n const [viewMode, setViewMode] = useState<'ai' | 'grid' | 'pivot' | 'chart'>('grid')\n\n // AI Analyst ref (for accessing loadFullData)\n const aiAnalystRef = useRef<AIAnalystHandle>(null)\n\n // AI-loaded data (replaces current data when AI loads results)\n const [aiLoadedData, setAiLoadedData] = useState<Record<string, unknown>[] | null>(null)\n\n // Loading state for full data reset\n const [isLoadingFullData, setIsLoadingFullData] = useState(false)\n\n // Data to display - AI loaded data takes precedence\n const displayData = useMemo(() => aiLoadedData || data, [aiLoadedData, data])\n const [_chartConfig, setChartConfig] = useState<ChartConfig | null>(null)\n\n const handleChartConfigChange = useCallback((config: ChartConfig) => {\n setChartConfig(config)\n }, [])\n const [showPivotConfig, setShowPivotConfig] = useState(true)\n const [draggingField, setDraggingField] = useState<string | null>(null)\n const [activeFilterColumn, setActiveFilterColumn] = useState<string | null>(null)\n const [filterDropdownPosition, setFilterDropdownPosition] = useState({ top: 0, left: 0, maxHeight: 400 })\n const [selectedCell, setSelectedCell] = useState<{ row: number, col: number } | null>(null)\n const [selectionStart, setSelectionStart] = useState<{ row: number, col: number } | null>(null)\n const [selectionEnd, setSelectionEnd] = useState<{ row: number, col: number } | null>(null)\n const [isSelecting, setIsSelecting] = useState(false)\n\n const tableContainerRef = useRef<HTMLDivElement>(null)\n const tableBodyRef = useRef<HTMLTableSectionElement>(null)\n\n const fontSizeOptions = [\n { value: 'xs' as const, label: 'S' },\n { value: 'sm' as const, label: 'M' },\n { value: 'base' as const, label: 'L' },\n ]\n\n // Grid composable\n const {\n table,\n columnKeys,\n filteredRowCount,\n totalRowCount,\n getColumnStats,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n columnFilters,\n activeFilters,\n // Numeric range filters\n setNumericRangeFilter,\n getNumericRangeFilter,\n // Date range filters\n setDateRangeFilter,\n getDateRangeFilter,\n } = useExcelGrid({ data: displayData, enableSorting: true, enableFiltering: true })\n\n // Filtered data for pivot table\n const filteredDataForPivot = useMemo(() => {\n const filteredRows = table.getFilteredRowModel().rows\n return filteredRows.map(row => row.original)\n }, [table, columnFilters])\n\n // Pivot table composable\n const {\n rowFields: pivotRowFields,\n columnFields: pivotColumnFields,\n valueFields: pivotValueFields,\n showRowTotals: pivotShowRowTotals,\n showColumnTotals: pivotShowColumnTotals,\n calculatedFields: pivotCalculatedFields,\n availableFields: pivotAvailableFields,\n isConfigured: pivotIsConfigured,\n pivotResult,\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig: clearPivotConfig,\n autoSuggestConfig,\n setShowRowTotals: setPivotShowRowTotals,\n setShowColumnTotals: setPivotShowColumnTotals,\n setRowFields,\n setColumnFields,\n addCalculatedField,\n removeCalculatedField,\n } = usePivotTable(filteredDataForPivot)\n\n // Active filters info for display\n const activeFilterInfo = useMemo(() => {\n if (activeFilters.length === 0)\n return null\n return activeFilters.map((f) => {\n if (f.type === 'range' && f.range) {\n // Format numeric range filter display\n const parts = []\n if (f.range.min !== null)\n parts.push(`\\u2265 ${f.range.min}`)\n if (f.range.max !== null)\n parts.push(`\\u2264 ${f.range.max}`)\n return {\n column: f.column,\n valueCount: 1,\n displayText: parts.join(' and '),\n isRange: true,\n }\n }\n if (f.type === 'dateRange' && f.dateRange) {\n // Format date range filter display\n const parts = []\n if (f.dateRange.min !== null)\n parts.push(`from ${coreFormatDate(f.dateRange.min, dateFormat)}`)\n if (f.dateRange.max !== null)\n parts.push(`to ${coreFormatDate(f.dateRange.max, dateFormat)}`)\n return {\n column: f.column,\n valueCount: 1,\n displayText: parts.join(' '),\n isRange: true,\n }\n }\n return {\n column: f.column,\n valueCount: f.values?.length || 0,\n values: f.values || [],\n isRange: false,\n }\n })\n }, [activeFilters, dateFormat])\n\n // Rows - depends on columnFilters to recompute when filters change\n const rows = useMemo(() => table.getFilteredRowModel().rows, [table, columnFilters])\n\n // Filtered data based on global search\n const searchFilteredData = useMemo(() => {\n if (!globalSearchTerm.trim() || !enableSearch) {\n return rows\n }\n const term = globalSearchTerm.toLowerCase().trim()\n return rows.filter((row) => {\n for (const col of columnKeys) {\n const value = row.original[col]\n if (value === null || value === undefined)\n continue\n if (String(value).toLowerCase().includes(term)) {\n return true\n }\n }\n return false\n })\n }, [rows, globalSearchTerm, enableSearch, columnKeys])\n\n // Paginated rows\n const totalSearchedRows = searchFilteredData.length\n const totalPages = useMemo(() => {\n if (!enablePagination)\n return 1\n return Math.max(1, Math.ceil(totalSearchedRows / pageSize))\n }, [enablePagination, totalSearchedRows, pageSize])\n\n const paginatedRows = useMemo(() => {\n if (!enablePagination)\n return searchFilteredData\n const start = (currentPage - 1) * pageSize\n const end = start + pageSize\n return searchFilteredData.slice(start, end)\n }, [enablePagination, searchFilteredData, currentPage, pageSize])\n\n // Reset to page 1 when filters or search changes\n useEffect(() => {\n setCurrentPage(1)\n }, [columnFilters, globalSearchTerm])\n\n // Selection bounds\n const selectionBounds = useMemo(() => {\n if (!selectionStart || !selectionEnd)\n return null\n return {\n minRow: Math.min(selectionStart.row, selectionEnd.row),\n maxRow: Math.max(selectionStart.row, selectionEnd.row),\n minCol: Math.min(selectionStart.col, selectionEnd.col),\n maxCol: Math.max(selectionStart.col, selectionEnd.col),\n }\n }, [selectionStart, selectionEnd])\n\n // Selection stats\n const selectionStats = useMemo(() => {\n if (!selectionBounds)\n return null\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n\n const values: number[] = []\n let count = 0\n\n for (let r = minRow; r <= maxRow; r++) {\n const row = rows[r]\n if (!row)\n continue\n\n for (let c = minCol; c <= maxCol; c++) {\n const colId = columnKeys[c]\n if (!colId)\n continue\n\n const value = row.original[colId]\n count++\n\n if (value !== null && value !== undefined && value !== '') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (!Number.isNaN(num)) {\n values.push(num)\n }\n }\n }\n }\n\n if (values.length === 0)\n return { count, sum: null, avg: null, numericCount: 0 }\n\n const sum = values.reduce((a, b) => a + b, 0)\n const avg = sum / values.length\n\n return { count, sum, avg, numericCount: values.length }\n }, [selectionBounds, rows, columnKeys])\n\n // Calculate column widths\n useEffect(() => {\n // Skip during SSR (no document available)\n if (typeof document === 'undefined')\n return\n if (displayData.length === 0)\n return\n\n const widths: Record<string, number> = {}\n const sampleSize = Math.min(100, displayData.length)\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n\n ctx.font = '13px system-ui, -apple-system, sans-serif'\n\n for (const key of columnKeys) {\n let maxWidth = ctx.measureText(key).width + 56\n\n for (let i = 0; i < sampleSize; i++) {\n const value = displayData[i][key]\n const text = value === null || value === undefined ? '' : String(value)\n const width = ctx.measureText(text).width + 28\n maxWidth = Math.max(maxWidth, width)\n }\n\n widths[key] = Math.min(Math.max(maxWidth, MIN_COL_WIDTH), MAX_COL_WIDTH)\n }\n\n setColumnWidths(widths)\n }, [displayData, columnKeys])\n\n // Column resize handlers\n const startColumnResize = useCallback(\n (columnId: string, event: React.MouseEvent) => {\n if (!enableColumnResize)\n return\n event.preventDefault()\n event.stopPropagation()\n\n setResizingColumnId(columnId)\n setResizeStartX(event.clientX)\n setResizeStartWidth(columnWidths[columnId] || MIN_COL_WIDTH)\n },\n [enableColumnResize, columnWidths],\n )\n\n useEffect(() => {\n if (!resizingColumnId)\n return\n\n const handleResizeMove = (event: MouseEvent) => {\n const diff = event.clientX - resizeStartX\n const newWidth = Math.max(MIN_COL_WIDTH, Math.min(MAX_COL_WIDTH, resizeStartWidth + diff))\n setColumnWidths(prev => ({\n ...prev,\n [resizingColumnId]: newWidth,\n }))\n }\n\n const handleResizeEnd = () => {\n setResizingColumnId(null)\n }\n\n document.addEventListener('mousemove', handleResizeMove)\n document.addEventListener('mouseup', handleResizeEnd)\n return () => {\n document.removeEventListener('mousemove', handleResizeMove)\n document.removeEventListener('mouseup', handleResizeEnd)\n }\n }, [resizingColumnId, resizeStartX, resizeStartWidth])\n\n // Vertical resize handlers\n const startVerticalResize = useCallback(\n (event: React.MouseEvent) => {\n if (!enableVerticalResize)\n return\n event.preventDefault()\n\n setIsResizingVertically(true)\n setVerticalResizeStartY(event.clientY)\n setVerticalResizeStartHeight(gridHeight)\n },\n [enableVerticalResize, gridHeight],\n )\n\n useEffect(() => {\n if (!isResizingVertically)\n return\n\n const handleVerticalResizeMove = (event: MouseEvent) => {\n const diff = event.clientY - verticalResizeStartY\n const newHeight = Math.max(minHeight, Math.min(maxHeight, verticalResizeStartHeight + diff))\n setGridHeight(newHeight)\n }\n\n const handleVerticalResizeEnd = () => {\n setIsResizingVertically(false)\n }\n\n document.addEventListener('mousemove', handleVerticalResizeMove)\n document.addEventListener('mouseup', handleVerticalResizeEnd)\n return () => {\n document.removeEventListener('mousemove', handleVerticalResizeMove)\n document.removeEventListener('mouseup', handleVerticalResizeEnd)\n }\n }, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight])\n\n // Export handlers\n const handleExport = useCallback(() => {\n if (viewMode === 'pivot') {\n if (!pivotResult)\n return\n\n const pivotFilename = exportFilename.replace('.csv', '-pivot.csv')\n exportPivotToCSV(\n {\n headers: pivotResult.headers,\n rowHeaders: pivotResult.rowHeaders,\n data: pivotResult.data,\n rowTotals: pivotResult.rowTotals,\n columnTotals: pivotResult.columnTotals,\n grandTotal: pivotResult.grandTotal,\n showRowTotals: pivotShowRowTotals,\n showColumnTotals: pivotShowColumnTotals,\n },\n pivotRowFields,\n pivotColumnFields,\n pivotValueFields,\n { filename: pivotFilename },\n )\n\n onExport?.({ rowCount: pivotResult.rowHeaders.length, filename: pivotFilename })\n return\n }\n\n const dataToExport\n = enableSearch && globalSearchTerm.trim()\n ? searchFilteredData.map(row => row.original)\n : rows.map(row => row.original)\n\n exportToCSV(dataToExport, columnKeys, {\n filename: exportFilename,\n includeHeaders: true,\n })\n\n onExport?.({ rowCount: dataToExport.length, filename: exportFilename })\n }, [\n viewMode,\n pivotResult,\n exportFilename,\n pivotShowRowTotals,\n pivotShowColumnTotals,\n pivotRowFields,\n pivotColumnFields,\n pivotValueFields,\n enableSearch,\n globalSearchTerm,\n searchFilteredData,\n rows,\n columnKeys,\n onExport,\n ])\n\n // Copy to clipboard\n const copySelectionToClipboard = useCallback(() => {\n if (!selectionBounds || !enableClipboard)\n return\n\n const text = formatSelectionForClipboard(\n rows.map(r => r.original),\n columnKeys,\n selectionBounds,\n )\n\n copyToClipboard(\n text,\n () => {\n const cellCount\n = (selectionBounds.maxRow - selectionBounds.minRow + 1)\n * (selectionBounds.maxCol - selectionBounds.minCol + 1)\n setCopyToastMessage(`Copied ${cellCount} cell${cellCount > 1 ? 's' : ''}`)\n setShowCopyToast(true)\n setTimeout(() => setShowCopyToast(false), 2000)\n onCopy?.({ text, cellCount })\n },\n (err) => {\n setCopyToastMessage('Copy failed')\n setShowCopyToast(true)\n setTimeout(() => setShowCopyToast(false), 2000)\n console.error('Copy failed:', err)\n },\n )\n }, [selectionBounds, enableClipboard, rows, columnKeys, onCopy])\n\n // Cell selection handlers\n const handleMouseDown = useCallback(\n (rowIndex: number, colIndex: number, event: React.MouseEvent) => {\n event.preventDefault()\n\n if (event.shiftKey && selectedCell) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n else {\n setSelectedCell({ row: rowIndex, col: colIndex })\n setSelectionStart({ row: rowIndex, col: colIndex })\n setSelectionEnd({ row: rowIndex, col: colIndex })\n setIsSelecting(true)\n }\n\n const row = rows[rowIndex]\n if (row) {\n const colId = columnKeys[colIndex]\n onCellClick?.({\n row: rowIndex,\n col: colIndex,\n value: row.original[colId],\n rowData: row.original,\n })\n }\n },\n [selectedCell, rows, columnKeys, onCellClick],\n )\n\n const handleMouseEnter = useCallback(\n (rowIndex: number, colIndex: number) => {\n if (isSelecting) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n },\n [isSelecting],\n )\n\n // Track if we're showing AI-shaped data (filtered/aggregated by AI queries)\n const isShowingAIData = aiLoadedData !== null\n\n // Reset to full original dataset\n // If AI Analyst is enabled and has a selected data source, load full data from that source\n // Otherwise, just clear the AI loaded data to show original props.data\n const resetToFullData = useCallback(async () => {\n // If we have AI Analyst with a selected data source, load full data from it\n if (aiAnalystRef.current?.selectedDataSource) {\n setIsLoadingFullData(true)\n try {\n const fullData = await aiAnalystRef.current.loadFullData()\n if (fullData && fullData.length > 0) {\n setAiLoadedData(fullData)\n }\n else {\n // Fall back to props.data if loading fails\n setAiLoadedData(null)\n }\n }\n catch (err) {\n console.warn('Failed to load full data:', err)\n setAiLoadedData(null)\n }\n finally {\n setIsLoadingFullData(false)\n }\n }\n else {\n // No AI Analyst or no selected data source - just clear filters by resetting to props.data\n setAiLoadedData(null)\n }\n // Also clear any grid filters\n clearAllFilters()\n }, [clearAllFilters])\n\n // AI Analyst event handlers\n const handleAIDataLoaded = useCallback(\n (payload: AIDataLoadedEvent) => {\n setAiLoadedData(payload.data)\n // Don't auto-switch to grid - let user decide when to view results\n onAIDataLoaded?.(payload)\n },\n [onAIDataLoaded],\n )\n\n const handleAIConversationUpdate = useCallback(\n (payload: AIConversationUpdateEvent) => {\n onAIConversationUpdate?.(payload)\n },\n [onAIConversationUpdate],\n )\n\n const handleAIQueryExecuted = useCallback(\n (payload: AIQueryExecutedEvent) => {\n onAIQueryExecuted?.(payload)\n },\n [onAIQueryExecuted],\n )\n\n const handleAIError = useCallback(\n (payload: AIErrorEvent) => {\n onAIError?.(payload)\n },\n [onAIError],\n )\n\n useEffect(() => {\n const handleMouseUp = () => setIsSelecting(false)\n document.addEventListener('mouseup', handleMouseUp)\n return () => document.removeEventListener('mouseup', handleMouseUp)\n }, [])\n\n // Keyboard handling\n useEffect(() => {\n const handleKeydown = (event: KeyboardEvent) => {\n // Handle Ctrl+C / Cmd+C for clipboard\n if ((event.ctrlKey || event.metaKey) && event.key === 'c' && selectionBounds) {\n event.preventDefault()\n copySelectionToClipboard()\n return\n }\n\n // Handle Escape\n if (event.key === 'Escape') {\n setSelectedCell(null)\n setSelectionStart(null)\n setSelectionEnd(null)\n setShowSearchInput(false)\n setGlobalSearchTerm('')\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n return () => document.removeEventListener('keydown', handleKeydown)\n }, [selectionBounds, copySelectionToClipboard])\n\n // Filter dropdown\n const openFilterDropdown = useCallback(\n (columnId: string, event: React.MouseEvent) => {\n event.stopPropagation()\n const target = event.currentTarget as HTMLElement\n const headerCell = target.closest('.vpg-header-cell') as HTMLElement\n const rect = headerCell?.getBoundingClientRect() || target.getBoundingClientRect()\n\n const dropdownWidth = 280\n const padding = 12\n\n let left = rect.left\n if (left + dropdownWidth > window.innerWidth - padding) {\n left = window.innerWidth - dropdownWidth - padding\n }\n left = Math.max(padding, left)\n\n const spaceBelow = window.innerHeight - rect.bottom - padding\n const spaceAbove = rect.top - padding\n\n let top: number\n let maxDropdownHeight: number\n\n if (spaceBelow >= 300 || spaceBelow >= spaceAbove) {\n top = rect.bottom + 4\n maxDropdownHeight = Math.min(400, spaceBelow - 4)\n }\n else {\n maxDropdownHeight = Math.min(400, spaceAbove - 4)\n top = rect.top - maxDropdownHeight - 4\n }\n\n setFilterDropdownPosition({ top, left, maxHeight: maxDropdownHeight })\n setActiveFilterColumn(columnId)\n },\n [],\n )\n\n const closeFilterDropdown = useCallback(() => {\n setActiveFilterColumn(null)\n }, [])\n\n const handleFilter = useCallback(\n (columnId: string, values: string[]) => {\n setColumnFilter(columnId, values)\n },\n [setColumnFilter],\n )\n\n const handleRangeFilter = useCallback(\n (columnId: string, range: import('@smallwebco/tinypivot-core').NumericRange | null) => {\n setNumericRangeFilter(columnId, range)\n },\n [setNumericRangeFilter],\n )\n\n const handleDateRangeFilter = useCallback(\n (columnId: string, range: DateRange | null) => {\n setDateRangeFilter(columnId, range)\n },\n [setDateRangeFilter],\n )\n\n const handleSort = useCallback(\n (columnId: string, direction: 'asc' | 'desc' | null) => {\n if (direction === null) {\n const current = getSortDirection(columnId)\n if (current) {\n toggleSort(columnId)\n if (getSortDirection(columnId)) {\n toggleSort(columnId)\n }\n }\n }\n else {\n const current = getSortDirection(columnId)\n if (current === null) {\n toggleSort(columnId)\n if (direction === 'desc' && getSortDirection(columnId) === 'asc') {\n toggleSort(columnId)\n }\n }\n else if (current !== direction) {\n toggleSort(columnId)\n }\n }\n },\n [getSortDirection, toggleSort],\n )\n\n const isCellSelected = useCallback(\n (rowIndex: number, colIndex: number): boolean => {\n if (!selectionBounds) {\n return selectedCell?.row === rowIndex && selectedCell?.col === colIndex\n }\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol\n },\n [selectionBounds, selectedCell],\n )\n\n const formatStatValue = (value: number | null): string => {\n if (value === null)\n return '-'\n return coreFormatNumber(value, numberFormat)\n }\n\n // Format cell value\n const noFormatPatterns\n = /^(?:.*_)?(?:id|code|year|month|quarter|day|week|date|zip|phone|fax|ssn|ein|npi|ndc|gpi|hcpcs|icd|cpt|rx|bin|pcn|group|member|claim|rx_number|script|fill)(?:_.*)?$/i\n\n const shouldFormatNumber = (columnId: string): boolean => {\n return !noFormatPatterns.test(columnId)\n }\n\n const formatCellValueDisplay = (value: unknown, columnId: string): string => {\n if (value === null || value === undefined)\n return ''\n if (value === '')\n return ''\n\n const stats = getColumnStats(columnId)\n\n if (stats.type === 'date') {\n return coreFormatDate(value, dateFormat)\n }\n\n if (stats.type === 'number') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (Number.isNaN(num))\n return String(value)\n\n if (shouldFormatNumber(columnId) && Math.abs(num) >= 1000) {\n return coreFormatNumber(num, numberFormat)\n }\n\n if (Number.isInteger(num)) {\n return String(num)\n }\n return coreFormatNumber(num, numberFormat, { maximumFractionDigits: 4 })\n }\n\n return String(value)\n }\n\n const totalTableWidth = useMemo(() => {\n return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0)\n }, [columnKeys, columnWidths])\n\n const activeFilterCount = columnFilters.length\n\n return (\n <div\n className={`vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? 'vpg-striped' : ''} ${resizingColumnId ? 'vpg-resizing' : ''} ${isResizingVertically ? 'vpg-resizing-vertical' : ''}`}\n style={{ height: `${gridHeight}px` }}\n >\n {/* Copy Toast */}\n {showCopyToast && (\n <div className=\"vpg-toast\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n {copyToastMessage}\n </div>\n )}\n\n {/* Toolbar */}\n <div className=\"vpg-toolbar\">\n <div className=\"vpg-toolbar-left\">\n {/* View mode toggle */}\n {showPivot && (\n <div className=\"vpg-view-toggle\">\n {/* AI Analyst button (first, only if enabled) */}\n {showAIAnalyst && (\n <button\n className={`vpg-view-btn vpg-ai-btn ${viewMode === 'ai' ? 'active' : ''}`}\n onClick={() => setViewMode('ai')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z\" />\n </svg>\n AI Analyst\n </button>\n )}\n {aiAnalyst?.enabled && !canUseAIAnalyst && (\n <button\n className=\"vpg-view-btn vpg-ai-btn vpg-pro-feature\"\n title=\"AI Analyst (Pro feature)\"\n onClick={e => e.preventDefault()}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z\" />\n </svg>\n AI Analyst\n <span className=\"vpg-pro-badge\">Pro</span>\n </button>\n )}\n <button\n className={`vpg-view-btn ${viewMode === 'grid' ? 'active' : ''}`}\n onClick={() => setViewMode('grid')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n Grid\n </button>\n <button\n className={`vpg-view-btn vpg-pivot-btn ${viewMode === 'pivot' ? 'active' : ''}`}\n onClick={() => setViewMode('pivot')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n Pivot\n </button>\n <button\n className={`vpg-view-btn vpg-chart-btn ${viewMode === 'chart' ? 'active' : ''} ${!canUseCharts ? 'vpg-pro-feature' : ''}`}\n title={canUseCharts ? 'Chart Builder' : 'Chart Builder (Pro feature)'}\n onClick={() => canUseCharts && setViewMode('chart')}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n Chart\n {!canUseCharts && <span className=\"vpg-pro-badge\">Pro</span>}\n </button>\n </div>\n )}\n\n {/* Grid mode controls */}\n {viewMode === 'grid' && (\n <>\n {/* Search */}\n {enableSearch && (\n <div className=\"vpg-search-container\">\n {!showSearchInput\n ? (\n <button\n className=\"vpg-icon-btn\"\n title=\"Search (Ctrl+F)\"\n onClick={() => setShowSearchInput(true)}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n </button>\n )\n : (\n <div className=\"vpg-search-box\">\n <svg\n className=\"vpg-search-icon\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <input\n type=\"text\"\n value={globalSearchTerm}\n onChange={e => setGlobalSearchTerm(e.target.value)}\n className=\"vpg-search-input\"\n placeholder=\"Search all columns...\"\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n setShowSearchInput(false)\n setGlobalSearchTerm('')\n }\n }}\n autoFocus\n />\n {globalSearchTerm && (\n <button className=\"vpg-search-clear\" onClick={() => setGlobalSearchTerm('')}>\n <svg\n className=\"vpg-icon-xs\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n )}\n </div>\n )}\n\n <div className=\"vpg-font-size-control\">\n <span className=\"vpg-label\">Size:</span>\n <div className=\"vpg-font-size-toggle\">\n {fontSizeOptions.map(opt => (\n <button\n key={opt.value}\n className={`vpg-font-size-btn ${currentFontSize === opt.value ? 'active' : ''}`}\n onClick={() => setCurrentFontSize(opt.value)}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </div>\n\n {activeFilterCount > 0 && (\n <div className=\"vpg-filter-info\">\n <svg className=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span>\n {activeFilterCount}\n {' '}\n filter\n {activeFilterCount > 1 ? 's' : ''}\n </span>\n </div>\n )}\n\n {globalSearchTerm && (\n <div className=\"vpg-search-info\">\n <span>\n {totalSearchedRows}\n {' '}\n match\n {totalSearchedRows !== 1 ? 'es' : ''}\n </span>\n </div>\n )}\n </>\n )}\n\n {/* Pivot mode controls */}\n {viewMode === 'pivot' && canUsePivot && (\n <>\n <button\n className={`vpg-config-toggle ${showPivotConfig ? 'active' : ''}`}\n onClick={() => setShowPivotConfig(!showPivotConfig)}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4\"\n />\n </svg>\n {showPivotConfig ? 'Hide' : 'Show'}\n {' '}\n Config\n </button>\n\n {pivotIsConfigured && (\n <div className=\"vpg-pivot-status\">\n <svg className=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span>Pivot configured</span>\n </div>\n )}\n </>\n )}\n </div>\n\n <div className=\"vpg-toolbar-right\">\n {viewMode === 'grid' && activeFilterCount > 0 && (\n <button className=\"vpg-clear-filters\" onClick={clearAllFilters}>\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Clear Filters\n </button>\n )}\n\n {/* Reset to full data button (when showing AI-filtered results) */}\n {viewMode === 'grid' && isShowingAIData && (\n <button\n className={`vpg-reset-data-btn${isLoadingFullData ? ' vpg-loading-btn' : ''}`}\n disabled={isLoadingFullData}\n title=\"Reset to full dataset\"\n onClick={resetToFullData}\n >\n <svg className={`vpg-icon${isLoadingFullData ? ' vpg-spin' : ''}`} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n <span>{isLoadingFullData ? 'Loading...' : 'Full Data'}</span>\n </button>\n )}\n\n {/* Copy button */}\n {enableClipboard && selectionBounds && viewMode === 'grid' && (\n <button\n className=\"vpg-icon-btn\"\n title=\"Copy selection (Ctrl+C)\"\n onClick={copySelectionToClipboard}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n </button>\n )}\n\n {/* Export button - Grid export is free, Pivot export requires Pro */}\n {enableExport && viewMode === 'grid' && (\n <button\n className=\"vpg-export-btn\"\n title=\"Export to CSV\"\n onClick={handleExport}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n Export\n </button>\n )}\n {enableExport && viewMode === 'pivot' && pivotIsConfigured && (\n <button\n className={`vpg-export-btn ${!isPro ? 'vpg-export-btn-disabled' : ''}`}\n disabled={!isPro}\n title={isPro ? 'Export Pivot to CSV' : 'Export Pivot to CSV (Pro feature)'}\n onClick={() => isPro && handleExport()}\n >\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n Export Pivot\n {!isPro ? ' (Pro)' : ''}\n </button>\n )}\n </div>\n </div>\n\n {/* AI Analyst View - always render if enabled, use CSS to hide for state preservation */}\n {showAIAnalyst && aiAnalyst && (\n <div className=\"vpg-ai-view\" style={{ display: viewMode === 'ai' ? undefined : 'none' }}>\n <AIAnalyst\n ref={aiAnalystRef}\n config={aiAnalyst}\n theme={currentTheme}\n onDataLoaded={handleAIDataLoaded}\n onConversationUpdate={handleAIConversationUpdate}\n onQueryExecuted={handleAIQueryExecuted}\n onError={handleAIError}\n />\n </div>\n )}\n\n {/* Grid View */}\n {viewMode === 'grid' && (\n <div ref={tableContainerRef} className=\"vpg-grid-container\" tabIndex={0}>\n {loading && (\n <div className=\"vpg-loading\">\n <div className=\"vpg-spinner\" />\n <span>Loading data...</span>\n </div>\n )}\n\n {!loading && displayData.length === 0 && (\n <div className=\"vpg-empty\">\n <div className=\"vpg-empty-icon\">\n <svg className=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n </div>\n <span>No data available</span>\n </div>\n )}\n\n {!loading && displayData.length > 0 && filteredRowCount === 0 && (\n <div className=\"vpg-empty\">\n <div className=\"vpg-empty-icon vpg-warning\">\n <svg className=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n </div>\n <span>No matching records</span>\n <button className=\"vpg-clear-link\" onClick={clearAllFilters}>\n Clear all filters\n </button>\n </div>\n )}\n\n {!loading && filteredRowCount > 0 && (\n <div className=\"vpg-table-wrapper\">\n <table className=\"vpg-table\" style={{ minWidth: `${totalTableWidth}px` }}>\n <thead>\n <tr>\n {columnKeys.map(colId => (\n <th\n key={colId}\n className={`vpg-header-cell ${hasActiveFilter(colId) ? 'vpg-has-filter' : ''} ${getSortDirection(colId) !== null ? 'vpg-is-sorted' : ''} ${activeFilterColumn === colId ? 'vpg-is-active' : ''}`}\n style={{\n width: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n }}\n onClick={(e) => {\n const target = e.target as HTMLElement\n if (target.closest('.vpg-dropdown-arrow')) {\n openFilterDropdown(colId, e)\n }\n }}\n >\n <div className=\"vpg-header-content\">\n <span className=\"vpg-header-text\">{colId}</span>\n <div className=\"vpg-header-icons\">\n {getSortDirection(colId) && (\n <span className=\"vpg-sort-indicator\">\n {getSortDirection(colId) === 'asc'\n ? (\n <svg\n className=\"vpg-icon-sm\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )\n : (\n <svg\n className=\"vpg-icon-sm\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )}\n </span>\n )}\n {hasActiveFilter(colId) && (\n <span className=\"vpg-filter-indicator\">\n <svg\n className=\"vpg-icon-xs\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </span>\n )}\n <span className=\"vpg-dropdown-arrow\" title=\"Filter & Sort\">\n <svg\n className=\"vpg-icon-sm\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </span>\n </div>\n </div>\n {enableColumnResize && (\n <div\n className=\"vpg-resize-handle\"\n onMouseDown={e => startColumnResize(colId, e)}\n />\n )}\n </th>\n ))}\n </tr>\n </thead>\n\n <tbody ref={tableBodyRef}>\n {paginatedRows.map((row, rowIndex) => (\n <tr key={row.id} className=\"vpg-row\">\n {columnKeys.map((colId, colIndex) => (\n <td\n key={colId}\n className={`vpg-cell ${isCellSelected(rowIndex, colIndex) ? 'vpg-selected' : ''} ${getColumnStats(colId).type === 'number' ? 'vpg-is-number' : ''}`}\n data-row={rowIndex}\n data-col={colIndex}\n style={{\n width: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px`,\n }}\n onMouseDown={e => handleMouseDown(rowIndex, colIndex, e)}\n onMouseEnter={() => handleMouseEnter(rowIndex, colIndex)}\n >\n {formatCellValueDisplay(row.original[colId], colId)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* Pivot View */}\n {viewMode === 'pivot' && (\n <div className=\"vpg-pivot-container\">\n {showPivotConfig && canUsePivot && (\n <div className=\"vpg-pivot-config-panel\">\n <PivotConfig\n availableFields={pivotAvailableFields}\n rowFields={pivotRowFields}\n columnFields={pivotColumnFields}\n valueFields={pivotValueFields}\n showRowTotals={pivotShowRowTotals}\n showColumnTotals={pivotShowColumnTotals}\n calculatedFields={pivotCalculatedFields}\n onShowRowTotalsChange={setPivotShowRowTotals}\n onShowColumnTotalsChange={setPivotShowColumnTotals}\n onClearConfig={clearPivotConfig}\n onAutoSuggest={autoSuggestConfig}\n onDragStart={(field, _e) => setDraggingField(field)}\n onDragEnd={() => setDraggingField(null)}\n onUpdateAggregation={updateValueFieldAggregation}\n onAddRowField={addRowField}\n onRemoveRowField={removeRowField}\n onAddColumnField={addColumnField}\n onRemoveColumnField={removeColumnField}\n onAddValueField={addValueField}\n onRemoveValueField={removeValueField}\n onAddCalculatedField={addCalculatedField}\n onRemoveCalculatedField={removeCalculatedField}\n onUpdateCalculatedField={addCalculatedField}\n />\n </div>\n )}\n\n <div className={`vpg-pivot-main ${!showPivotConfig ? 'vpg-full-width' : ''}`}>\n <PivotSkeleton\n rowFields={pivotRowFields}\n columnFields={pivotColumnFields}\n valueFields={pivotValueFields}\n calculatedFields={pivotCalculatedFields}\n isConfigured={pivotIsConfigured}\n draggingField={draggingField}\n pivotResult={pivotResult}\n fontSize={currentFontSize}\n activeFilters={activeFilterInfo}\n totalRowCount={totalRowCount}\n filteredRowCount={filteredRowCount}\n onAddRowField={addRowField}\n onRemoveRowField={removeRowField}\n onAddColumnField={addColumnField}\n onRemoveColumnField={removeColumnField}\n onAddValueField={addValueField}\n onRemoveValueField={removeValueField}\n onUpdateAggregation={updateValueFieldAggregation}\n onReorderRowFields={setRowFields}\n onReorderColumnFields={setColumnFields}\n />\n </div>\n </div>\n )}\n\n {/* Chart View */}\n {viewMode === 'chart' && (\n <div className=\"vpg-chart-view\">\n {/* Filter indicator for chart */}\n {activeFilterInfo && activeFilterInfo.length > 0 && (\n <div className=\"vpg-chart-filter-bar\">\n <svg className=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\" clipRule=\"evenodd\" />\n </svg>\n <span>\n Chart showing\n {filteredRowCount.toLocaleString()}\n {' '}\n of\n {totalRowCount.toLocaleString()}\n {' '}\n records\n </span>\n <button className=\"vpg-chart-clear-filters\" onClick={clearAllFilters}>\n Clear filters\n </button>\n </div>\n )}\n <ChartBuilder\n data={filteredDataForPivot}\n theme={currentTheme}\n onConfigChange={handleChartConfigChange}\n />\n </div>\n )}\n\n {/* Footer */}\n <div className=\"vpg-footer\">\n <div className=\"vpg-footer-left\">\n {viewMode === 'grid'\n ? (\n enablePagination\n ? (\n <>\n <span>\n {((currentPage - 1) * pageSize + 1).toLocaleString()}\n -\n {Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()}\n </span>\n <span className=\"vpg-separator\">of</span>\n <span>{totalSearchedRows.toLocaleString()}</span>\n {totalSearchedRows !== totalRowCount && (\n <span className=\"vpg-filtered-note\">\n (\n {totalRowCount.toLocaleString()}\n {' '}\n total)\n </span>\n )}\n </>\n )\n : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount\n ? (\n <span>\n {totalRowCount.toLocaleString()}\n {' '}\n records\n </span>\n )\n : (\n <>\n <span className=\"vpg-filtered-count\">{totalSearchedRows.toLocaleString()}</span>\n <span className=\"vpg-separator\">of</span>\n <span>{totalRowCount.toLocaleString()}</span>\n <span className=\"vpg-separator\">records</span>\n </>\n )\n )\n : viewMode === 'pivot'\n ? (\n <>\n <span className=\"vpg-pivot-label\">Pivot Table</span>\n <span className=\"vpg-separator\">•</span>\n <span>\n {totalRowCount.toLocaleString()}\n {' '}\n source records\n </span>\n </>\n )\n : (\n <>\n <span className=\"vpg-chart-label\">Chart Builder</span>\n <span className=\"vpg-separator\">•</span>\n <span>\n {totalRowCount.toLocaleString()}\n {' '}\n records\n </span>\n </>\n )}\n </div>\n\n {/* Pagination controls */}\n {enablePagination && viewMode === 'grid' && totalPages > 1 && (\n <div className=\"vpg-pagination\">\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage(1)}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 19l-7-7 7-7m8 14l-7-7 7-7\"\n />\n </svg>\n </button>\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage(p => Math.max(1, p - 1))}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 19l-7-7 7-7\"\n />\n </svg>\n </button>\n <span className=\"vpg-page-info\">\n Page\n {' '}\n {currentPage}\n {' '}\n of\n {' '}\n {totalPages}\n </span>\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === totalPages}\n onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 5l7 7-7 7\"\n />\n </svg>\n </button>\n <button\n className=\"vpg-page-btn\"\n disabled={currentPage === totalPages}\n onClick={() => setCurrentPage(totalPages)}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 5l7 7-7 7M5 5l7 7-7 7\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {viewMode === 'grid' && selectionStats && selectionStats.count > 1 && (\n <div className=\"vpg-selection-stats\">\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Count:</span>\n <span className=\"vpg-stat-value\">{selectionStats.count}</span>\n </span>\n {selectionStats.numericCount > 0 && (\n <>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Sum:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.sum)}</span>\n </span>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Avg:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.avg)}</span>\n </span>\n </>\n )}\n </div>\n )}\n\n <div className=\"vpg-footer-right\">\n {isDemo\n ? (\n <div className=\"vpg-demo-banner\">\n <span className=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features enabled</span>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener noreferrer\">\n Get License →\n </a>\n </div>\n )\n : showWatermark\n ? (\n <span className=\"vpg-watermark-inline\">\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener noreferrer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" />\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" />\n </svg>\n Powered by TinyPivot\n </a>\n </span>\n )\n : null}\n </div>\n </div>\n\n {/* Vertical Resize Handle */}\n {enableVerticalResize && (\n <div className=\"vpg-vertical-resize-handle\" onMouseDown={startVerticalResize}>\n <div className=\"vpg-resize-grip\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n )}\n\n {/* Filter Dropdown Portal */}\n {activeFilterColumn && typeof document !== 'undefined'\n && createPortal(\n <div\n className=\"vpg-filter-portal\"\n style={{\n position: 'fixed',\n top: `${filterDropdownPosition.top}px`,\n left: `${filterDropdownPosition.left}px`,\n maxHeight: `${filterDropdownPosition.maxHeight}px`,\n zIndex: 9999,\n }}\n >\n <ColumnFilter\n columnId={activeFilterColumn}\n columnName={activeFilterColumn}\n stats={getColumnStats(activeFilterColumn)}\n selectedValues={getColumnFilterValues(activeFilterColumn)}\n sortDirection={getSortDirection(activeFilterColumn)}\n numericRange={getNumericRangeFilter(activeFilterColumn)}\n dateRange={getDateRangeFilter(activeFilterColumn)}\n numberFormat={numberFormat}\n dateFormat={dateFormat}\n onFilter={values => handleFilter(activeFilterColumn, values)}\n onRangeFilter={range => handleRangeFilter(activeFilterColumn, range)}\n onDateRangeFilter={range => handleDateRangeFilter(activeFilterColumn, range)}\n onSort={dir => handleSort(activeFilterColumn, dir)}\n onClose={closeFilterDropdown}\n />\n </div>,\n document.body,\n )}\n </div>\n )\n}\n","import type { ColumnFilterValue, ColumnStats, DateRange, NumericRange } from '@smallwebco/tinypivot-core'\nimport { formatCellValue, getColumnUniqueValues, isDateRange, isNumericRange } from '@smallwebco/tinypivot-core'\nimport {\n type ColumnDef,\n type ColumnFiltersState,\n type FilterFn,\n getCoreRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n type SortingState,\n useReactTable,\n type VisibilityState,\n} from '@tanstack/react-table'\n/**\n * Excel-like Grid Hook for React\n * Provides Excel-like filtering, sorting, and data manipulation functionality\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react'\n\n// Re-export for convenience\nexport { formatCellValue, getColumnUniqueValues, isDateRange, isNumericRange }\n\nexport interface ExcelGridOptions<T> {\n data: T[]\n columns?: string[]\n enableSorting?: boolean\n enableFiltering?: boolean\n pageSize?: number\n}\n\n/**\n * Combined filter function for Excel-style filtering, numeric range, and date range filtering\n */\nconst multiSelectFilter: FilterFn<unknown> = (row, columnId, filterValue: ColumnFilterValue | undefined) => {\n if (!filterValue)\n return true\n\n // Handle numeric range filter\n if (isNumericRange(filterValue)) {\n const cellValue = row.getValue(columnId)\n if (cellValue === null || cellValue === undefined || cellValue === '') {\n return false // Exclude null/empty values from numeric range filtering\n }\n const num = typeof cellValue === 'number' ? cellValue : Number.parseFloat(String(cellValue))\n if (Number.isNaN(num))\n return false\n\n const { min, max } = filterValue\n if (min !== null && num < min)\n return false\n if (max !== null && num > max)\n return false\n return true\n }\n\n // Handle date range filter\n if (isDateRange(filterValue)) {\n const cellValue = row.getValue(columnId)\n if (cellValue === null || cellValue === undefined || cellValue === '') {\n return false\n }\n const dateObj = cellValue instanceof Date ? cellValue : new Date(String(cellValue))\n if (Number.isNaN(dateObj.getTime()))\n return false\n const dateStr = dateObj.toISOString().split('T')[0]\n\n const { min, max } = filterValue\n if (min !== null && dateStr < min)\n return false\n if (max !== null && dateStr > max)\n return false\n return true\n }\n\n // Handle multi-select array filter\n if (Array.isArray(filterValue) && filterValue.length > 0) {\n const cellValue = row.getValue(columnId)\n const cellString\n = cellValue === null || cellValue === undefined || cellValue === ''\n ? '(blank)'\n : String(cellValue)\n return filterValue.includes(cellString)\n }\n\n return true\n}\n\n/**\n * Excel-like grid hook\n */\nexport function useExcelGrid<T extends Record<string, unknown>>(options: ExcelGridOptions<T>) {\n const { data, enableSorting = true, enableFiltering = true } = options\n\n // State\n const [sorting, setSorting] = useState<SortingState>([])\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])\n const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})\n const [globalFilter, setGlobalFilter] = useState('')\n\n // Column statistics cache\n const [columnStatsCache, setColumnStatsCache] = useState<Record<string, ColumnStats>>({})\n\n const dataSignature = useMemo(\n () => `${Date.now()}-${Math.random().toString(36).slice(2)}`,\n [data],\n )\n\n // Compute columns from data\n const columnKeys = useMemo(() => {\n if (data.length === 0)\n return []\n return Object.keys(data[0] as Record<string, unknown>)\n }, [data])\n\n // Get column stats (memoized)\n const getColumnStats = useCallback(\n (columnKey: string): ColumnStats => {\n const cacheKey = `${columnKey}-${dataSignature}`\n if (!columnStatsCache[cacheKey]) {\n const stats = getColumnUniqueValues(data, columnKey)\n setColumnStatsCache(prev => ({ ...prev, [cacheKey]: stats }))\n return stats\n }\n return columnStatsCache[cacheKey]\n },\n [data, columnStatsCache, dataSignature],\n )\n\n // Clear stats cache\n const clearStatsCache = useCallback(() => {\n setColumnStatsCache({})\n }, [])\n\n useEffect(() => {\n clearStatsCache()\n }, [dataSignature, clearStatsCache])\n\n // Create column definitions dynamically\n const columnDefs = useMemo<ColumnDef<T, unknown>[]>(() => {\n return columnKeys.map((key) => {\n const stats = getColumnStats(key)\n\n return {\n id: key,\n accessorKey: key,\n header: key,\n cell: info => formatCellValue(info.getValue(), stats.type),\n filterFn: multiSelectFilter,\n meta: {\n type: stats.type,\n uniqueCount: stats.uniqueValues.length,\n },\n } as ColumnDef<T, unknown>\n })\n }, [columnKeys, getColumnStats])\n\n // Create table instance\n const table = useReactTable({\n data,\n columns: columnDefs,\n state: {\n sorting,\n columnFilters,\n columnVisibility,\n globalFilter,\n },\n onSortingChange: setSorting,\n onColumnFiltersChange: setColumnFilters,\n onColumnVisibilityChange: setColumnVisibility,\n onGlobalFilterChange: setGlobalFilter,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: enableSorting ? getSortedRowModel() : undefined,\n getFilteredRowModel: enableFiltering ? getFilteredRowModel() : undefined,\n filterFns: {\n multiSelect: multiSelectFilter,\n },\n enableSorting,\n enableFilters: enableFiltering,\n })\n\n // Computed properties\n const filteredRowCount = table.getFilteredRowModel().rows.length\n const totalRowCount = data.length\n\n // Active filters (handles array values, numeric ranges, and date ranges)\n const activeFilters = useMemo(() => {\n return columnFilters.map((f) => {\n const filterValue = f.value as ColumnFilterValue | undefined\n\n // Handle numeric range\n if (filterValue && isNumericRange(filterValue)) {\n return {\n column: f.id,\n type: 'range' as const,\n range: filterValue,\n dateRange: null as DateRange | null,\n values: [] as string[],\n }\n }\n\n // Handle date range\n if (filterValue && isDateRange(filterValue)) {\n return {\n column: f.id,\n type: 'dateRange' as const,\n range: null as NumericRange | null,\n dateRange: filterValue,\n values: [] as string[],\n }\n }\n\n // Handle value array\n return {\n column: f.id,\n type: 'values' as const,\n values: Array.isArray(filterValue) ? filterValue : [],\n range: null as NumericRange | null,\n dateRange: null as DateRange | null,\n }\n })\n }, [columnFilters])\n\n // Check if column has active filter (handles array, numeric range, and date range)\n const hasActiveFilter = useCallback(\n (columnId: string): boolean => {\n const column = table.getColumn(columnId)\n if (!column)\n return false\n const filterValue = column.getFilterValue() as ColumnFilterValue | undefined\n if (!filterValue)\n return false\n\n // Check for numeric range\n if (isNumericRange(filterValue)) {\n return filterValue.min !== null || filterValue.max !== null\n }\n\n // Check for date range\n if (isDateRange(filterValue)) {\n return filterValue.min !== null || filterValue.max !== null\n }\n\n // Check for value array\n return Array.isArray(filterValue) && filterValue.length > 0\n },\n [table],\n )\n\n // Set column filter (value-based)\n const setColumnFilter = useCallback(\n (columnId: string, values: string[]) => {\n const column = table.getColumn(columnId)\n if (column) {\n // Let the table's onColumnFiltersChange handler update the state\n // Do NOT manually call setColumnFilters after - it causes a race condition\n // where the stale state overwrites the pending update\n column.setFilterValue(values.length === 0 ? undefined : values)\n }\n },\n [table],\n )\n\n // Set numeric range filter\n const setNumericRangeFilter = useCallback(\n (columnId: string, range: NumericRange | null) => {\n const column = table.getColumn(columnId)\n if (column) {\n if (!range || (range.min === null && range.max === null)) {\n column.setFilterValue(undefined)\n }\n else {\n column.setFilterValue(range)\n }\n }\n },\n [table],\n )\n\n // Get numeric range filter for a column\n const getNumericRangeFilter = useCallback(\n (columnId: string): NumericRange | null => {\n const column = table.getColumn(columnId)\n if (!column)\n return null\n const filterValue = column.getFilterValue() as ColumnFilterValue | undefined\n if (filterValue && isNumericRange(filterValue)) {\n return filterValue\n }\n return null\n },\n [table],\n )\n\n // Set date range filter\n const setDateRangeFilter = useCallback(\n (columnId: string, range: DateRange | null) => {\n const column = table.getColumn(columnId)\n if (column) {\n if (!range || (range.min === null && range.max === null)) {\n column.setFilterValue(undefined)\n }\n else {\n column.setFilterValue(range)\n }\n }\n },\n [table],\n )\n\n // Get date range filter for a column\n const getDateRangeFilter = useCallback(\n (columnId: string): DateRange | null => {\n const column = table.getColumn(columnId)\n if (!column)\n return null\n const filterValue = column.getFilterValue() as ColumnFilterValue | undefined\n if (filterValue && isDateRange(filterValue)) {\n return filterValue\n }\n return null\n },\n [table],\n )\n\n // Clear all filters\n const clearAllFilters = useCallback(() => {\n table.resetColumnFilters()\n setGlobalFilter('')\n // Force sync columnFilters state\n setColumnFilters([])\n }, [table])\n\n // Get filter values for a specific column\n const getColumnFilterValues = useCallback(\n (columnId: string): string[] => {\n const column = table.getColumn(columnId)\n if (!column)\n return []\n const filterValue = column.getFilterValue()\n return Array.isArray(filterValue) ? filterValue : []\n },\n [table],\n )\n\n // Toggle column sort\n const toggleSort = useCallback((columnId: string) => {\n setSorting((prev) => {\n const current = prev.find(s => s.id === columnId)\n if (!current) {\n return [{ id: columnId, desc: false }]\n }\n else if (!current.desc) {\n return [{ id: columnId, desc: true }]\n }\n else {\n return []\n }\n })\n }, [])\n\n // Get sort direction for column\n const getSortDirection = useCallback(\n (columnId: string): 'asc' | 'desc' | null => {\n const sort = sorting.find(s => s.id === columnId)\n if (!sort)\n return null\n return sort.desc ? 'desc' : 'asc'\n },\n [sorting],\n )\n\n return {\n // Table instance\n table,\n\n // State\n sorting,\n columnFilters,\n columnVisibility,\n globalFilter,\n columnKeys,\n setSorting,\n setColumnFilters,\n setGlobalFilter,\n\n // Computed\n filteredRowCount,\n totalRowCount,\n activeFilters,\n\n // Methods\n getColumnStats,\n clearStatsCache,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n // Numeric range filters\n setNumericRangeFilter,\n getNumericRangeFilter,\n // Date range filters\n setDateRangeFilter,\n getDateRangeFilter,\n }\n}\n","import type { ExportOptions, PaginationOptions, PivotExportData, PivotValueField, SelectionBounds } from '@smallwebco/tinypivot-core'\nimport {\n copyToClipboard as coreCopyToClipboard,\n exportPivotToCSV as coreExportPivotToCSV,\n exportToCSV as coreExportToCSV,\n formatSelectionForClipboard as coreFormatSelection,\n} from '@smallwebco/tinypivot-core'\n/**\n * Grid Features Hook for React\n * Provides CSV export, clipboard, pagination, and other utility features\n */\nimport { useCallback, useMemo, useState } from 'react'\n\n// Re-export core functions\nexport function exportToCSV<T extends Record<string, unknown>>(\n data: T[],\n columns: string[],\n options?: ExportOptions,\n): void {\n coreExportToCSV(data, columns, options)\n}\n\nexport function exportPivotToCSV(\n pivotData: PivotExportData,\n rowFields: string[],\n columnFields: string[],\n valueFields: PivotValueField[],\n options?: ExportOptions,\n): void {\n coreExportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options)\n}\n\nexport function copyToClipboard(\n text: string,\n onSuccess?: () => void,\n onError?: (err: Error) => void,\n): void {\n coreCopyToClipboard(text, onSuccess, onError)\n}\n\nexport function formatSelectionForClipboard<T extends Record<string, unknown>>(\n rows: T[],\n columns: string[],\n selectionBounds: SelectionBounds,\n): string {\n return coreFormatSelection(rows, columns, selectionBounds)\n}\n\n/**\n * Pagination hook\n */\nexport function usePagination<T>(data: T[], options: PaginationOptions = {}) {\n const [pageSize, setPageSize] = useState(options.pageSize ?? 50)\n const [currentPage, setCurrentPage] = useState(options.currentPage ?? 1)\n\n const totalPages = useMemo(\n () => Math.max(1, Math.ceil(data.length / pageSize)),\n [data.length, pageSize],\n )\n\n const paginatedData = useMemo(() => {\n const start = (currentPage - 1) * pageSize\n const end = start + pageSize\n return data.slice(start, end)\n }, [data, currentPage, pageSize])\n\n const startIndex = useMemo(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize])\n const endIndex = useMemo(\n () => Math.min(currentPage * pageSize, data.length),\n [currentPage, pageSize, data.length],\n )\n\n const goToPage = useCallback(\n (page: number) => {\n setCurrentPage(Math.max(1, Math.min(page, totalPages)))\n },\n [totalPages],\n )\n\n const nextPage = useCallback(() => {\n if (currentPage < totalPages) {\n setCurrentPage(prev => prev + 1)\n }\n }, [currentPage, totalPages])\n\n const prevPage = useCallback(() => {\n if (currentPage > 1) {\n setCurrentPage(prev => prev - 1)\n }\n }, [currentPage])\n\n const firstPage = useCallback(() => {\n setCurrentPage(1)\n }, [])\n\n const lastPage = useCallback(() => {\n setCurrentPage(totalPages)\n }, [totalPages])\n\n const updatePageSize = useCallback((size: number) => {\n setPageSize(size)\n setCurrentPage(1)\n }, [])\n\n return {\n pageSize,\n currentPage,\n totalPages,\n paginatedData,\n startIndex,\n endIndex,\n goToPage,\n nextPage,\n prevPage,\n firstPage,\n lastPage,\n setPageSize: updatePageSize,\n }\n}\n\n/**\n * Global search/filter hook\n */\nexport function useGlobalSearch<T extends Record<string, unknown>>(data: T[], columns: string[]) {\n const [searchTerm, setSearchTerm] = useState('')\n const [caseSensitive, setCaseSensitive] = useState(false)\n\n const filteredData = useMemo(() => {\n if (!searchTerm.trim()) {\n return data\n }\n\n const term = caseSensitive ? searchTerm.trim() : searchTerm.trim().toLowerCase()\n\n return data.filter((row) => {\n for (const col of columns) {\n const value = row[col]\n if (value === null || value === undefined)\n continue\n\n const strValue = caseSensitive ? String(value) : String(value).toLowerCase()\n\n if (strValue.includes(term)) {\n return true\n }\n }\n return false\n })\n }, [data, columns, searchTerm, caseSensitive])\n\n const clearSearch = useCallback(() => {\n setSearchTerm('')\n }, [])\n\n return {\n searchTerm,\n setSearchTerm,\n caseSensitive,\n setCaseSensitive,\n filteredData,\n clearSearch,\n }\n}\n\n/**\n * Row selection hook\n */\nexport function useRowSelection<T>(data: T[]) {\n const [selectedRowIndices, setSelectedRowIndices] = useState<Set<number>>(new Set())\n\n const selectedRows = useMemo(() => {\n return Array.from(selectedRowIndices)\n .sort((a, b) => a - b)\n .map(idx => data[idx])\n .filter(Boolean)\n }, [data, selectedRowIndices])\n\n const allSelected = useMemo(() => {\n return data.length > 0 && selectedRowIndices.size === data.length\n }, [data.length, selectedRowIndices.size])\n\n const someSelected = useMemo(() => {\n return selectedRowIndices.size > 0 && selectedRowIndices.size < data.length\n }, [data.length, selectedRowIndices.size])\n\n const toggleRow = useCallback((index: number) => {\n setSelectedRowIndices((prev) => {\n const next = new Set(prev)\n if (next.has(index)) {\n next.delete(index)\n }\n else {\n next.add(index)\n }\n return next\n })\n }, [])\n\n const selectRow = useCallback((index: number) => {\n setSelectedRowIndices(prev => new Set([...prev, index]))\n }, [])\n\n const deselectRow = useCallback((index: number) => {\n setSelectedRowIndices((prev) => {\n const next = new Set(prev)\n next.delete(index)\n return next\n })\n }, [])\n\n const selectAll = useCallback(() => {\n setSelectedRowIndices(new Set(data.map((_, idx) => idx)))\n }, [data])\n\n const deselectAll = useCallback(() => {\n setSelectedRowIndices(new Set())\n }, [])\n\n const toggleAll = useCallback(() => {\n if (allSelected) {\n deselectAll()\n }\n else {\n selectAll()\n }\n }, [allSelected, selectAll, deselectAll])\n\n const isSelected = useCallback(\n (index: number): boolean => {\n return selectedRowIndices.has(index)\n },\n [selectedRowIndices],\n )\n\n const selectRange = useCallback((startIndex: number, endIndex: number) => {\n const min = Math.min(startIndex, endIndex)\n const max = Math.max(startIndex, endIndex)\n setSelectedRowIndices((prev) => {\n const next = new Set(prev)\n for (let i = min; i <= max; i++) {\n next.add(i)\n }\n return next\n })\n }, [])\n\n return {\n selectedRowIndices,\n selectedRows,\n allSelected,\n someSelected,\n toggleRow,\n selectRow,\n deselectRow,\n selectAll,\n deselectAll,\n toggleAll,\n isSelected,\n selectRange,\n }\n}\n\n/**\n * Column resizing hook\n */\nexport function useColumnResize(\n initialWidths: Record<string, number>,\n minWidth = 60,\n maxWidth = 600,\n) {\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>({ ...initialWidths })\n const [isResizing, setIsResizing] = useState(false)\n const [resizingColumn, setResizingColumn] = useState<string | null>(null)\n\n const startResize = useCallback(\n (columnId: string, event: React.MouseEvent) => {\n setIsResizing(true)\n setResizingColumn(columnId)\n const startX = event.clientX\n const startWidth = columnWidths[columnId] || 150\n\n const handleMouseMove = (e: MouseEvent) => {\n const diff = e.clientX - startX\n const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + diff))\n setColumnWidths(prev => ({\n ...prev,\n [columnId]: newWidth,\n }))\n }\n\n const handleMouseUp = () => {\n setIsResizing(false)\n setResizingColumn(null)\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n },\n [columnWidths, minWidth, maxWidth],\n )\n\n const resetColumnWidth = useCallback(\n (columnId: string) => {\n if (initialWidths[columnId]) {\n setColumnWidths(prev => ({\n ...prev,\n [columnId]: initialWidths[columnId],\n }))\n }\n },\n [initialWidths],\n )\n\n const resetAllWidths = useCallback(() => {\n setColumnWidths({ ...initialWidths })\n }, [initialWidths])\n\n return {\n columnWidths,\n setColumnWidths,\n isResizing,\n resizingColumn,\n startResize,\n resetColumnWidth,\n resetAllWidths,\n }\n}\n","import type { LicenseInfo } from '@smallwebco/tinypivot-core'\nimport {\n canUseAIAnalyst as coreCanUseAIAnalyst,\n canUseCharts as coreCanUseCharts,\n canUsePivot as coreCanUsePivot,\n configureLicenseSecret as coreConfigureLicenseSecret,\n isPro as coreIsPro,\n shouldShowWatermark as coreShouldShowWatermark,\n getDemoLicenseInfo,\n getFreeLicenseInfo,\n logProRequired,\n validateLicenseKey,\n} from '@smallwebco/tinypivot-core'\n/**\n * License Management Hook for React\n * Wraps core license logic with React state management\n */\nimport { useCallback, useMemo, useState } from 'react'\n\n// Global state (shared across all hook instances)\nlet globalLicenseInfo: LicenseInfo = getFreeLicenseInfo()\nlet globalDemoMode = false\nconst listeners = new Set<() => void>()\n\nfunction notifyListeners() {\n listeners.forEach(listener => listener())\n}\n\n/**\n * Set the license key for the library\n */\nexport async function setLicenseKey(key: string): Promise<void> {\n globalLicenseInfo = await validateLicenseKey(key)\n\n if (!globalLicenseInfo.isValid) {\n console.warn('[TinyPivot] License validation failed. Check the console for environment details. Running in free mode.')\n }\n else if (globalLicenseInfo.type !== 'free') {\n console.info(`[TinyPivot] Pro license activated (${globalLicenseInfo.type})`)\n }\n\n notifyListeners()\n}\n\n/**\n * Enable demo mode - requires the correct demo secret\n * Returns true if activation succeeded, false if secret was invalid\n */\nexport async function enableDemoMode(secret: string): Promise<boolean> {\n const demoLicense = await getDemoLicenseInfo(secret)\n if (!demoLicense) {\n console.warn('[TinyPivot] Demo mode activation failed - invalid secret')\n return false\n }\n globalDemoMode = true\n globalLicenseInfo = demoLicense\n console.info('[TinyPivot] Demo mode enabled - all Pro features unlocked for evaluation')\n notifyListeners()\n return true\n}\n\n/**\n * Configure the license secret\n */\nexport function configureLicenseSecret(secret: string): void {\n coreConfigureLicenseSecret(secret)\n}\n\n/**\n * Hook for accessing license information\n */\nexport function useLicense() {\n const [, forceUpdate] = useState({})\n\n // Subscribe to global state changes\n useState(() => {\n const update = () => forceUpdate({})\n listeners.add(update)\n return () => listeners.delete(update)\n })\n\n const isDemo = globalDemoMode\n const licenseInfo = globalLicenseInfo\n\n const isPro = useMemo(\n () => globalDemoMode || coreIsPro(licenseInfo),\n [licenseInfo],\n )\n\n const canUsePivot = useMemo(\n () => globalDemoMode || coreCanUsePivot(licenseInfo),\n [licenseInfo],\n )\n\n const canUseAdvancedAggregations = useMemo(\n () => globalDemoMode || licenseInfo.features.advancedAggregations,\n [licenseInfo],\n )\n\n const canUsePercentageMode = useMemo(\n () => globalDemoMode || licenseInfo.features.percentageMode,\n [licenseInfo],\n )\n\n const canUseCharts = useMemo(\n () => globalDemoMode || coreCanUseCharts(licenseInfo),\n [licenseInfo],\n )\n\n const canUseAIAnalyst = useMemo(\n () => globalDemoMode || coreCanUseAIAnalyst(licenseInfo),\n [licenseInfo],\n )\n\n const showWatermark = useMemo(\n () => coreShouldShowWatermark(licenseInfo, globalDemoMode),\n [licenseInfo],\n )\n\n const requirePro = useCallback((feature: string): boolean => {\n if (!isPro) {\n logProRequired(feature)\n return false\n }\n return true\n }, [isPro])\n\n return {\n licenseInfo,\n isDemo,\n isPro,\n canUsePivot,\n canUseAdvancedAggregations,\n canUsePercentageMode,\n canUseCharts,\n canUseAIAnalyst,\n showWatermark,\n requirePro,\n }\n}\n","import type {\n AggregationFunction,\n CalculatedField,\n FieldStats,\n PivotConfig,\n PivotResult,\n PivotValueField,\n} from '@smallwebco/tinypivot-core'\nimport {\n computeAvailableFields,\n computePivotResult,\n generateStorageKey,\n getAggregationLabel,\n getUnassignedFields,\n isConfigValidForFields,\n isPivotConfigured,\n loadCalculatedFields,\n loadPivotConfig,\n saveCalculatedFields,\n savePivotConfig,\n} from '@smallwebco/tinypivot-core'\n/**\n * Pivot Table Hook for React\n * Wraps core pivot logic with React state management\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useLicense } from './useLicense'\n\n// Re-export for convenience\nexport { getAggregationLabel }\n\ninterface UsePivotTableReturn {\n // State\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n showRowTotals: boolean\n showColumnTotals: boolean\n calculatedFields: CalculatedField[]\n\n // Computed\n availableFields: FieldStats[]\n unassignedFields: FieldStats[]\n isConfigured: boolean\n pivotResult: PivotResult | null\n\n // Actions\n addRowField: (field: string) => void\n removeRowField: (field: string) => void\n addColumnField: (field: string) => void\n removeColumnField: (field: string) => void\n addValueField: (field: string, aggregation?: AggregationFunction) => void\n removeValueField: (field: string, aggregation?: AggregationFunction) => void\n updateValueFieldAggregation: (\n field: string,\n oldAgg: AggregationFunction,\n newAgg: AggregationFunction\n ) => void\n clearConfig: () => void\n setShowRowTotals: (value: boolean) => void\n setShowColumnTotals: (value: boolean) => void\n autoSuggestConfig: () => void\n setRowFields: (fields: string[]) => void\n setColumnFields: (fields: string[]) => void\n addCalculatedField: (field: CalculatedField) => void\n removeCalculatedField: (id: string) => void\n}\n\n/**\n * Main pivot table hook\n */\nexport function usePivotTable(data: Record<string, unknown>[]): UsePivotTableReturn {\n const { canUsePivot, requirePro } = useLicense()\n\n // Configuration state\n const [rowFields, setRowFieldsState] = useState<string[]>([])\n const [columnFields, setColumnFieldsState] = useState<string[]>([])\n const [valueFields, setValueFields] = useState<PivotValueField[]>([])\n const [showRowTotals, setShowRowTotals] = useState(true)\n const [showColumnTotals, setShowColumnTotals] = useState(true)\n const [calculatedFields, setCalculatedFields] = useState<CalculatedField[]>(() => loadCalculatedFields())\n const [currentStorageKey, setCurrentStorageKey] = useState<string | null>(null)\n\n // Compute available fields from data\n const availableFields = useMemo((): FieldStats[] => {\n return computeAvailableFields(data)\n }, [data])\n\n // Get fields that haven't been assigned yet\n const unassignedFields = useMemo(() => {\n return getUnassignedFields(availableFields, rowFields, columnFields, valueFields)\n }, [availableFields, rowFields, columnFields, valueFields])\n\n // Check if pivot is configured\n const isConfigured = useMemo(() => {\n return isPivotConfigured({\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n })\n }, [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals])\n\n // Build pivot result\n const pivotResult = useMemo((): PivotResult | null => {\n if (!isConfigured)\n return null\n if (!canUsePivot)\n return null\n\n return computePivotResult(data, {\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n calculatedFields,\n })\n }, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields])\n\n // Load/save config from storage\n useEffect(() => {\n if (data.length === 0)\n return\n\n const newKeys = Object.keys(data[0])\n const storageKey = generateStorageKey(newKeys)\n\n if (storageKey !== currentStorageKey) {\n setCurrentStorageKey(storageKey)\n\n const savedConfig = loadPivotConfig(storageKey)\n if (savedConfig && isConfigValidForFields(savedConfig, newKeys)) {\n setRowFieldsState(savedConfig.rowFields)\n setColumnFieldsState(savedConfig.columnFields)\n setValueFields(savedConfig.valueFields)\n setShowRowTotals(savedConfig.showRowTotals)\n setShowColumnTotals(savedConfig.showColumnTotals)\n if (savedConfig.calculatedFields) {\n setCalculatedFields(savedConfig.calculatedFields)\n }\n }\n else {\n // Validate current config\n const currentConfig: PivotConfig = {\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n }\n if (!isConfigValidForFields(currentConfig, newKeys)) {\n setRowFieldsState([])\n setColumnFieldsState([])\n setValueFields([])\n }\n }\n }\n }, [data])\n\n // Save config when it changes\n useEffect(() => {\n if (!currentStorageKey)\n return\n\n const config: PivotConfig = {\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n calculatedFields,\n }\n savePivotConfig(currentStorageKey, config)\n }, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields])\n\n // Actions - pivot is free with sum aggregation, Pro required for other aggregations\n const addRowField = useCallback(\n (field: string) => {\n if (!rowFields.includes(field)) {\n setRowFieldsState(prev => [...prev, field])\n }\n },\n [rowFields],\n )\n\n const removeRowField = useCallback((field: string) => {\n setRowFieldsState(prev => prev.filter(f => f !== field))\n }, [])\n\n const setRowFields = useCallback((fields: string[]) => {\n setRowFieldsState(fields)\n }, [])\n\n const addColumnField = useCallback(\n (field: string) => {\n if (!columnFields.includes(field)) {\n setColumnFieldsState(prev => [...prev, field])\n }\n },\n [columnFields],\n )\n\n const removeColumnField = useCallback((field: string) => {\n setColumnFieldsState(prev => prev.filter(f => f !== field))\n }, [])\n\n const setColumnFields = useCallback((fields: string[]) => {\n setColumnFieldsState(fields)\n }, [])\n\n const addValueField = useCallback(\n (field: string, aggregation: AggregationFunction = 'sum') => {\n // Pro required for non-sum aggregations\n if (aggregation !== 'sum' && !requirePro(`${aggregation} aggregation`)) {\n return\n }\n setValueFields((prev) => {\n if (prev.some(v => v.field === field && v.aggregation === aggregation)) {\n return prev\n }\n return [...prev, { field, aggregation }]\n })\n },\n [requirePro],\n )\n\n const removeValueField = useCallback((field: string, aggregation?: AggregationFunction) => {\n setValueFields((prev) => {\n if (aggregation) {\n return prev.filter(v => !(v.field === field && v.aggregation === aggregation))\n }\n return prev.filter(v => v.field !== field)\n })\n }, [])\n\n const updateValueFieldAggregation = useCallback(\n (field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction) => {\n setValueFields(prev =>\n prev.map((v) => {\n if (v.field === field && v.aggregation === oldAgg) {\n return { ...v, aggregation: newAgg }\n }\n return v\n }),\n )\n },\n [],\n )\n\n const clearConfig = useCallback(() => {\n setRowFieldsState([])\n setColumnFieldsState([])\n setValueFields([])\n }, [])\n\n const autoSuggestConfig = useCallback(() => {\n if (!requirePro('Pivot Table - Auto Suggest'))\n return\n if (availableFields.length === 0)\n return\n\n const categoricalFields = availableFields.filter(f => !f.isNumeric && f.uniqueCount < 50)\n const numericFields = availableFields.filter(f => f.isNumeric)\n\n if (categoricalFields.length > 0 && numericFields.length > 0) {\n setRowFieldsState([categoricalFields[0].field])\n setValueFields([{ field: numericFields[0].field, aggregation: 'sum' }])\n }\n }, [availableFields, requirePro])\n\n // Calculated field management\n const addCalculatedField = useCallback((field: CalculatedField) => {\n setCalculatedFields((prev) => {\n const existing = prev.findIndex(f => f.id === field.id)\n let updated: CalculatedField[]\n if (existing >= 0) {\n updated = [...prev.slice(0, existing), field, ...prev.slice(existing + 1)]\n }\n else {\n updated = [...prev, field]\n }\n saveCalculatedFields(updated)\n return updated\n })\n }, [])\n\n const removeCalculatedField = useCallback((id: string) => {\n setCalculatedFields((prev) => {\n const updated = prev.filter(f => f.id !== id)\n saveCalculatedFields(updated)\n return updated\n })\n // Also remove from value fields if it was being used\n setValueFields(prev => prev.filter(v => v.field !== `calc:${id}`))\n }, [])\n\n return {\n // State\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n calculatedFields,\n\n // Computed\n availableFields,\n unassignedFields,\n isConfigured,\n pivotResult,\n\n // Actions\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig,\n setShowRowTotals,\n setShowColumnTotals,\n autoSuggestConfig,\n setRowFields,\n setColumnFields,\n addCalculatedField,\n removeCalculatedField,\n }\n}\n","import type { AggregationFunction, CalculatedField, FieldStats, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { AGGREGATION_OPTIONS, getAggregationSymbol } from '@smallwebco/tinypivot-core'\n/**\n * Pivot Table Configuration Panel for React\n * Draggable fields with aggregation selection\n */\nimport React, { useCallback, useMemo, useState } from 'react'\nimport { useLicense } from '../hooks/useLicense'\nimport { CalculatedFieldModal } from './CalculatedFieldModal'\n\n// Check if an aggregation requires Pro license (everything except sum)\nfunction aggregationRequiresPro(agg: AggregationFunction): boolean {\n return agg !== 'sum'\n}\n\n// Extended field stats for calculated fields\ninterface ExtendedFieldStats extends FieldStats {\n isCalculated?: boolean\n calcId?: string\n calcName?: string\n calcFormula?: string\n}\n\ninterface PivotConfigProps {\n availableFields: FieldStats[]\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n showRowTotals: boolean\n showColumnTotals: boolean\n calculatedFields?: CalculatedField[]\n onShowRowTotalsChange: (value: boolean) => void\n onShowColumnTotalsChange: (value: boolean) => void\n onClearConfig: () => void\n onAutoSuggest: () => void\n onDragStart: (field: string, event: React.DragEvent) => void\n onDragEnd: () => void\n onUpdateAggregation: (field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction) => void\n onAddRowField: (field: string) => void\n onRemoveRowField: (field: string) => void\n onAddColumnField: (field: string) => void\n onRemoveColumnField: (field: string) => void\n onAddValueField: (field: string, aggregation: AggregationFunction) => void\n onRemoveValueField: (field: string, aggregation: AggregationFunction) => void\n onAddCalculatedField?: (field: CalculatedField) => void\n onRemoveCalculatedField?: (id: string) => void\n onUpdateCalculatedField?: (field: CalculatedField) => void\n}\n\nfunction getFieldIcon(type: FieldStats['type'], isCalculated?: boolean): string {\n if (isCalculated)\n return 'ƒ'\n switch (type) {\n case 'number':\n return '#'\n case 'date':\n return '📅'\n case 'boolean':\n return '✓'\n default:\n return 'Aa'\n }\n}\n\nexport function PivotConfig({\n availableFields,\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n calculatedFields,\n onShowRowTotalsChange,\n onShowColumnTotalsChange,\n onClearConfig,\n onAutoSuggest: _onAutoSuggest,\n onDragStart,\n onDragEnd,\n onUpdateAggregation,\n onRemoveRowField,\n onRemoveColumnField,\n onRemoveValueField,\n onAddRowField,\n onAddColumnField,\n onAddCalculatedField,\n onRemoveCalculatedField,\n onUpdateCalculatedField,\n}: PivotConfigProps) {\n const [fieldSearch, setFieldSearch] = useState('')\n const [showCalcModal, setShowCalcModal] = useState(false)\n const [editingCalcField, setEditingCalcField] = useState<CalculatedField | null>(null)\n const { canUseAdvancedAggregations } = useLicense()\n\n // Check if an aggregation is available based on license\n const isAggregationAvailable = useCallback((agg: AggregationFunction): boolean => {\n return !aggregationRequiresPro(agg) || canUseAdvancedAggregations\n }, [canUseAdvancedAggregations])\n\n // Get only numeric field names for calculated field formulas\n const numericFieldNames = useMemo(() =>\n availableFields\n .filter(f => f.isNumeric)\n .map(f => f.field), [availableFields])\n\n // Convert calculated fields to virtual FieldStats for display\n const calculatedFieldsAsStats = useMemo((): ExtendedFieldStats[] => {\n if (!calculatedFields)\n return []\n return calculatedFields.map(calc => ({\n field: `calc:${calc.id}`,\n type: 'number' as const,\n uniqueCount: 0,\n isNumeric: true,\n isCalculated: true,\n calcId: calc.id,\n calcName: calc.name,\n calcFormula: calc.formula,\n }))\n }, [calculatedFields])\n\n // Combined available fields (data fields + calculated fields)\n const allAvailableFields = useMemo((): ExtendedFieldStats[] => [\n ...availableFields.map(f => ({ ...f, isCalculated: false })),\n ...calculatedFieldsAsStats,\n ], [availableFields, calculatedFieldsAsStats])\n\n // Assigned fields\n const assignedFields = useMemo(() => {\n const rowSet = new Set(rowFields)\n const colSet = new Set(columnFields)\n const valueMap = new Map(valueFields.map(v => [v.field, v]))\n\n return allAvailableFields\n .filter(f => rowSet.has(f.field) || colSet.has(f.field) || valueMap.has(f.field))\n .map(f => ({\n ...f,\n assignedTo: rowSet.has(f.field)\n ? ('row' as const)\n : colSet.has(f.field)\n ? ('column' as const)\n : ('value' as const),\n valueConfig: valueMap.get(f.field),\n }))\n }, [allAvailableFields, rowFields, columnFields, valueFields])\n\n // Unassigned fields (including unassigned calculated fields)\n const unassignedFields = useMemo(() => {\n const rowSet = new Set(rowFields)\n const colSet = new Set(columnFields)\n const valSet = new Set(valueFields.map(v => v.field))\n\n return allAvailableFields.filter(\n f => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field),\n )\n }, [allAvailableFields, rowFields, columnFields, valueFields])\n\n const filteredUnassignedFields = useMemo(() => {\n if (!fieldSearch.trim())\n return unassignedFields\n const search = fieldSearch.toLowerCase().trim()\n return unassignedFields.filter((f) => {\n const fieldName = f.field.toLowerCase()\n const displayName = f.isCalculated && f.calcName ? f.calcName.toLowerCase() : ''\n return fieldName.includes(search) || displayName.includes(search)\n })\n }, [unassignedFields, fieldSearch])\n\n const assignedCount = assignedFields.length\n\n // Get display name for field (handles calculated fields)\n const getFieldDisplayName = useCallback((field: ExtendedFieldStats): string => {\n if (field.isCalculated && field.calcName) {\n return field.calcName\n }\n return field.field\n }, [])\n\n const handleDragStart = useCallback(\n (field: string, event: React.DragEvent) => {\n event.dataTransfer?.setData('text/plain', field)\n event.dataTransfer!.effectAllowed = 'move'\n onDragStart(field, event)\n },\n [onDragStart],\n )\n\n const handleAggregationChange = useCallback(\n (field: string, currentAgg: AggregationFunction, newAgg: AggregationFunction) => {\n // Prevent changing to Pro aggregations without license\n if (!isAggregationAvailable(newAgg)) {\n console.warn(`[TinyPivot] \"${newAgg}\" aggregation requires a Pro license. Visit https://tiny-pivot.com/#pricing to upgrade.`)\n return\n }\n onUpdateAggregation(field, currentAgg, newAgg)\n },\n [onUpdateAggregation, isAggregationAvailable],\n )\n\n const toggleRowColumn = useCallback(\n (field: string, currentAssignment: 'row' | 'column') => {\n if (currentAssignment === 'row') {\n onRemoveRowField(field)\n onAddColumnField(field)\n }\n else {\n onRemoveColumnField(field)\n onAddRowField(field)\n }\n },\n [onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField],\n )\n\n const removeField = useCallback(\n (field: string, assignedTo: 'row' | 'column' | 'value', valueConfig?: PivotValueField) => {\n if (assignedTo === 'row') {\n onRemoveRowField(field)\n }\n else if (assignedTo === 'column') {\n onRemoveColumnField(field)\n }\n else if (valueConfig) {\n onRemoveValueField(field, valueConfig.aggregation)\n }\n },\n [onRemoveRowField, onRemoveColumnField, onRemoveValueField],\n )\n\n // Handle totals toggle (toggle both row and column together)\n const handleTotalsToggle = useCallback((checked: boolean) => {\n onShowRowTotalsChange(checked)\n onShowColumnTotalsChange(checked)\n }, [onShowRowTotalsChange, onShowColumnTotalsChange])\n\n // Calculated field modal handlers\n const openCalcModal = useCallback((field?: CalculatedField) => {\n setEditingCalcField(field || null)\n setShowCalcModal(true)\n }, [])\n\n const handleSaveCalcField = useCallback((field: CalculatedField) => {\n if (editingCalcField && onUpdateCalculatedField) {\n onUpdateCalculatedField(field)\n }\n else if (onAddCalculatedField) {\n onAddCalculatedField(field)\n }\n setShowCalcModal(false)\n setEditingCalcField(null)\n }, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField])\n\n const handleCloseCalcModal = useCallback(() => {\n setShowCalcModal(false)\n setEditingCalcField(null)\n }, [])\n\n return (\n <div className=\"vpg-pivot-config\">\n {/* Header */}\n <div className=\"vpg-config-header\">\n <h3 className=\"vpg-config-title\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 10h16M4 14h16M4 18h16\"\n />\n </svg>\n Fields\n </h3>\n <div className=\"vpg-header-actions\">\n {assignedCount > 0 && (\n <button\n className=\"vpg-action-btn vpg-clear-btn\"\n title=\"Clear all\"\n onClick={onClearConfig}\n >\n <svg className=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n\n {/* Assigned Fields */}\n {assignedCount > 0 && (\n <div className=\"vpg-assigned-section\">\n <div className=\"vpg-section-label\">Active</div>\n <div className=\"vpg-assigned-list\">\n {assignedFields.map(field => (\n <div\n key={field.field}\n className={`vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? ' vpg-type-calc' : ''}`}\n title={field.isCalculated ? field.calcFormula : field.field}\n draggable\n onDragStart={e => handleDragStart(field.field, e)}\n onDragEnd={onDragEnd}\n >\n <div className=\"vpg-item-main\">\n <span className={`vpg-item-badge ${field.assignedTo}${field.isCalculated ? ' calc' : ''}`}>\n {field.isCalculated\n ? 'ƒ'\n : field.assignedTo === 'row'\n ? 'R'\n : field.assignedTo === 'column'\n ? 'C'\n : getAggregationSymbol(field.valueConfig?.aggregation || 'sum')}\n </span>\n <span className=\"vpg-item-name\">{getFieldDisplayName(field)}</span>\n </div>\n\n <div className=\"vpg-item-actions\">\n {(field.assignedTo === 'row' || field.assignedTo === 'column') && (\n <button\n className=\"vpg-toggle-btn\"\n title={field.assignedTo === 'row' ? 'Move to Columns' : 'Move to Rows'}\n onClick={(e) => {\n e.stopPropagation()\n toggleRowColumn(field.field, field.assignedTo as 'row' | 'column')\n }}\n >\n <svg\n className=\"vpg-icon-xs\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4\"\n />\n </svg>\n </button>\n )}\n\n {field.assignedTo === 'value' && field.valueConfig && (\n <select\n className=\"vpg-agg-select\"\n value={field.valueConfig.aggregation}\n onChange={(e) => {\n e.stopPropagation()\n handleAggregationChange(\n field.field,\n field.valueConfig!.aggregation,\n e.target.value as AggregationFunction,\n )\n }}\n onClick={e => e.stopPropagation()}\n >\n {AGGREGATION_OPTIONS.map(agg => (\n <option\n key={agg.value}\n value={agg.value}\n disabled={aggregationRequiresPro(agg.value) && !canUseAdvancedAggregations}\n >\n {agg.symbol}\n {' '}\n {agg.label}\n {aggregationRequiresPro(agg.value) && !canUseAdvancedAggregations ? ' (Pro)' : ''}\n </option>\n ))}\n </select>\n )}\n\n <button\n className=\"vpg-remove-btn\"\n title=\"Remove\"\n onClick={(e) => {\n e.stopPropagation()\n removeField(field.field, field.assignedTo, field.valueConfig)\n }}\n >\n ×\n </button>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Unassigned Fields */}\n <div className=\"vpg-unassigned-section\">\n <div className=\"vpg-section-header\">\n <div className=\"vpg-section-label\">\n Available\n {' '}\n <span className=\"vpg-count\">{unassignedFields.length}</span>\n </div>\n </div>\n\n {/* Field Search */}\n <div className=\"vpg-field-search\">\n <svg className=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <input\n type=\"text\"\n value={fieldSearch}\n onChange={e => setFieldSearch(e.target.value)}\n placeholder=\"Search fields...\"\n className=\"vpg-search-input\"\n />\n {fieldSearch && (\n <button className=\"vpg-clear-search\" onClick={() => setFieldSearch('')}>\n <svg className=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n\n <div className=\"vpg-field-list\">\n {filteredUnassignedFields.map(field => (\n <div\n key={field.field}\n className={`vpg-field-item${field.isNumeric && !field.isCalculated ? ' vpg-is-numeric' : ''}${field.isCalculated ? ' vpg-is-calculated' : ''}`}\n title={field.isCalculated ? field.calcFormula : field.field}\n draggable\n onDragStart={e => handleDragStart(field.field, e)}\n onDragEnd={onDragEnd}\n >\n <span className={`vpg-field-type-icon${field.isCalculated ? ' vpg-calc-type' : ''}`} title={field.type}>\n {getFieldIcon(field.type, field.isCalculated)}\n </span>\n <span className=\"vpg-field-name\">{getFieldDisplayName(field)}</span>\n {field.isCalculated\n ? (\n <>\n <button\n className=\"vpg-field-edit\"\n title=\"Edit calculated field\"\n onClick={(e) => {\n e.stopPropagation()\n const calcField = calculatedFields?.find(c => c.id === field.calcId)\n if (calcField)\n openCalcModal(calcField)\n }}\n >\n ✎\n </button>\n <button\n className=\"vpg-field-delete\"\n title=\"Delete calculated field\"\n onClick={(e) => {\n e.stopPropagation()\n if (field.calcId && onRemoveCalculatedField) {\n onRemoveCalculatedField(field.calcId)\n }\n }}\n >\n ×\n </button>\n </>\n )\n : (\n <span className=\"vpg-unique-count\">{field.uniqueCount}</span>\n )}\n </div>\n ))}\n {filteredUnassignedFields.length === 0 && fieldSearch && (\n <div className=\"vpg-empty-hint\">\n No fields match \"\n {fieldSearch}\n \"\n </div>\n )}\n {unassignedFields.length === 0 && <div className=\"vpg-empty-hint\">All fields assigned</div>}\n </div>\n </div>\n\n {/* Options */}\n <div className=\"vpg-options-section\">\n <label className=\"vpg-option-toggle\">\n <input\n type=\"checkbox\"\n checked={showRowTotals}\n onChange={e => handleTotalsToggle(e.target.checked)}\n />\n <span>Totals</span>\n </label>\n <button className=\"vpg-calc-btn\" onClick={() => openCalcModal()} title=\"Add calculated field (e.g. Profit Margin %)\">\n <span className=\"vpg-calc-icon\">ƒ</span>\n <span>+ Calc</span>\n </button>\n </div>\n\n {/* Calculated Field Modal */}\n <CalculatedFieldModal\n show={showCalcModal}\n availableFields={numericFieldNames}\n existingField={editingCalcField}\n onClose={handleCloseCalcModal}\n onSave={handleSaveCalcField}\n />\n </div>\n )\n}\n","import type { AggregationFunction, CalculatedField, PivotResult, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { getAggregationLabel, getAggregationSymbol } from '@smallwebco/tinypivot-core'\n/**\n * Pivot Table Skeleton + Data Display for React\n * Visual layout for pivot configuration and results\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useLicense } from '../hooks/useLicense'\n\ninterface ActiveFilter {\n column: string\n valueCount: number\n values?: string[]\n displayText?: string\n isRange?: boolean\n}\n\ninterface PivotSkeletonProps {\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n calculatedFields?: CalculatedField[]\n isConfigured: boolean\n draggingField: string | null\n pivotResult: PivotResult | null\n fontSize?: 'xs' | 'sm' | 'base'\n activeFilters?: ActiveFilter[] | null\n totalRowCount?: number\n filteredRowCount?: number\n onAddRowField: (field: string) => void\n onRemoveRowField: (field: string) => void\n onAddColumnField: (field: string) => void\n onRemoveColumnField: (field: string) => void\n onAddValueField: (field: string, aggregation: AggregationFunction) => void\n onRemoveValueField: (field: string, aggregation: AggregationFunction) => void\n onUpdateAggregation: (field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction) => void\n onReorderRowFields: (fields: string[]) => void\n onReorderColumnFields: (fields: string[]) => void\n}\n\nexport function PivotSkeleton({\n rowFields,\n columnFields,\n valueFields,\n calculatedFields,\n isConfigured,\n draggingField,\n pivotResult,\n fontSize = 'xs',\n activeFilters,\n totalRowCount,\n filteredRowCount,\n onAddRowField,\n onRemoveRowField,\n onAddColumnField,\n onRemoveColumnField,\n onAddValueField,\n onRemoveValueField,\n onReorderRowFields,\n onReorderColumnFields,\n}: PivotSkeletonProps) {\n const { showWatermark, canUsePivot, isDemo } = useLicense()\n\n // Helper to get display name for value fields (resolves calc IDs to names)\n const getValueFieldDisplayName = useCallback((field: string): string => {\n if (field.startsWith('calc:')) {\n const calcId = field.replace('calc:', '')\n const calcField = calculatedFields?.find(c => c.id === calcId)\n return calcField?.name || field\n }\n return field\n }, [calculatedFields])\n\n // Helper to check if field is a calculated field\n const isCalculatedField = useCallback((field: string): boolean => {\n return field.startsWith('calc:')\n }, [])\n\n // Drag state\n const [dragOverArea, setDragOverArea] = useState<'row' | 'column' | 'value' | null>(null)\n\n // Reorder drag state\n const [reorderDragSource, setReorderDragSource] = useState<{ zone: 'row' | 'column', index: number } | null>(null)\n const [reorderDropTarget, setReorderDropTarget] = useState<{ zone: 'row' | 'column', index: number } | null>(null)\n\n // Sorting\n type SortTarget = 'row' | number\n const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc')\n const [sortTarget, setSortTarget] = useState<SortTarget>('row')\n\n const toggleSort = useCallback((target: SortTarget = 'row') => {\n if (sortTarget === target) {\n setSortDirection(prev => (prev === 'asc' ? 'desc' : 'asc'))\n }\n else {\n setSortTarget(target)\n setSortDirection('asc')\n }\n }, [sortTarget])\n\n // Selection state for cell selection and copy\n const [selectedCell, setSelectedCell] = useState<{ row: number, col: number } | null>(null)\n const [selectionStart, setSelectionStart] = useState<{ row: number, col: number } | null>(null)\n const [selectionEnd, setSelectionEnd] = useState<{ row: number, col: number } | null>(null)\n const [isSelecting, setIsSelecting] = useState(false)\n const [showCopyToast, setShowCopyToast] = useState(false)\n const [copyToastMessage, setCopyToastMessage] = useState('')\n\n const selectionBounds = useMemo(() => {\n if (!selectionStart || !selectionEnd)\n return null\n return {\n minRow: Math.min(selectionStart.row, selectionEnd.row),\n maxRow: Math.max(selectionStart.row, selectionEnd.row),\n minCol: Math.min(selectionStart.col, selectionEnd.col),\n maxCol: Math.max(selectionStart.col, selectionEnd.col),\n }\n }, [selectionStart, selectionEnd])\n\n const handleCellMouseDown = useCallback(\n (rowIndex: number, colIndex: number, event: React.MouseEvent) => {\n event.preventDefault()\n\n if (event.shiftKey && selectedCell) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n else {\n setSelectedCell({ row: rowIndex, col: colIndex })\n setSelectionStart({ row: rowIndex, col: colIndex })\n setSelectionEnd({ row: rowIndex, col: colIndex })\n setIsSelecting(true)\n }\n },\n [selectedCell],\n )\n\n const handleCellMouseEnter = useCallback(\n (rowIndex: number, colIndex: number) => {\n if (isSelecting) {\n setSelectionEnd({ row: rowIndex, col: colIndex })\n }\n },\n [isSelecting],\n )\n\n const isCellSelected = useCallback(\n (rowIndex: number, colIndex: number): boolean => {\n if (!selectionBounds) {\n return selectedCell?.row === rowIndex && selectedCell?.col === colIndex\n }\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol\n },\n [selectionBounds, selectedCell],\n )\n\n // Mouse up handler\n useEffect(() => {\n const handleMouseUp = () => setIsSelecting(false)\n document.addEventListener('mouseup', handleMouseUp)\n return () => document.removeEventListener('mouseup', handleMouseUp)\n }, [])\n\n // Sorted row indices\n const sortedRowIndices = useMemo(() => {\n if (!pivotResult)\n return []\n\n const indices = pivotResult.rowHeaders.map((_, i) => i)\n const headers = pivotResult.rowHeaders\n const data = pivotResult.data\n\n indices.sort((a, b) => {\n let cmp: number\n\n if (sortTarget === 'row') {\n const aHeader = headers[a]?.join(' / ') || ''\n const bHeader = headers[b]?.join(' / ') || ''\n cmp = aHeader.localeCompare(bHeader, undefined, { numeric: true, sensitivity: 'base' })\n }\n else {\n const colIdx = sortTarget as number\n const aVal = data[a]?.[colIdx]?.value ?? null\n const bVal = data[b]?.[colIdx]?.value ?? null\n\n if (aVal === null && bVal === null)\n cmp = 0\n else if (aVal === null)\n cmp = 1\n else if (bVal === null)\n cmp = -1\n else cmp = aVal - bVal\n }\n\n return sortDirection === 'asc' ? cmp : -cmp\n })\n\n return indices\n }, [pivotResult, sortTarget, sortDirection])\n\n // Copy selection to clipboard\n const copySelectionToClipboard = useCallback(() => {\n if (!selectionBounds || !pivotResult)\n return\n\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n const lines: string[] = []\n\n for (let r = minRow; r <= maxRow; r++) {\n const sortedIdx = sortedRowIndices[r]\n if (sortedIdx === undefined)\n continue\n\n const rowValues: string[] = []\n for (let c = minCol; c <= maxCol; c++) {\n const cell = pivotResult.data[sortedIdx]?.[c]\n rowValues.push(cell?.formattedValue ?? '')\n }\n lines.push(rowValues.join('\\t'))\n }\n\n const text = lines.join('\\n')\n\n navigator.clipboard.writeText(text).then(() => {\n const cellCount = (maxRow - minRow + 1) * (maxCol - minCol + 1)\n setCopyToastMessage(`Copied ${cellCount} cell${cellCount > 1 ? 's' : ''}`)\n setShowCopyToast(true)\n setTimeout(() => setShowCopyToast(false), 2000)\n }).catch((err) => {\n console.error('Copy failed:', err)\n })\n }, [selectionBounds, pivotResult, sortedRowIndices])\n\n // Keyboard handler for copy\n useEffect(() => {\n const handleKeydown = (event: KeyboardEvent) => {\n if (!selectionBounds)\n return\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'c') {\n event.preventDefault()\n copySelectionToClipboard()\n return\n }\n\n if (event.key === 'Escape') {\n setSelectedCell(null)\n setSelectionStart(null)\n setSelectionEnd(null)\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n return () => document.removeEventListener('keydown', handleKeydown)\n }, [selectionBounds, copySelectionToClipboard])\n\n // Selection statistics for footer\n const selectionStats = useMemo(() => {\n if (!selectionBounds || !pivotResult)\n return null\n\n const { minRow, maxRow, minCol, maxCol } = selectionBounds\n const values: number[] = []\n let count = 0\n\n for (let r = minRow; r <= maxRow; r++) {\n const sortedIdx = sortedRowIndices[r]\n if (sortedIdx === undefined)\n continue\n\n for (let c = minCol; c <= maxCol; c++) {\n const cell = pivotResult.data[sortedIdx]?.[c]\n count++\n if (cell?.value !== null && cell?.value !== undefined && typeof cell.value === 'number') {\n values.push(cell.value)\n }\n }\n }\n\n if (count <= 1)\n return null\n\n const sum = values.reduce((a, b) => a + b, 0)\n const avg = values.length > 0 ? sum / values.length : 0\n\n return {\n count,\n numericCount: values.length,\n sum,\n avg,\n }\n }, [selectionBounds, pivotResult, sortedRowIndices])\n\n const formatStatValue = useCallback((val: number): string => {\n if (Math.abs(val) >= 1_000_000)\n return `${(val / 1_000_000).toFixed(2)}M`\n if (Math.abs(val) >= 1_000)\n return `${(val / 1_000).toFixed(2)}K`\n return val.toFixed(2)\n }, [])\n\n // Column headers\n const columnHeaderCells = useMemo(() => {\n if (!pivotResult || pivotResult.headers.length === 0) {\n return [\n valueFields.map(vf => ({\n label: `${getValueFieldDisplayName(vf.field)} (${getAggregationLabel(vf.aggregation)})`,\n colspan: 1,\n })),\n ]\n }\n\n const result: Array<Array<{ label: string, colspan: number }>> = []\n\n for (let level = 0; level < pivotResult.headers.length; level++) {\n const headerRow = pivotResult.headers[level]\n const cells: Array<{ label: string, colspan: number }> = []\n\n let i = 0\n while (i < headerRow.length) {\n const value = headerRow[i]\n let colspan = 1\n\n while (i + colspan < headerRow.length && headerRow[i + colspan] === value) {\n colspan++\n }\n\n cells.push({ label: value, colspan })\n i += colspan\n }\n\n result.push(cells)\n }\n\n return result\n }, [pivotResult, valueFields])\n\n // Filter status\n const hasActiveFilters = activeFilters && activeFilters.length > 0\n const filterSummary = useMemo(() => {\n if (!activeFilters || activeFilters.length === 0)\n return ''\n return activeFilters.map(f => f.column).join(', ')\n }, [activeFilters])\n\n // Detailed filter tooltip\n const [showFilterTooltip, setShowFilterTooltip] = useState(false)\n const filterTooltipDetails = useMemo(() => {\n if (!activeFilters || activeFilters.length === 0)\n return []\n return activeFilters.map((f) => {\n // Handle range filters\n if (f.isRange && f.displayText) {\n return {\n column: f.column,\n displayText: f.displayText,\n isRange: true,\n values: [] as string[],\n remaining: 0,\n }\n }\n // Handle value filters\n const values = f.values || []\n const maxDisplay = 5\n const displayValues = values.slice(0, maxDisplay)\n const remaining = values.length - maxDisplay\n return {\n column: f.column,\n values: displayValues,\n remaining: remaining > 0 ? remaining : 0,\n isRange: false,\n }\n })\n }, [activeFilters])\n\n // Drag handlers\n const handleDragOver = useCallback(\n (area: 'row' | 'column' | 'value', event: React.DragEvent) => {\n event.preventDefault()\n event.dataTransfer!.dropEffect = 'move'\n setDragOverArea(area)\n },\n [],\n )\n\n const handleDragLeave = useCallback(() => {\n setDragOverArea(null)\n }, [])\n\n const handleDrop = useCallback(\n (area: 'row' | 'column' | 'value', event: React.DragEvent) => {\n event.preventDefault()\n const field = event.dataTransfer?.getData('text/plain')\n\n if (!field || field.startsWith('reorder:')) {\n setDragOverArea(null)\n return\n }\n\n if (rowFields.includes(field))\n onRemoveRowField(field)\n if (columnFields.includes(field))\n onRemoveColumnField(field)\n const existingValue = valueFields.find(v => v.field === field)\n if (existingValue)\n onRemoveValueField(field, existingValue.aggregation)\n\n switch (area) {\n case 'row':\n onAddRowField(field)\n break\n case 'column':\n onAddColumnField(field)\n break\n case 'value':\n onAddValueField(field, 'sum')\n break\n }\n setDragOverArea(null)\n },\n [rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField],\n )\n\n // Reorder handlers for chips within zones\n const handleChipDragStart = useCallback(\n (zone: 'row' | 'column', index: number, event: React.DragEvent) => {\n setReorderDragSource({ zone, index })\n event.dataTransfer!.effectAllowed = 'move'\n event.dataTransfer!.setData('text/plain', `reorder:${zone}:${index}`)\n // Clear any zone drag-over state\n requestAnimationFrame(() => {\n setDragOverArea(null)\n })\n },\n [],\n )\n\n const handleChipDragEnd = useCallback(() => {\n setReorderDragSource(null)\n setReorderDropTarget(null)\n }, [])\n\n const handleChipDragOver = useCallback(\n (zone: 'row' | 'column', index: number, event: React.DragEvent) => {\n event.preventDefault()\n // Only handle reorder within same zone\n if (reorderDragSource && reorderDragSource.zone === zone) {\n event.dataTransfer!.dropEffect = 'move'\n setReorderDropTarget({ zone, index })\n }\n },\n [reorderDragSource],\n )\n\n const handleChipDragLeave = useCallback(() => {\n setReorderDropTarget(null)\n }, [])\n\n const handleChipDrop = useCallback(\n (zone: 'row' | 'column', targetIndex: number, event: React.DragEvent) => {\n event.preventDefault()\n event.stopPropagation()\n\n if (!reorderDragSource || reorderDragSource.zone !== zone) {\n return\n }\n\n const sourceIndex = reorderDragSource.index\n if (sourceIndex === targetIndex) {\n setReorderDragSource(null)\n setReorderDropTarget(null)\n return\n }\n\n // Create reordered array\n const fields = zone === 'row' ? [...rowFields] : [...columnFields]\n const [movedField] = fields.splice(sourceIndex, 1)\n fields.splice(targetIndex, 0, movedField)\n\n // Emit reorder event\n if (zone === 'row') {\n onReorderRowFields(fields)\n }\n else {\n onReorderColumnFields(fields)\n }\n\n setReorderDragSource(null)\n setReorderDropTarget(null)\n },\n [reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields],\n )\n\n const isChipDragSource = useCallback(\n (zone: 'row' | 'column', index: number): boolean => {\n return reorderDragSource?.zone === zone && reorderDragSource?.index === index\n },\n [reorderDragSource],\n )\n\n const isChipDropTarget = useCallback(\n (zone: 'row' | 'column', index: number): boolean => {\n return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index\n },\n [reorderDropTarget],\n )\n\n const currentFontSize = fontSize\n\n // Calculate width per row header column\n const rowHeaderWidth = 180\n const rowHeaderColWidth = useMemo(() => {\n const numCols = Math.max(rowFields.length, 1)\n return Math.max(rowHeaderWidth / numCols, 80)\n }, [rowFields.length])\n\n // Calculate left offset for each row header column (for sticky positioning)\n const getRowHeaderLeftOffset = useCallback((fieldIdx: number): number => {\n return fieldIdx * rowHeaderColWidth\n }, [rowHeaderColWidth])\n\n return (\n <div\n className={`vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? 'vpg-is-dragging' : ''}`}\n >\n {/* Copy Toast */}\n {showCopyToast && (\n <div className=\"vpg-toast\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n {copyToastMessage}\n </div>\n )}\n\n {/* Header Bar */}\n <div className=\"vpg-skeleton-header\">\n <div className=\"vpg-skeleton-title\">\n <svg className=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n <span>Pivot Table</span>\n </div>\n\n <div className=\"vpg-header-right\">\n {hasActiveFilters && (\n <div\n className=\"vpg-filter-indicator\"\n onMouseEnter={() => setShowFilterTooltip(true)}\n onMouseLeave={() => setShowFilterTooltip(false)}\n >\n <svg\n className=\"vpg-filter-icon\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n <span className=\"vpg-filter-text\">\n Filtered:\n {' '}\n <strong>{filterSummary}</strong>\n {filteredRowCount !== undefined && totalRowCount !== undefined && (\n <span className=\"vpg-filter-count\">\n (\n {filteredRowCount.toLocaleString()}\n {' '}\n of\n {' '}\n {totalRowCount.toLocaleString()}\n {' '}\n rows)\n </span>\n )}\n </span>\n\n {/* Tooltip */}\n {showFilterTooltip && (\n <div className=\"vpg-filter-tooltip\">\n <div className=\"vpg-tooltip-header\">Active Filters</div>\n {filterTooltipDetails.map(filter => (\n <div key={filter.column} className=\"vpg-tooltip-filter\">\n <div className=\"vpg-tooltip-column\">{filter.column}</div>\n <div className=\"vpg-tooltip-values\">\n {filter.isRange\n ? (\n <span className=\"vpg-tooltip-value vpg-range-value\">{filter.displayText}</span>\n )\n : (\n <>\n {filter.values.map((val, idx) => (\n <span key={idx} className=\"vpg-tooltip-value\">\n {val}\n </span>\n ))}\n {filter.remaining > 0 && (\n <span className=\"vpg-tooltip-more\">\n +\n {filter.remaining}\n {' '}\n more\n </span>\n )}\n </>\n )}\n </div>\n </div>\n ))}\n {filteredRowCount !== undefined && totalRowCount !== undefined && (\n <div className=\"vpg-tooltip-summary\">\n Showing\n {' '}\n {filteredRowCount.toLocaleString()}\n {' '}\n of\n {' '}\n {totalRowCount.toLocaleString()}\n {' '}\n rows\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {isConfigured && (\n <div className=\"vpg-config-summary\">\n <span className=\"vpg-summary-badge vpg-rows\">\n {rowFields.length}\n {' '}\n row\n {rowFields.length !== 1 ? 's' : ''}\n </span>\n <span className=\"vpg-summary-badge vpg-cols\">\n {columnFields.length}\n {' '}\n col\n {columnFields.length !== 1 ? 's' : ''}\n </span>\n <span className=\"vpg-summary-badge vpg-vals\">\n {valueFields.length}\n {' '}\n val\n {valueFields.length !== 1 ? 's' : ''}\n </span>\n </div>\n )}\n </div>\n </div>\n\n {/* License Required Message */}\n {!canUsePivot ? (\n <div className=\"vpg-pro-required\">\n <div className=\"vpg-pro-content\">\n <svg className=\"vpg-pro-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <h3>Pro Feature</h3>\n <p>Pivot Table functionality requires a Pro license.</p>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener noreferrer\" className=\"vpg-pro-link\">\n Get Pro License →\n </a>\n </div>\n </div>\n ) : (\n <>\n {/* Config Bar */}\n <div className=\"vpg-config-bar\">\n {/* Row drop zone */}\n <div\n className={`vpg-drop-zone vpg-row-zone ${dragOverArea === 'row' ? 'vpg-drag-over' : ''}`}\n onDragOver={e => handleDragOver('row', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('row', e)}\n >\n <div className=\"vpg-zone-header\">\n <span className=\"vpg-zone-icon vpg-row-icon\">↓</span>\n <span className=\"vpg-zone-label\">Rows</span>\n </div>\n <div className=\"vpg-zone-chips\">\n {rowFields.map((field, idx) => (\n <div\n key={field}\n className={`vpg-mini-chip vpg-row-chip ${isChipDragSource('row', idx) ? 'vpg-chip-dragging' : ''} ${isChipDropTarget('row', idx) ? 'vpg-chip-drop-target' : ''}`}\n draggable\n onDragStart={e => handleChipDragStart('row', idx, e)}\n onDragEnd={handleChipDragEnd}\n onDragOver={e => handleChipDragOver('row', idx, e)}\n onDragLeave={handleChipDragLeave}\n onDrop={e => handleChipDrop('row', idx, e)}\n >\n <span className=\"vpg-drag-handle\">⋮⋮</span>\n <span className=\"vpg-mini-name\">{field}</span>\n <button\n className=\"vpg-mini-remove\"\n onClick={(e) => { e.stopPropagation(); onRemoveRowField(field) }}\n >\n ×\n </button>\n </div>\n ))}\n {rowFields.length === 0 && <span className=\"vpg-zone-hint\">Drop here</span>}\n </div>\n </div>\n\n {/* Column drop zone */}\n <div\n className={`vpg-drop-zone vpg-column-zone ${dragOverArea === 'column' ? 'vpg-drag-over' : ''}`}\n onDragOver={e => handleDragOver('column', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('column', e)}\n >\n <div className=\"vpg-zone-header\">\n <span className=\"vpg-zone-icon vpg-column-icon\">→</span>\n <span className=\"vpg-zone-label\">Columns</span>\n </div>\n <div className=\"vpg-zone-chips\">\n {columnFields.map((field, idx) => (\n <div\n key={field}\n className={`vpg-mini-chip vpg-column-chip ${isChipDragSource('column', idx) ? 'vpg-chip-dragging' : ''} ${isChipDropTarget('column', idx) ? 'vpg-chip-drop-target' : ''}`}\n draggable\n onDragStart={e => handleChipDragStart('column', idx, e)}\n onDragEnd={handleChipDragEnd}\n onDragOver={e => handleChipDragOver('column', idx, e)}\n onDragLeave={handleChipDragLeave}\n onDrop={e => handleChipDrop('column', idx, e)}\n >\n <span className=\"vpg-drag-handle\">⋮⋮</span>\n <span className=\"vpg-mini-name\">{field}</span>\n <button\n className=\"vpg-mini-remove\"\n onClick={(e) => { e.stopPropagation(); onRemoveColumnField(field) }}\n >\n ×\n </button>\n </div>\n ))}\n {columnFields.length === 0 && <span className=\"vpg-zone-hint\">Drop here</span>}\n </div>\n </div>\n\n {/* Values drop zone */}\n <div\n className={`vpg-drop-zone vpg-value-zone ${dragOverArea === 'value' ? 'vpg-drag-over' : ''}`}\n onDragOver={e => handleDragOver('value', e)}\n onDragLeave={handleDragLeave}\n onDrop={e => handleDrop('value', e)}\n >\n <div className=\"vpg-zone-header\">\n <span className=\"vpg-zone-icon vpg-value-icon\">Σ</span>\n <span className=\"vpg-zone-label\">Values</span>\n </div>\n <div className=\"vpg-zone-chips\">\n {valueFields.map(vf => (\n <div\n key={`${vf.field}-${vf.aggregation}`}\n className={`vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? ' vpg-calc-chip' : ''}`}\n >\n <span className=\"vpg-agg-symbol\">{isCalculatedField(vf.field) ? 'ƒ' : getAggregationSymbol(vf.aggregation)}</span>\n <span className=\"vpg-mini-name\">{getValueFieldDisplayName(vf.field)}</span>\n <button\n className=\"vpg-mini-remove\"\n onClick={() => onRemoveValueField(vf.field, vf.aggregation)}\n >\n ×\n </button>\n </div>\n ))}\n {valueFields.length === 0 && <span className=\"vpg-zone-hint\">Drop numeric</span>}\n </div>\n </div>\n </div>\n\n {/* Placeholder when not configured */}\n {(!isConfigured || !pivotResult) && (\n <div className=\"vpg-placeholder\">\n <div className=\"vpg-placeholder-content\">\n <svg\n className=\"vpg-placeholder-icon\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n <span className=\"vpg-placeholder-text\">\n {valueFields.length === 0\n ? (\n <>\n Add a\n {' '}\n <strong>Values</strong>\n {' '}\n field to see your pivot table\n </>\n )\n : rowFields.length === 0 && columnFields.length === 0\n ? (\n <>\n Add\n {' '}\n <strong>Row</strong>\n {' '}\n or\n {' '}\n <strong>Column</strong>\n {' '}\n fields to group your data\n </>\n )\n : (\n 'Your pivot table will appear here'\n )}\n </span>\n </div>\n </div>\n )}\n\n {/* Data Table */}\n {isConfigured && pivotResult && (\n <div className=\"vpg-table-container\">\n <table className=\"vpg-pivot-table\">\n <thead>\n {columnHeaderCells.map((headerRow, levelIdx) => (\n <tr key={`header-${levelIdx}`} className=\"vpg-column-header-row\">\n {levelIdx === 0 && (rowFields.length > 0 ? rowFields : ['Rows']).map((field, fieldIdx) => (\n <th\n key={`row-header-${fieldIdx}`}\n className=\"vpg-row-header-label\"\n rowSpan={columnHeaderCells.length}\n style={{ width: `${rowHeaderColWidth}px`, minWidth: '80px', left: `${getRowHeaderLeftOffset(fieldIdx)}px` }}\n onClick={() => toggleSort('row')}\n >\n <div className=\"vpg-header-content\">\n <span>{field}</span>\n {(fieldIdx === rowFields.length - 1 || rowFields.length === 0) && (\n <span className={`vpg-sort-indicator ${sortTarget === 'row' ? 'active' : ''}`}>\n {sortTarget === 'row' ? (sortDirection === 'asc' ? '↑' : '↓') : '⇅'}\n </span>\n )}\n </div>\n </th>\n ))}\n {headerRow.map((cell, idx) => (\n <th\n key={idx}\n className=\"vpg-column-header-cell\"\n colSpan={cell.colspan}\n onClick={() =>\n levelIdx === columnHeaderCells.length - 1 && toggleSort(idx)}\n >\n <div className=\"vpg-header-content\">\n <span>{cell.label}</span>\n {levelIdx === columnHeaderCells.length - 1 && (\n <span className={`vpg-sort-indicator ${sortTarget === idx ? 'active' : ''}`}>\n {sortTarget === idx\n ? sortDirection === 'asc'\n ? '↑'\n : '↓'\n : '⇅'}\n </span>\n )}\n </div>\n </th>\n ))}\n {pivotResult.rowTotals.length > 0 && levelIdx === 0 && (\n <th className=\"vpg-total-header\" rowSpan={columnHeaderCells.length}>\n Total\n </th>\n )}\n </tr>\n ))}\n </thead>\n\n <tbody>\n {sortedRowIndices.map(sortedIdx => (\n <tr key={sortedIdx} className=\"vpg-data-row\">\n {pivotResult.rowHeaders[sortedIdx].map((val, idx) => (\n <th\n key={`row-${sortedIdx}-${idx}`}\n className=\"vpg-row-header-cell\"\n style={{ width: `${rowHeaderColWidth}px`, minWidth: '80px', left: `${getRowHeaderLeftOffset(idx)}px` }}\n >\n {val}\n </th>\n ))}\n\n {pivotResult.data[sortedIdx].map((cell, colIdx) => {\n const displayRowIdx = sortedRowIndices.indexOf(sortedIdx)\n return (\n <td\n key={colIdx}\n className={`vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? 'selected' : ''} ${cell.value === null ? 'vpg-is-null' : ''}`}\n onMouseDown={e => handleCellMouseDown(displayRowIdx, colIdx, e)}\n onMouseEnter={() => handleCellMouseEnter(displayRowIdx, colIdx)}\n >\n {cell.formattedValue}\n </td>\n )\n })}\n\n {pivotResult.rowTotals[sortedIdx] && (\n <td className=\"vpg-data-cell vpg-total-cell\">\n {pivotResult.rowTotals[sortedIdx].formattedValue}\n </td>\n )}\n </tr>\n ))}\n\n {pivotResult.columnTotals.length > 0 && (\n <tr className=\"vpg-totals-row\">\n <th\n className=\"vpg-row-header-cell vpg-total-label\"\n colSpan={Math.max(rowFields.length, 1)}\n style={{ width: `${rowHeaderWidth}px` }}\n >\n Total\n </th>\n {pivotResult.columnTotals.map((cell, colIdx) => (\n <td key={colIdx} className=\"vpg-data-cell vpg-total-cell\">\n {cell.formattedValue}\n </td>\n ))}\n {pivotResult.rowTotals.length > 0 && (\n <td className=\"vpg-data-cell vpg-grand-total-cell\">\n {pivotResult.grandTotal.formattedValue}\n </td>\n )}\n </tr>\n )}\n </tbody>\n </table>\n </div>\n )}\n\n {/* Footer */}\n {isConfigured && pivotResult && (\n <div className=\"vpg-skeleton-footer\">\n <span className=\"vpg-footer-info\">\n {pivotResult.rowHeaders.length}\n {' '}\n rows ×\n {pivotResult.data[0]?.length || 0}\n {' '}\n columns\n </span>\n\n {selectionStats && selectionStats.count > 1 && (\n <div className=\"vpg-selection-stats\">\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Count:</span>\n <span className=\"vpg-stat-value\">{selectionStats.count}</span>\n </span>\n {selectionStats.numericCount > 0 && (\n <>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Sum:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.sum)}</span>\n </span>\n <span className=\"vpg-stat-divider\">|</span>\n <span className=\"vpg-stat\">\n <span className=\"vpg-stat-label\">Avg:</span>\n <span className=\"vpg-stat-value\">{formatStatValue(selectionStats.avg)}</span>\n </span>\n </>\n )}\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {/* Watermark / Demo Banner */}\n {showWatermark && canUsePivot && (\n <div className={`vpg-watermark ${isDemo ? 'vpg-demo-mode' : ''}`}>\n {isDemo\n ? (\n <>\n <span className=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features unlocked for evaluation</span>\n <a\n href=\"https://tiny-pivot.com/#pricing\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"vpg-get-pro\"\n >\n Get Pro License →\n </a>\n </>\n )\n : (\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener noreferrer\">\n Powered by TinyPivot\n </a>\n )}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["import_tinypivot_core","import_react","messages","copyToClipboard","formatCellValue","import_tinypivot_core","import_react","import_jsx_runtime","import_tinypivot_core","import_react","import_jsx_runtime","React","chartData","import_react","import_tinypivot_core","import_react","import_jsx_runtime","import_tinypivot_core","import_react","import_jsx_runtime","import_jsx_runtime","import_tinypivot_core","import_react","import_react_dom","import_tinypivot_core","import_react","import_tinypivot_core","import_react","coreExportToCSV","coreExportPivotToCSV","coreCopyToClipboard","coreFormatSelection","import_tinypivot_core","import_react","coreConfigureLicenseSecret","coreIsPro","coreCanUsePivot","coreCanUseCharts","coreCanUseAIAnalyst","coreShouldShowWatermark","import_tinypivot_core","import_react","import_tinypivot_core","import_react","import_jsx_runtime","import_tinypivot_core","import_react","import_jsx_runtime","import_jsx_runtime","coreFormatDate","coreFormatNumber"]}