@prismiq/react 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/{CustomSQLEditor-d84v_Cgp.d.cts → ChatBubble-ARocmvZD.d.cts} +40 -3
  2. package/dist/{CustomSQLEditor-CYlOtecq.d.ts → ChatBubble-BN_CjIpk.d.ts} +40 -3
  3. package/dist/{DashboardDialog-CZD8I-6z.d.cts → DashboardDialog-UhUGXx2h.d.ts} +5 -3
  4. package/dist/{DashboardDialog-DBNTVVSp.d.ts → DashboardDialog-Z-HypxmG.d.cts} +5 -3
  5. package/dist/charts/index.d.cts +2 -2
  6. package/dist/charts/index.d.ts +2 -2
  7. package/dist/{chunk-VQDFS6VS.cjs → chunk-FKXCINUF.cjs} +368 -210
  8. package/dist/chunk-FKXCINUF.cjs.map +1 -0
  9. package/dist/{chunk-ET7GCREP.js → chunk-GELI7MDZ.js} +482 -7
  10. package/dist/chunk-GELI7MDZ.js.map +1 -0
  11. package/dist/{chunk-WWTT2OJ5.js → chunk-HKZFEXT6.js} +27 -9
  12. package/dist/chunk-HKZFEXT6.js.map +1 -0
  13. package/dist/{chunk-3LDRRDJ6.js → chunk-JBJ5LEAG.js} +186 -28
  14. package/dist/chunk-JBJ5LEAG.js.map +1 -0
  15. package/dist/{chunk-URJH4H6G.cjs → chunk-PG7QBH3G.cjs} +485 -6
  16. package/dist/chunk-PG7QBH3G.cjs.map +1 -0
  17. package/dist/{chunk-MDXGGZSW.cjs → chunk-ZYVN6XAZ.cjs} +35 -37
  18. package/dist/chunk-ZYVN6XAZ.cjs.map +1 -0
  19. package/dist/components/index.cjs +62 -54
  20. package/dist/components/index.d.cts +2 -2
  21. package/dist/components/index.d.ts +2 -2
  22. package/dist/components/index.js +1 -1
  23. package/dist/dashboard/index.cjs +34 -34
  24. package/dist/dashboard/index.d.cts +7 -5
  25. package/dist/dashboard/index.d.ts +7 -5
  26. package/dist/dashboard/index.js +2 -2
  27. package/dist/export/index.cjs +7 -7
  28. package/dist/export/index.d.cts +6 -4
  29. package/dist/export/index.d.ts +6 -4
  30. package/dist/export/index.js +1 -1
  31. package/dist/{index-CvKj3SWO.d.cts → index-B8DelfpL.d.cts} +1 -1
  32. package/dist/{index-DXGLs1yY.d.ts → index-RbfYPQD_.d.ts} +1 -1
  33. package/dist/index.cjs +119 -103
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +74 -7
  36. package/dist/index.d.ts +74 -7
  37. package/dist/index.js +5 -5
  38. package/dist/index.js.map +1 -1
  39. package/dist/{types-j0kPJ9Hz.d.cts → types-ccB9Ps3k.d.cts} +44 -1
  40. package/dist/{types-j0kPJ9Hz.d.ts → types-ccB9Ps3k.d.ts} +44 -1
  41. package/dist/utils/index.d.cts +1 -1
  42. package/dist/utils/index.d.ts +1 -1
  43. package/package.json +2 -6
  44. package/dist/chunk-3LDRRDJ6.js.map +0 -1
  45. package/dist/chunk-ET7GCREP.js.map +0 -1
  46. package/dist/chunk-MDXGGZSW.cjs.map +0 -1
  47. package/dist/chunk-URJH4H6G.cjs.map +0 -1
  48. package/dist/chunk-VQDFS6VS.cjs.map +0 -1
  49. package/dist/chunk-WWTT2OJ5.js.map +0 -1
@@ -1,4 +1,3 @@
1
- import * as XLSX from 'xlsx';
2
1
  import { useState, useMemo, useCallback } from 'react';
3
2
 
4
3
  // src/export/csv.ts
@@ -96,6 +95,18 @@ function exportToCSV(data, options) {
96
95
  const fullFilename = filename.endsWith(".csv") ? filename : `${filename}.csv`;
97
96
  downloadFile(csv, fullFilename, "text/csv;charset=utf-8");
98
97
  }
98
+
99
+ // src/export/excel.ts
100
+ async function loadXLSX() {
101
+ try {
102
+ return await import('xlsx');
103
+ } catch (err) {
104
+ const detail = err instanceof Error ? `: ${err.message}` : "";
105
+ throw new Error(
106
+ `xlsx is required for Excel export. Install it with: npm install xlsx${detail}`
107
+ );
108
+ }
109
+ }
99
110
  function isQueryResult2(data) {
100
111
  return typeof data === "object" && data !== null && "columns" in data && "rows" in data && Array.isArray(data.columns) && Array.isArray(data.rows);
101
112
  }
@@ -127,7 +138,8 @@ function calculateColumnWidth(values) {
127
138
  }
128
139
  return Math.min(Math.max(maxLength + 2, 8), 50);
129
140
  }
130
- function exportToExcel(data, options) {
141
+ async function exportToExcel(data, options) {
142
+ const XLSX = await loadXLSX();
131
143
  const { columns: allColumns, rows } = normalizeData2(data);
132
144
  const exportColumns = options?.columns ?? allColumns;
133
145
  const workbook = XLSX.utils.book_new();
@@ -148,7 +160,7 @@ function exportToExcel(data, options) {
148
160
  }
149
161
  const worksheet = XLSX.utils.aoa_to_sheet(wsData);
150
162
  const colWidths = exportColumns.map((col, index) => {
151
- if (options?.columnWidths?.[col]) {
163
+ if (options?.columnWidths?.[col] !== void 0) {
152
164
  return { wch: options.columnWidths[col] };
153
165
  }
154
166
  const columnValues = [headers[index], ...rows.map((r) => r[col])];
@@ -164,7 +176,8 @@ function exportToExcel(data, options) {
164
176
  const fullFilename = filename.endsWith(".xlsx") ? filename : `${filename}.xlsx`;
165
177
  XLSX.writeFile(workbook, fullFilename);
166
178
  }
167
- function exportMultipleSheets(sheets, filename) {
179
+ async function exportMultipleSheets(sheets, filename) {
180
+ const XLSX = await loadXLSX();
168
181
  const workbook = XLSX.utils.book_new();
169
182
  for (const [sheetName, data] of Object.entries(sheets)) {
170
183
  const { columns, rows } = normalizeData2(data);
@@ -196,6 +209,7 @@ function exportMultipleSheets(sheets, filename) {
196
209
  function useExport(options) {
197
210
  const { data, filename, columns, headers } = options;
198
211
  const [isExporting, setIsExporting] = useState(false);
212
+ const [error, setError] = useState(null);
199
213
  const canExport = useMemo(() => {
200
214
  return data !== null && data.rows.length > 0;
201
215
  }, [data]);
@@ -218,9 +232,10 @@ function useExport(options) {
218
232
  setIsExporting(false);
219
233
  }
220
234
  }, [canExport, data, generateFilename, columns, headers]);
221
- const handleExportExcel = useCallback((excelOptions) => {
235
+ const handleExportExcel = useCallback(async (excelOptions) => {
222
236
  if (!canExport || !data) return;
223
237
  setIsExporting(true);
238
+ setError(null);
224
239
  try {
225
240
  const exportOptions = {
226
241
  filename: generateFilename(),
@@ -228,7 +243,9 @@ function useExport(options) {
228
243
  headers,
229
244
  ...excelOptions
230
245
  };
231
- exportToExcel(data, exportOptions);
246
+ await exportToExcel(data, exportOptions);
247
+ } catch (err) {
248
+ setError(err instanceof Error ? err : new Error(String(err)));
232
249
  } finally {
233
250
  setIsExporting(false);
234
251
  }
@@ -237,10 +254,11 @@ function useExport(options) {
237
254
  exportCSV: handleExportCSV,
238
255
  exportExcel: handleExportExcel,
239
256
  isExporting,
240
- canExport
257
+ canExport,
258
+ error
241
259
  };
242
260
  }
243
261
 
244
262
  export { downloadFile, exportMultipleSheets, exportToCSV, exportToExcel, generateCSV, useExport };
245
- //# sourceMappingURL=chunk-WWTT2OJ5.js.map
246
- //# sourceMappingURL=chunk-WWTT2OJ5.js.map
263
+ //# sourceMappingURL=chunk-HKZFEXT6.js.map
264
+ //# sourceMappingURL=chunk-HKZFEXT6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/export/csv.ts","../src/export/excel.ts","../src/export/useExport.ts"],"names":["isQueryResult","normalizeData"],"mappings":"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","file":"chunk-HKZFEXT6.js","sourcesContent":["/**\n * CSV export functionality.\n */\n\nimport type { QueryResult } from '../types';\nimport type { ExportData, ExportOptions } from './types';\n\n/**\n * Check if data is a QueryResult.\n */\nfunction isQueryResult(data: ExportData): data is QueryResult {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'columns' in data &&\n 'rows' in data &&\n Array.isArray((data as QueryResult).columns) &&\n Array.isArray((data as QueryResult).rows)\n );\n}\n\n/**\n * Convert data to array of objects format.\n */\nfunction normalizeData(data: ExportData): {\n columns: string[];\n rows: Record<string, unknown>[];\n} {\n if (isQueryResult(data)) {\n const rows = data.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n data.columns.forEach((col, index) => {\n obj[col] = row[index];\n });\n return obj;\n });\n return { columns: data.columns, rows };\n }\n\n if (Array.isArray(data) && data.length > 0) {\n const firstRow = data[0];\n if (firstRow && typeof firstRow === 'object') {\n const columns = Object.keys(firstRow);\n return { columns, rows: data };\n }\n }\n\n return { columns: [], rows: [] };\n}\n\n/**\n * Escape a value for CSV.\n *\n * Handles:\n * - Commas (wrap in quotes)\n * - Quotes (double them)\n * - Newlines (wrap in quotes)\n * - Leading/trailing whitespace (wrap in quotes)\n */\nfunction escapeCSVValue(value: unknown): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n const stringValue = String(value);\n\n // Check if we need to quote the value\n const needsQuoting =\n stringValue.includes(',') ||\n stringValue.includes('\"') ||\n stringValue.includes('\\n') ||\n stringValue.includes('\\r') ||\n stringValue.startsWith(' ') ||\n stringValue.endsWith(' ');\n\n if (needsQuoting) {\n // Double any existing quotes and wrap in quotes\n return `\"${stringValue.replace(/\"/g, '\"\"')}\"`;\n }\n\n return stringValue;\n}\n\n/**\n * Format a value for CSV export.\n */\nfunction formatValue(\n value: unknown,\n options?: ExportOptions\n): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Handle dates\n if (value instanceof Date) {\n if (options?.dateFormat) {\n // Simple date formatting (could be extended with a library)\n return value.toISOString();\n }\n return value.toISOString();\n }\n\n // Handle numbers\n if (typeof value === 'number') {\n if (options?.numberFormat) {\n return new Intl.NumberFormat(undefined, options.numberFormat).format(value);\n }\n return String(value);\n }\n\n // Handle booleans\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n // Handle objects/arrays\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n\n return String(value);\n}\n\n/**\n * Generate CSV content from data.\n *\n * @param data - Array of row objects\n * @param columns - Column names\n * @param headers - Custom header names\n * @param options - Export options\n * @returns CSV string\n */\nexport function generateCSV(\n data: Record<string, unknown>[],\n columns: string[],\n headers?: Record<string, string>,\n options?: ExportOptions\n): string {\n const lines: string[] = [];\n\n // Header row\n const headerRow = columns.map((col) => {\n const headerName = headers?.[col] ?? col;\n return escapeCSVValue(headerName);\n });\n lines.push(headerRow.join(','));\n\n // Data rows\n for (const row of data) {\n const rowValues = columns.map((col) => {\n const value = row[col];\n const formatted = formatValue(value, options);\n return escapeCSVValue(formatted);\n });\n lines.push(rowValues.join(','));\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Trigger a file download in the browser.\n *\n * @param content - File content\n * @param filename - File name with extension\n * @param mimeType - MIME type\n */\nexport function downloadFile(\n content: string,\n filename: string,\n mimeType: string\n): void {\n // Create blob\n const blob = new Blob([content], { type: mimeType });\n\n // Create download link\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n\n // Trigger download\n document.body.appendChild(link);\n link.click();\n\n // Cleanup\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Export data to CSV and trigger download.\n *\n * @param data - QueryResult or array of objects\n * @param options - Export options\n *\n * @example\n * ```tsx\n * // Export query result\n * exportToCSV(queryResult, { filename: 'sales-report' });\n *\n * // Export with custom columns\n * exportToCSV(data, {\n * columns: ['id', 'name', 'value'],\n * headers: { id: 'ID', name: 'Name', value: 'Value' }\n * });\n * ```\n */\nexport function exportToCSV(\n data: ExportData,\n options?: ExportOptions\n): void {\n const { columns: allColumns, rows } = normalizeData(data);\n\n // Use specified columns or all columns\n const exportColumns = options?.columns ?? allColumns;\n\n // Generate CSV\n const csv = generateCSV(rows, exportColumns, options?.headers, options);\n\n // Generate filename\n const filename = options?.filename ?? 'export';\n const fullFilename = filename.endsWith('.csv') ? filename : `${filename}.csv`;\n\n // Download\n downloadFile(csv, fullFilename, 'text/csv;charset=utf-8');\n}\n","/**\n * Excel export functionality.\n *\n * Uses the xlsx library (SheetJS) for Excel file generation.\n */\n\nimport type { QueryResult } from '../types';\nimport type { ExcelExportOptions, ExportData } from './types';\n\ntype XLSXModule = typeof import('xlsx');\n\nasync function loadXLSX(): Promise<XLSXModule> {\n try {\n return await import('xlsx');\n } catch (err) {\n const detail = err instanceof Error ? `: ${err.message}` : '';\n throw new Error(\n `xlsx is required for Excel export. Install it with: npm install xlsx${detail}`\n );\n }\n}\n\n/**\n * Check if data is a QueryResult.\n */\nfunction isQueryResult(data: ExportData): data is QueryResult {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'columns' in data &&\n 'rows' in data &&\n Array.isArray((data as QueryResult).columns) &&\n Array.isArray((data as QueryResult).rows)\n );\n}\n\n/**\n * Convert data to array of objects format.\n */\nfunction normalizeData(data: ExportData): {\n columns: string[];\n rows: Record<string, unknown>[];\n} {\n if (isQueryResult(data)) {\n const rows = data.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n data.columns.forEach((col, index) => {\n obj[col] = row[index];\n });\n return obj;\n });\n return { columns: data.columns, rows };\n }\n\n if (Array.isArray(data) && data.length > 0) {\n const firstRow = data[0];\n if (firstRow && typeof firstRow === 'object') {\n const columns = Object.keys(firstRow);\n return { columns, rows: data };\n }\n }\n\n return { columns: [], rows: [] };\n}\n\n/**\n * Calculate optimal column width based on content.\n */\nfunction calculateColumnWidth(values: unknown[]): number {\n let maxLength = 0;\n\n for (const value of values) {\n const strValue = value === null || value === undefined ? '' : String(value);\n maxLength = Math.max(maxLength, strValue.length);\n }\n\n // Add some padding and cap at reasonable max\n return Math.min(Math.max(maxLength + 2, 8), 50);\n}\n\n/**\n * Export data to Excel and trigger download.\n *\n * @param data - QueryResult or array of objects\n * @param options - Export options\n *\n * @example\n * ```tsx\n * // Basic export\n * exportToExcel(queryResult, { filename: 'sales-report' });\n *\n * // With styling\n * exportToExcel(data, {\n * filename: 'report',\n * sheetName: 'Sales Data',\n * freezeHeader: true,\n * headerStyle: { bold: true, fill: '#e3f2fd', align: 'center' }\n * });\n * ```\n */\nexport async function exportToExcel(\n data: ExportData,\n options?: ExcelExportOptions\n): Promise<void> {\n const XLSX = await loadXLSX();\n const { columns: allColumns, rows } = normalizeData(data);\n\n // Use specified columns or all columns\n const exportColumns = options?.columns ?? allColumns;\n\n // Create workbook and worksheet\n const workbook = XLSX.utils.book_new();\n\n // Prepare data with headers\n const headers = exportColumns.map(col => options?.headers?.[col] ?? col);\n\n // Convert rows to array format for the worksheet\n const wsData: unknown[][] = [headers];\n\n for (const row of rows) {\n const rowData = exportColumns.map(col => {\n const value = row[col];\n // Handle special types\n if (value instanceof Date) {\n return value;\n }\n if (typeof value === 'object' && value !== null) {\n return JSON.stringify(value);\n }\n return value;\n });\n wsData.push(rowData);\n }\n\n // Create worksheet from data\n const worksheet = XLSX.utils.aoa_to_sheet(wsData);\n\n // Set column widths\n const colWidths = exportColumns.map((col, index) => {\n // Use custom width if specified\n if (options?.columnWidths?.[col] !== undefined) {\n return { wch: options.columnWidths[col] };\n }\n\n // Calculate width from content\n const columnValues = [headers[index], ...rows.map(r => r[col])];\n return { wch: calculateColumnWidth(columnValues) };\n });\n worksheet['!cols'] = colWidths;\n\n // Freeze header row if requested\n if (options?.freezeHeader) {\n worksheet['!freeze'] = { xSplit: 0, ySplit: 1 };\n }\n\n // Add worksheet to workbook\n const sheetName = options?.sheetName ?? 'Sheet1';\n XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);\n\n // Generate filename\n const filename = options?.filename ?? 'export';\n const fullFilename = filename.endsWith('.xlsx') ? filename : `${filename}.xlsx`;\n\n // Write and download\n XLSX.writeFile(workbook, fullFilename);\n}\n\n/**\n * Export multiple sheets to a single Excel file.\n *\n * @param sheets - Object mapping sheet names to data\n * @param filename - Output filename\n *\n * @example\n * ```tsx\n * exportMultipleSheets({\n * 'Sales': salesData,\n * 'Customers': customerData,\n * 'Products': productData,\n * }, 'full-report');\n * ```\n */\nexport async function exportMultipleSheets(\n sheets: Record<string, ExportData>,\n filename: string\n): Promise<void> {\n const XLSX = await loadXLSX();\n const workbook = XLSX.utils.book_new();\n\n for (const [sheetName, data] of Object.entries(sheets)) {\n const { columns, rows } = normalizeData(data);\n\n // Prepare data with headers\n const wsData: unknown[][] = [columns];\n\n for (const row of rows) {\n const rowData = columns.map(col => {\n const value = row[col];\n if (value instanceof Date) {\n return value;\n }\n if (typeof value === 'object' && value !== null) {\n return JSON.stringify(value);\n }\n return value;\n });\n wsData.push(rowData);\n }\n\n const worksheet = XLSX.utils.aoa_to_sheet(wsData);\n\n // Auto-size columns\n const colWidths = columns.map((col, index) => {\n const columnValues = [columns[index], ...rows.map(r => r[col])];\n return { wch: calculateColumnWidth(columnValues) };\n });\n worksheet['!cols'] = colWidths;\n\n XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);\n }\n\n const fullFilename = filename.endsWith('.xlsx') ? filename : `${filename}.xlsx`;\n XLSX.writeFile(workbook, fullFilename);\n}\n","'use client';\n\nimport { useCallback, useMemo, useState } from 'react';\nimport type { QueryResult } from '../types';\nimport { exportToCSV } from './csv';\nimport { exportToExcel } from './excel';\nimport type { ExcelExportOptions, ExportOptions } from './types';\n\n/**\n * Options for the useExport hook.\n */\nexport interface UseExportOptions {\n /** Data to export */\n data: QueryResult | null;\n /** Default filename for exports */\n filename?: string;\n /** Columns to export (defaults to all) */\n columns?: string[];\n /** Custom column headers */\n headers?: Record<string, string>;\n}\n\n/**\n * Result of the useExport hook.\n */\nexport interface UseExportResult {\n /** Export to CSV file */\n exportCSV: () => void;\n /** Export to Excel file */\n exportExcel: (options?: ExcelExportOptions) => Promise<void>;\n /** Whether an export is in progress */\n isExporting: boolean;\n /** Whether export is possible (data is available) */\n canExport: boolean;\n /** Error from the most recent export attempt, if any */\n error: Error | null;\n}\n\n/**\n * Hook for exporting query data to CSV or Excel.\n *\n * @param options - Export options\n * @returns Export functions and state\n *\n * @example\n * ```tsx\n * function DataTable({ data }) {\n * const { exportCSV, exportExcel, canExport, isExporting } = useExport({\n * data,\n * filename: 'sales-report',\n * columns: ['id', 'name', 'amount'],\n * headers: { id: 'ID', name: 'Name', amount: 'Amount' }\n * });\n *\n * return (\n * <div>\n * <button onClick={exportCSV} disabled={!canExport || isExporting}>\n * Export CSV\n * </button>\n * <button onClick={() => exportExcel()} disabled={!canExport || isExporting}>\n * Export Excel\n * </button>\n * {isExporting && <span>Exporting...</span>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useExport(options: UseExportOptions): UseExportResult {\n const { data, filename, columns, headers } = options;\n const [isExporting, setIsExporting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Check if export is possible\n const canExport = useMemo(() => {\n return data !== null && data.rows.length > 0;\n }, [data]);\n\n // Generate timestamp for filename\n const generateFilename = useCallback(() => {\n const base = filename ?? 'export';\n const timestamp = new Date().toISOString().slice(0, 10);\n return `${base}-${timestamp}`;\n }, [filename]);\n\n // Export to CSV\n const handleExportCSV = useCallback(() => {\n if (!canExport || !data) return;\n\n setIsExporting(true);\n try {\n const exportOptions: ExportOptions = {\n filename: generateFilename(),\n columns,\n headers,\n };\n exportToCSV(data, exportOptions);\n } finally {\n setIsExporting(false);\n }\n }, [canExport, data, generateFilename, columns, headers]);\n\n // Export to Excel\n const handleExportExcel = useCallback(async (excelOptions?: ExcelExportOptions) => {\n if (!canExport || !data) return;\n\n setIsExporting(true);\n setError(null);\n try {\n const exportOptions: ExcelExportOptions = {\n filename: generateFilename(),\n columns,\n headers,\n ...excelOptions,\n };\n await exportToExcel(data, exportOptions);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsExporting(false);\n }\n }, [canExport, data, generateFilename, columns, headers]);\n\n return {\n exportCSV: handleExportCSV,\n exportExcel: handleExportExcel,\n isExporting,\n canExport,\n error,\n };\n}\n\nexport default useExport;\n"]}
@@ -1,5 +1,5 @@
1
1
  import { ScatterChart, PieChart, AreaChart, LineChart, BarChart, MetricCard } from './chunk-FQ23KG6G.js';
2
- import { Dropdown, DropdownItem, Icon, DropdownSeparator, Button, Skeleton, EmptyState, Dialog, Input, Checkbox, DialogFooter, useAnalytics, useCrossFilterOptional, useDebouncedLayoutSave, AutoSaveIndicator, ResultsTable, CrossFilterProvider, Tooltip, QueryBuilder, SavedQueryPicker, useSchema, Select, CollapsibleSection, ColorPaletteSelector, FilterBuilder, TableSelector, JoinBuilder, TimeSeriesConfig, CalculatedFieldBuilder } from './chunk-ET7GCREP.js';
2
+ import { Dropdown, DropdownItem, Icon, DropdownSeparator, Button, Skeleton, EmptyState, Dialog, Input, Checkbox, DialogFooter, useAnalytics, useCrossFilterOptional, useDebouncedLayoutSave, AutoSaveIndicator, ResultsTable, CrossFilterProvider, useLLMStatus, Tooltip, QueryBuilder, SavedQueryPicker, SchemaExplorer, CustomSQLEditor, ChatPanel, useSchema, Select, CollapsibleSection, ColorPaletteSelector, FilterBuilder, TableSelector, JoinBuilder, TimeSeriesConfig, CalculatedFieldBuilder } from './chunk-GELI7MDZ.js';
3
3
  import { useTheme } from './chunk-T6STUE7E.js';
4
4
  import { formatRelativeTime, createDateFormatters, pivotQueryResult, parseMarkdownSafe, parseColumnRef } from './chunk-LBE6GIBC.js';
5
5
  import { createContext, forwardRef, useState, useEffect, useCallback, useRef, useMemo, useContext } from 'react';
@@ -180,7 +180,8 @@ function DashboardProvider({
180
180
  if (!lazyLoadingEnabledRef.current) {
181
181
  const initialLoadingState = {};
182
182
  data.widgets.forEach((widget) => {
183
- if (widget.query) {
183
+ const isSqlMode = widget.config?.data_source_mode === "sql" && widget.config?.raw_sql;
184
+ if (widget.query || isSqlMode) {
184
185
  initialLoadingState[widget.id] = true;
185
186
  }
186
187
  });
@@ -189,7 +190,8 @@ function DashboardProvider({
189
190
  }, []);
190
191
  const executeWidgetQuery = useCallback(
191
192
  async (widget, currentDashboard, currentFilters, currentCrossFilters, bypassCache = false, signal) => {
192
- if (!widget.query) {
193
+ const isSqlMode = widget.config?.data_source_mode === "sql" && widget.config?.raw_sql;
194
+ if (!widget.query && !isSqlMode) {
193
195
  return;
194
196
  }
195
197
  setWidgetLoading((prev) => ({ ...prev, [widget.id]: true }));
@@ -202,13 +204,18 @@ function DashboardProvider({
202
204
  return next;
203
205
  });
204
206
  try {
205
- let query = applyFiltersToQuery(
206
- widget.query,
207
- currentDashboard,
208
- currentFilters
209
- );
210
- query = applyCrossFiltersToQuery(query, currentCrossFilters, widget.id);
211
- const result = await client.executeQuery(query, bypassCache, signal);
207
+ let result;
208
+ if (isSqlMode) {
209
+ result = await client.executeSQL(widget.config.raw_sql);
210
+ } else {
211
+ let query = applyFiltersToQuery(
212
+ widget.query,
213
+ currentDashboard,
214
+ currentFilters
215
+ );
216
+ query = applyCrossFiltersToQuery(query, currentCrossFilters, widget.id);
217
+ result = await client.executeQuery(query, bypassCache, signal);
218
+ }
212
219
  if (signal?.aborted) return;
213
220
  setWidgetResults((prev) => ({ ...prev, [widget.id]: result }));
214
221
  const refreshTime = result.cached_at ?? Date.now() / 1e3;
@@ -237,7 +244,9 @@ function DashboardProvider({
237
244
  );
238
245
  const executeWidgetsInBatches = useCallback(
239
246
  async (widgets, currentDashboard, currentFilters, currentCrossFilters, bypassCache = false, currentBatchSize = batchSize, signal) => {
240
- const widgetsWithQueries = widgets.filter((w) => w.query !== null);
247
+ const widgetsWithQueries = widgets.filter(
248
+ (w) => w.query !== null || w.config?.data_source_mode === "sql" && w.config?.raw_sql
249
+ );
241
250
  for (let i = 0; i < widgetsWithQueries.length; i += currentBatchSize) {
242
251
  if (signal?.aborted) return;
243
252
  const batch = widgetsWithQueries.slice(i, i + currentBatchSize);
@@ -436,7 +445,7 @@ function DashboardProvider({
436
445
  useEffect(() => {
437
446
  if (!lazyLoadingEnabled || !dashboard || isLoading) return;
438
447
  const widgetsToLoad = dashboard.widgets.filter(
439
- (w) => visibleWidgets.has(w.id) && w.query !== null && !widgetResults[w.id] && !widgetLoading[w.id]
448
+ (w) => visibleWidgets.has(w.id) && (w.query !== null || w.config?.data_source_mode === "sql" && w.config?.raw_sql) && !widgetResults[w.id] && !widgetLoading[w.id]
440
449
  );
441
450
  if (widgetsToLoad.length > 0) {
442
451
  const signal = abortControllerRef.current?.signal;
@@ -470,7 +479,7 @@ function DashboardProvider({
470
479
  if (prevFilterValuesRef.current === filterValuesKey) return;
471
480
  prevFilterValuesRef.current = filterValuesKey;
472
481
  const widgetsToRefresh = dashboard.widgets.filter(
473
- (w) => everVisibleWidgets.has(w.id) && w.query !== null && widgetResults[w.id]
482
+ (w) => everVisibleWidgets.has(w.id) && (w.query !== null || w.config?.data_source_mode === "sql" && w.config?.raw_sql) && widgetResults[w.id]
474
483
  // Only re-execute if previously loaded
475
484
  );
476
485
  if (widgetsToRefresh.length > 0) {
@@ -3117,6 +3126,7 @@ function WidgetPreview({
3117
3126
  title,
3118
3127
  config,
3119
3128
  query,
3129
+ rawSql,
3120
3130
  result,
3121
3131
  isLoading = false,
3122
3132
  error,
@@ -3171,13 +3181,14 @@ function WidgetPreview({
3171
3181
  };
3172
3182
  const previewWidget = createPreviewWidget(type, title, config, query);
3173
3183
  const needsQuery = type !== "text";
3174
- const showEmptyState = needsQuery && !query && !isLoading;
3175
- return /* @__PURE__ */ jsxs("div", { className: `prismiq-widget-preview ${className}`, style: containerStyle, children: [
3184
+ const hasDataSource = !!query || !!rawSql;
3185
+ const showEmptyState = needsQuery && !hasDataSource && !isLoading;
3186
+ return /* @__PURE__ */ jsxs("div", { className: `prismiq-widget-preview ${className}`, style: containerStyle, "data-testid": "widget-preview", children: [
3176
3187
  /* @__PURE__ */ jsxs("div", { style: headerStyle, children: [
3177
3188
  /* @__PURE__ */ jsx("h3", { style: titleStyle, children: title || "Widget Preview" }),
3178
3189
  /* @__PURE__ */ jsx("span", { style: labelStyle, children: "Preview" })
3179
3190
  ] }),
3180
- /* @__PURE__ */ jsx("div", { style: contentStyle, children: showEmptyState ? /* @__PURE__ */ jsxs("div", { style: emptyStateStyle, children: [
3191
+ /* @__PURE__ */ jsx("div", { style: contentStyle, children: showEmptyState ? /* @__PURE__ */ jsxs("div", { style: emptyStateStyle, "data-testid": "widget-preview-empty", children: [
3181
3192
  /* @__PURE__ */ jsx(
3182
3193
  "div",
3183
3194
  {
@@ -5369,6 +5380,7 @@ function WidgetEditorPage({
5369
5380
  }) {
5370
5381
  const { theme } = useTheme();
5371
5382
  const { client } = useAnalytics();
5383
+ const { enabled: llmEnabled, isLoading: llmStatusLoading } = useLLMStatus();
5372
5384
  const isNew = widget === null;
5373
5385
  const [type, setType] = useState(widget?.type ?? "bar_chart");
5374
5386
  const [title, setTitle] = useState(widget?.title ?? "New Widget");
@@ -5380,6 +5392,8 @@ function WidgetEditorPage({
5380
5392
  const [position, setPosition] = useState(
5381
5393
  widget?.position ?? { x: 0, y: 0, w: 6, h: 4, minW: 2, minH: 2 }
5382
5394
  );
5395
+ const [rawSql, setRawSql] = useState(widget?.config?.raw_sql ?? "");
5396
+ const [schemaOpen, setSchemaOpen] = useState(true);
5383
5397
  const [dataSourceMode, setDataSourceMode] = useState(
5384
5398
  isNew ? "guided" : widget?.config?.data_source_mode ?? "guided"
5385
5399
  );
@@ -5404,6 +5418,24 @@ function WidgetEditorPage({
5404
5418
  []
5405
5419
  );
5406
5420
  const refreshPreview = useCallback(async () => {
5421
+ if (dataSourceMode === "sql") {
5422
+ if (!rawSql.trim() || !client) {
5423
+ setPreviewResult(null);
5424
+ return;
5425
+ }
5426
+ setPreviewLoading(true);
5427
+ setPreviewError(null);
5428
+ try {
5429
+ const result = await client.executeSQL(rawSql);
5430
+ setPreviewResult(result);
5431
+ } catch (err) {
5432
+ setPreviewError(err instanceof Error ? err : new Error("SQL execution failed"));
5433
+ setPreviewResult(null);
5434
+ } finally {
5435
+ setPreviewLoading(false);
5436
+ }
5437
+ return;
5438
+ }
5407
5439
  if (!query || !client) {
5408
5440
  setPreviewResult(null);
5409
5441
  return;
@@ -5419,15 +5451,18 @@ function WidgetEditorPage({
5419
5451
  } finally {
5420
5452
  setPreviewLoading(false);
5421
5453
  }
5422
- }, [query, client]);
5454
+ }, [query, rawSql, dataSourceMode, client]);
5423
5455
  useEffect(() => {
5456
+ if (dataSourceMode === "sql") {
5457
+ return;
5458
+ }
5424
5459
  if (query) {
5425
5460
  void refreshPreview();
5426
5461
  } else {
5427
5462
  setPreviewResult(null);
5428
5463
  setPreviewError(null);
5429
5464
  }
5430
- }, [query, refreshPreview]);
5465
+ }, [query, dataSourceMode, refreshPreview]);
5431
5466
  const queryHasAdvancedFeatures = useCallback((q) => {
5432
5467
  if (!q) return false;
5433
5468
  if (q.tables && q.tables.length > 1 && q.joins && q.joins.length > 0) return true;
@@ -5459,18 +5494,25 @@ function WidgetEditorPage({
5459
5494
  setPreviewResult(null);
5460
5495
  setPreviewError(null);
5461
5496
  }, []);
5497
+ const handleApplySql = useCallback((sql) => {
5498
+ setRawSql(sql);
5499
+ }, []);
5462
5500
  const handleSave = useCallback(() => {
5501
+ const savedConfig = { ...config, data_source_mode: dataSourceMode };
5502
+ if (dataSourceMode === "sql") {
5503
+ savedConfig.raw_sql = rawSql.trim() || void 0;
5504
+ }
5463
5505
  const savedWidget = {
5464
5506
  id: widget?.id ?? generateId(),
5465
5507
  type,
5466
5508
  title,
5467
- config: { ...config, data_source_mode: dataSourceMode },
5468
- query,
5509
+ config: savedConfig,
5510
+ query: dataSourceMode === "sql" ? null : query,
5469
5511
  position,
5470
5512
  hyperlink
5471
5513
  };
5472
5514
  onSave(savedWidget);
5473
- }, [widget, type, title, config, query, position, hyperlink, dataSourceMode, onSave]);
5515
+ }, [widget, type, title, config, query, rawSql, position, hyperlink, dataSourceMode, onSave]);
5474
5516
  const columnSelectOptions = useMemo(() => {
5475
5517
  if (!schema) return [];
5476
5518
  return schema.tables.flatMap(
@@ -5956,6 +5998,7 @@ function WidgetEditorPage({
5956
5998
  title,
5957
5999
  config,
5958
6000
  query,
6001
+ rawSql: dataSourceMode === "sql" ? rawSql : void 0,
5959
6002
  result: previewResult,
5960
6003
  isLoading: previewLoading,
5961
6004
  error: previewError
@@ -5999,6 +6042,24 @@ function WidgetEditorPage({
5999
6042
  }
6000
6043
  )
6001
6044
  }
6045
+ ),
6046
+ /* @__PURE__ */ jsx(
6047
+ Tooltip,
6048
+ {
6049
+ content: "Write raw SQL queries directly, with optional AI assistance",
6050
+ position: "bottom",
6051
+ style: { whiteSpace: "normal" },
6052
+ children: /* @__PURE__ */ jsx(
6053
+ "button",
6054
+ {
6055
+ type: "button",
6056
+ "data-testid": "data-source-mode-sql",
6057
+ style: tabStyle(dataSourceMode === "sql"),
6058
+ onClick: () => handleModeSwitch("sql"),
6059
+ children: "SQL"
6060
+ }
6061
+ )
6062
+ }
6002
6063
  )
6003
6064
  ] }),
6004
6065
  /* @__PURE__ */ jsxs("div", { style: dataSourceContentStyle, children: [
@@ -6030,7 +6091,100 @@ function WidgetEditorPage({
6030
6091
  onSelect: handleSavedQuerySelect,
6031
6092
  showSave: false
6032
6093
  }
6033
- )
6094
+ ),
6095
+ dataSourceMode === "sql" && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 0, height: "100%", minHeight: "400px" }, children: [
6096
+ /* @__PURE__ */ jsx("div", { "data-testid": "schema-panel", style: {
6097
+ width: schemaOpen ? "220px" : "36px",
6098
+ flexShrink: 0,
6099
+ transition: "width 0.2s ease",
6100
+ borderRight: `1px solid ${theme.colors.border}`,
6101
+ display: "flex",
6102
+ flexDirection: "column",
6103
+ overflow: "hidden"
6104
+ }, children: schemaOpen ? /* @__PURE__ */ jsx(
6105
+ SchemaExplorer,
6106
+ {
6107
+ searchable: true,
6108
+ collapsible: true,
6109
+ onColumnSelect: (table, col) => {
6110
+ const ref = `"${table.name}"."${col.name}"`;
6111
+ setRawSql((prev) => prev ? `${prev} ${ref}` : ref);
6112
+ },
6113
+ headerAction: /* @__PURE__ */ jsx(
6114
+ "button",
6115
+ {
6116
+ type: "button",
6117
+ onClick: () => setSchemaOpen(false),
6118
+ title: "Collapse schema panel",
6119
+ "data-testid": "schema-toggle-open",
6120
+ style: {
6121
+ display: "flex",
6122
+ alignItems: "center",
6123
+ justifyContent: "center",
6124
+ width: "22px",
6125
+ height: "22px",
6126
+ backgroundColor: "transparent",
6127
+ border: `1px solid ${theme.colors.border}`,
6128
+ borderRadius: theme.radius.sm,
6129
+ cursor: "pointer",
6130
+ color: theme.colors.textMuted,
6131
+ flexShrink: 0
6132
+ },
6133
+ children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 12 })
6134
+ }
6135
+ ),
6136
+ style: { flex: 1, border: "none", borderRadius: 0 }
6137
+ }
6138
+ ) : /* @__PURE__ */ jsxs(
6139
+ "button",
6140
+ {
6141
+ type: "button",
6142
+ onClick: () => setSchemaOpen(true),
6143
+ title: "Show schema browser",
6144
+ "data-testid": "schema-toggle-collapsed",
6145
+ style: {
6146
+ display: "flex",
6147
+ flexDirection: "column",
6148
+ alignItems: "center",
6149
+ gap: "6px",
6150
+ paddingTop: theme.spacing.sm,
6151
+ width: "100%",
6152
+ height: "100%",
6153
+ backgroundColor: theme.colors.surface,
6154
+ border: "none",
6155
+ cursor: "pointer",
6156
+ color: theme.colors.textMuted,
6157
+ fontFamily: theme.fonts.sans
6158
+ },
6159
+ children: [
6160
+ /* @__PURE__ */ jsx(Icon, { name: "table", size: 16 }),
6161
+ /* @__PURE__ */ jsx("span", { style: {
6162
+ writingMode: "vertical-rl",
6163
+ fontSize: "11px",
6164
+ fontWeight: 500,
6165
+ letterSpacing: "0.04em"
6166
+ }, children: "Schema" })
6167
+ ]
6168
+ }
6169
+ ) }),
6170
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, "data-testid": "sql-editor", children: /* @__PURE__ */ jsx(
6171
+ CustomSQLEditor,
6172
+ {
6173
+ initialSql: rawSql,
6174
+ onSqlChange: setRawSql,
6175
+ onExecute: () => void refreshPreview(),
6176
+ showResults: false,
6177
+ placeholder: "Write your SQL query here..."
6178
+ }
6179
+ ) }),
6180
+ !llmStatusLoading && llmEnabled && /* @__PURE__ */ jsx("div", { style: { width: "340px", flexShrink: 0 }, "data-testid": "chat-panel", children: /* @__PURE__ */ jsx(
6181
+ ChatPanel,
6182
+ {
6183
+ currentSql: rawSql || null,
6184
+ onApplySql: handleApplySql
6185
+ }
6186
+ ) })
6187
+ ] })
6034
6188
  ] })
6035
6189
  ] })
6036
6190
  ] })
@@ -6112,7 +6266,9 @@ function DashboardEditor({
6112
6266
  clientRef.current = client;
6113
6267
  const loadedDashboardRef = useRef(null);
6114
6268
  const executeWidgetQueries = useCallback(async (widgets, currentClient) => {
6115
- const widgetsWithQueries = widgets.filter((w) => w.query);
6269
+ const widgetsWithQueries = widgets.filter(
6270
+ (w) => w.query || w.config?.data_source_mode === "sql" && w.config?.raw_sql
6271
+ );
6116
6272
  if (widgetsWithQueries.length === 0) return;
6117
6273
  for (let i = 0; i < widgetsWithQueries.length; i += batchSize) {
6118
6274
  const batch = widgetsWithQueries.slice(i, i + batchSize);
@@ -6126,7 +6282,8 @@ function DashboardEditor({
6126
6282
  await Promise.all(
6127
6283
  batch.map(async (widget) => {
6128
6284
  try {
6129
- const result = await currentClient.executeQuery(widget.query);
6285
+ const isSqlMode = widget.config?.data_source_mode === "sql" && widget.config?.raw_sql;
6286
+ const result = isSqlMode ? await currentClient.executeSQL(widget.config.raw_sql) : await currentClient.executeQuery(widget.query);
6130
6287
  setWidgetResults((prev) => ({ ...prev, [widget.id]: result }));
6131
6288
  setWidgetRefreshTimes((prev) => ({ ...prev, [widget.id]: Math.floor(Date.now() / 1e3) }));
6132
6289
  } catch (err) {
@@ -6203,11 +6360,12 @@ function DashboardEditor({
6203
6360
  const refreshWidget = useCallback(
6204
6361
  async (widgetId, widgetOverride) => {
6205
6362
  const widget = widgetOverride ?? dashboard.widgets.find((w) => w.id === widgetId);
6206
- if (!widget?.query || !client) return;
6363
+ const isSqlMode = widget?.config?.data_source_mode === "sql" && widget?.config?.raw_sql;
6364
+ if (!widget?.query && !isSqlMode || !client) return;
6207
6365
  setWidgetLoading((prev) => ({ ...prev, [widgetId]: true }));
6208
6366
  setRefreshingWidgets((prev) => new Set(prev).add(widgetId));
6209
6367
  try {
6210
- const result = await client.executeQuery(widget.query, true);
6368
+ const result = isSqlMode ? await client.executeSQL(widget.config.raw_sql) : await client.executeQuery(widget.query, true);
6211
6369
  setWidgetResults((prev) => ({ ...prev, [widgetId]: result }));
6212
6370
  setWidgetRefreshTimes((prev) => ({ ...prev, [widgetId]: Math.floor(Date.now() / 1e3) }));
6213
6371
  setWidgetErrors((prev) => {
@@ -7600,5 +7758,5 @@ var DashboardDialog = forwardRef(
7600
7758
  );
7601
7759
 
7602
7760
  export { Dashboard, DashboardCard, DashboardContext, DashboardDialog, DashboardEditor, DashboardLayout, DashboardList, DashboardProvider, DateRangeFilter, EditableDashboardLayout, EditorToolbar, FilterBar, LazyWidget, MultiSelectFilter, SelectFilter, TextFilter, Widget, WidgetContainer, WidgetContent, WidgetEditor, WidgetEditorPage, WidgetHeader, WidgetPalette, WidgetPlaceholder, WidgetPreview, WidgetTypeSelector, useAutoRefresh, useDashboard, useDashboardFilters, useFullscreen, useWidget, useWidgetVisibility };
7603
- //# sourceMappingURL=chunk-3LDRRDJ6.js.map
7604
- //# sourceMappingURL=chunk-3LDRRDJ6.js.map
7761
+ //# sourceMappingURL=chunk-JBJ5LEAG.js.map
7762
+ //# sourceMappingURL=chunk-JBJ5LEAG.js.map