drizzle-cube 0.4.8 → 0.4.10
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.
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.js +1 -1
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.js +1 -1
- package/dist/adapters/{handler-odjn7MIB.js → handler-CySCodwi.js} +336 -210
- package/dist/adapters/{handler-BLcxTuwi.cjs → handler-e6zofK2k.cjs} +13 -13
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +1 -1
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/client/charts.js +4 -4
- package/dist/client/chunks/{analysis-builder-Bov_gLsf.js → analysis-builder-BMmWeFPr.js} +138 -138
- package/dist/client/chunks/{analysis-builder-Bov_gLsf.js.map → analysis-builder-BMmWeFPr.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-NBk6y0md.js → analysis-builder-shared-D56zYeV0.js} +713 -787
- package/dist/client/chunks/analysis-builder-shared-D56zYeV0.js.map +1 -0
- package/dist/client/chunks/{chart-area-QKKboTbq.js → chart-area-BJAgusst.js} +2 -2
- package/dist/client/chunks/{chart-area-QKKboTbq.js.map → chart-area-BJAgusst.js.map} +1 -1
- package/dist/client/chunks/chart-bar-Blypx8O4.js +267 -0
- package/dist/client/chunks/chart-bar-Blypx8O4.js.map +1 -0
- package/dist/client/chunks/{chart-line-C7YcMWBw.js → chart-line-zi6olZet.js} +2 -2
- package/dist/client/chunks/{chart-line-C7YcMWBw.js.map → chart-line-zi6olZet.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-HYQFVOo4.js → charts-loader-CH0_S06T.js} +4 -4
- package/dist/client/chunks/{charts-loader-HYQFVOo4.js.map → charts-loader-CH0_S06T.js.map} +1 -1
- package/dist/client/chunks/{components-O0hh7ooo.js → components-ClQziOcT.js} +1495 -1416
- package/dist/client/chunks/components-ClQziOcT.js.map +1 -0
- package/dist/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +1 -0
- package/dist/client/components.js +8 -8
- package/dist/client/index.js +655 -584
- package/dist/client/index.js.map +1 -1
- package/dist/client/stores/notebookStore.d.ts +2 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/utils.js +1 -1
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +13 -13
- package/dist/server/index.js +1824 -1698
- package/package.json +1 -1
- package/dist/client/chunks/analysis-builder-shared-NBk6y0md.js.map +0 -1
- package/dist/client/chunks/chart-bar-HpXF42H1.js +0 -254
- package/dist/client/chunks/chart-bar-HpXF42H1.js.map +0 -1
- package/dist/client/chunks/components-O0hh7ooo.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-line-C7YcMWBw.js","sources":["../../../src/client/utils/comparisonUtils.ts","../../../src/client/components/charts/LineChart.tsx"],"sourcesContent":["/**\n * Comparison Data Utilities\n * Handles period-over-period comparison data transformation for charts\n *\n * These utilities detect comparison query results (with __periodIndex metadata)\n * and transform them for visualization in either 'separate' or 'overlay' mode.\n */\n\n/**\n * Check if data contains comparison period metadata\n */\nexport function isComparisonData(data: any[]): boolean {\n return data.length > 0 && '__periodIndex' in data[0]\n}\n\n/**\n * Get unique period labels from comparison data\n */\nexport function getPeriodLabels(data: any[]): string[] {\n if (!isComparisonData(data)) return []\n\n const labels = new Set<string>()\n for (const row of data) {\n if (row.__period) {\n labels.add(row.__period)\n }\n }\n return Array.from(labels)\n}\n\n/**\n * Get period indices from comparison data\n */\nexport function getPeriodIndices(data: any[]): number[] {\n if (!isComparisonData(data)) return []\n\n const indices = new Set<number>()\n for (const row of data) {\n if (typeof row.__periodIndex === 'number') {\n indices.add(row.__periodIndex)\n }\n }\n return Array.from(indices).sort((a, b) => a - b)\n}\n\n/**\n * Generate a short label for a period (used in legends)\n * Uses simple \"Current\" / \"Prior\" labels for clarity\n */\nexport function generatePeriodShortLabel(_periodLabel: string, index: number): string {\n return index === 0 ? 'Current' : 'Prior'\n}\n\n/**\n * Transform comparison data for 'separate' mode\n * Returns data with each row having its original measure values\n * Series are created per period (e.g., \"totalLinesOfCode (Current)\", \"totalLinesOfCode (Prior)\")\n */\nexport function transformForSeparateMode(\n data: any[],\n measures: string[],\n _timeDimensionKey: string\n): { data: any[], seriesKeys: string[] } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures }\n }\n\n const periodLabels = getPeriodLabels(data)\n const seriesKeys: string[] = []\n\n // Create series key for each measure + period combination\n for (const measure of measures) {\n for (let i = 0; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n const key = `${measure} (${shortLabel})`\n seriesKeys.push(key)\n }\n }\n\n // Data already has period info, just return as-is for separate mode\n // The chart will group by time dimension and show multiple lines\n return { data, seriesKeys }\n}\n\n/**\n * Detect dimension fields in comparison data\n * Returns fields that are not measures, time dimension, or metadata fields\n */\nfunction detectDimensionFields(\n data: any[],\n measures: string[],\n timeDimensionKey: string\n): string[] {\n if (data.length === 0) return []\n\n const metadataFields = ['__period', '__periodIndex', '__periodDayIndex']\n const firstRow = data[0]\n const dimensions: string[] = []\n\n for (const key of Object.keys(firstRow)) {\n if (\n !measures.includes(key) &&\n key !== timeDimensionKey &&\n !metadataFields.includes(key)\n ) {\n dimensions.push(key)\n }\n }\n\n return dimensions\n}\n\n/**\n * Get unique dimension values from data for a set of dimension fields\n */\nfunction getUniqueDimensionValues(\n data: any[],\n dimensionFields: string[]\n): Map<string, Set<any>> {\n const values = new Map<string, Set<any>>()\n\n for (const field of dimensionFields) {\n values.set(field, new Set())\n }\n\n for (const row of data) {\n for (const field of dimensionFields) {\n if (row[field] !== undefined && row[field] !== null) {\n values.get(field)!.add(row[field])\n }\n }\n }\n\n return values\n}\n\n/**\n * Transform comparison data for 'overlay' mode\n * Pivots data so each row represents a day-of-period index,\n * with separate columns for each period's values.\n *\n * When dimensions are present, creates series keys that include\n * dimension values: \"Engineering - Total Lines of Code (Current)\"\n *\n * Input (without dimensions):\n * [\n * { date: '2024-01-01', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-02', value: 110, __periodIndex: 0, __periodDayIndex: 1 },\n * { date: '2023-01-01', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-02', value: 85, __periodIndex: 1, __periodDayIndex: 1 },\n * ]\n *\n * Output (without dimensions):\n * [\n * { __periodDayIndex: 0, 'value (Current)': 100, 'value (Prior)': 80 },\n * { __periodDayIndex: 1, 'value (Current)': 110, 'value (Prior)': 85 },\n * ]\n *\n * Input (with dimensions):\n * [\n * { date: '2024-01-01', 'Dept.name': 'Engineering', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-01', 'Dept.name': 'Sales', value: 50, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Engineering', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Sales', value: 40, __periodIndex: 1, __periodDayIndex: 0 },\n * ]\n *\n * Output (with dimensions):\n * [\n * {\n * __periodDayIndex: 0,\n * 'Engineering - value (Current)': 100,\n * 'Engineering - value (Prior)': 80,\n * 'Sales - value (Current)': 50,\n * 'Sales - value (Prior)': 40,\n * },\n * ]\n */\nexport function transformForOverlayMode(\n data: any[],\n measures: string[],\n timeDimensionKey: string,\n getFieldLabel?: (fieldName: string) => string\n): { data: any[], seriesKeys: string[], xAxisKey: string } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures, xAxisKey: timeDimensionKey }\n }\n\n const periodLabels = getPeriodLabels(data)\n const periodIndices = getPeriodIndices(data)\n\n // Detect dimension fields in the data\n const dimensionFields = detectDimensionFields(data, measures, timeDimensionKey)\n const hasDimensions = dimensionFields.length > 0\n\n // Get unique dimension values for generating series keys\n const uniqueDimensionValues = hasDimensions\n ? getUniqueDimensionValues(data, dimensionFields)\n : null\n\n // Group data by __periodDayIndex\n const groupedByDayIndex = new Map<number, Record<string, any>>()\n\n for (const row of data) {\n const dayIndex = row.__periodDayIndex\n const periodIndex = row.__periodIndex\n\n if (!groupedByDayIndex.has(dayIndex)) {\n groupedByDayIndex.set(dayIndex, {\n __periodDayIndex: dayIndex,\n // Store the date from the first period (index 0) for reference\n __displayDate: periodIndex === 0 ? row[timeDimensionKey] : undefined\n })\n }\n\n const groupedRow = groupedByDayIndex.get(dayIndex)!\n\n // If this is the first period and we don't have a display date yet, add it\n if (!groupedRow.__displayDate && row[timeDimensionKey]) {\n groupedRow.__displayDate = row[timeDimensionKey]\n }\n\n // Build dimension prefix if dimensions are present\n let dimensionPrefix = ''\n if (hasDimensions) {\n const dimensionValues = dimensionFields.map(field => {\n const value = row[field]\n return getFieldLabel ? getFieldLabel(String(value)) : String(value)\n })\n dimensionPrefix = dimensionValues.join(' / ')\n }\n\n // Add measure values with optional dimension prefix and period suffix\n const shortLabel = generatePeriodShortLabel(periodLabels[periodIndex] || '', periodIndex)\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n const key = dimensionPrefix\n ? `${dimensionPrefix} - ${displayName} (${shortLabel})`\n : `${displayName} (${shortLabel})`\n groupedRow[key] = row[measure]\n }\n }\n\n // Convert to array and sort by day index\n const transformedData = Array.from(groupedByDayIndex.values())\n .sort((a, b) => a.__periodDayIndex - b.__periodDayIndex)\n\n // Generate series keys (using display names to match the data keys)\n const seriesKeys: string[] = []\n\n if (hasDimensions && uniqueDimensionValues) {\n // Generate all combinations of dimension values\n const dimensionCombinations = generateDimensionCombinations(\n dimensionFields,\n uniqueDimensionValues,\n getFieldLabel\n )\n\n // For each dimension combination, create series keys for each measure + period\n for (const dimCombo of dimensionCombinations) {\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n for (let i = 0; i < periodIndices.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i] || '', i)\n seriesKeys.push(`${dimCombo} - ${displayName} (${shortLabel})`)\n }\n }\n }\n } else {\n // No dimensions - generate simple measure + period keys\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n for (let i = 0; i < periodIndices.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i] || '', i)\n seriesKeys.push(`${displayName} (${shortLabel})`)\n }\n }\n }\n\n return {\n data: transformedData,\n seriesKeys,\n xAxisKey: '__periodDayIndex'\n }\n}\n\n/**\n * Generate all combinations of dimension values as formatted strings\n */\nfunction generateDimensionCombinations(\n dimensionFields: string[],\n uniqueValues: Map<string, Set<any>>,\n getFieldLabel?: (fieldName: string) => string\n): string[] {\n if (dimensionFields.length === 0) return []\n\n // For single dimension, just return the values\n if (dimensionFields.length === 1) {\n const field = dimensionFields[0]\n const values = Array.from(uniqueValues.get(field) || [])\n return values.map(v => getFieldLabel ? getFieldLabel(String(v)) : String(v))\n }\n\n // For multiple dimensions, generate cartesian product\n const result: string[] = []\n const fieldValues = dimensionFields.map(field =>\n Array.from(uniqueValues.get(field) || [])\n )\n\n function generateCombos(index: number, current: string[]): void {\n if (index === fieldValues.length) {\n const formatted = current.map(v =>\n getFieldLabel ? getFieldLabel(String(v)) : String(v)\n )\n result.push(formatted.join(' / '))\n return\n }\n\n for (const value of fieldValues[index]) {\n generateCombos(index + 1, [...current, value])\n }\n }\n\n generateCombos(0, [])\n return result\n}\n\n/**\n * Format the period day index for display on X-axis\n * Can show as \"Day 1\", \"Day 2\", etc., or as the original date\n */\nexport function formatPeriodDayIndex(\n dayIndex: number,\n displayDate?: string | Date,\n options?: {\n showDayNumber?: boolean\n dateFormat?: 'short' | 'long'\n }\n): string {\n if (options?.showDayNumber) {\n return `Day ${dayIndex + 1}`\n }\n\n if (displayDate) {\n const date = typeof displayDate === 'string' ? new Date(displayDate) : displayDate\n if (!isNaN(date.getTime())) {\n return date.toLocaleDateString('en-US', {\n month: options?.dateFormat === 'long' ? 'long' : 'short',\n day: 'numeric'\n })\n }\n }\n\n return `${dayIndex + 1}`\n}\n\n/**\n * Check if a series key represents a prior period (not the first period)\n * Used for applying different styling to prior period lines\n */\nexport function isPriorPeriodSeries(seriesKey: string, periodLabels: string[]): boolean {\n if (periodLabels.length < 2) return false\n\n // Check if the series key contains any label other than the first period's\n for (let i = 1; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n if (seriesKey.includes(`(${shortLabel})`)) {\n return true\n }\n }\n\n // Also check for \"(Prior\" pattern\n return seriesKey.includes('(Prior')\n}\n\n/**\n * Get the stroke dash array for prior period styling\n */\nexport function getPriorPeriodStrokeDashArray(\n style: 'solid' | 'dashed' | 'dotted' = 'dashed'\n): string | undefined {\n switch (style) {\n case 'solid':\n return undefined\n case 'dashed':\n return '5 5'\n case 'dotted':\n return '2 2'\n default:\n return '5 5'\n }\n}\n","import React, { useState, useMemo } from 'react'\nimport { LineChart as RechartsLineChart, Line, XAxis, YAxis, CartesianGrid, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport AngledXAxisTick from './AngledXAxisTick'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, formatAxisValue, formatTimeValue, getFieldGranularity } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport {\n isComparisonData,\n getPeriodLabels,\n transformForOverlayMode,\n isPriorPeriodSeries,\n getPriorPeriodStrokeDashArray\n} from '../../utils/comparisonUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst LineChart = React.memo(function LineChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Extract Y-axis fields early for use in useMemo hooks\n // This ensures hooks are always called in the same order\n const yAxisFields = useMemo(() => {\n if (chartConfig?.yAxis) {\n return Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n }\n if (chartConfig?.y) {\n return Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n }\n return []\n }, [chartConfig?.yAxis, chartConfig?.y])\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig (memoized to prevent object recreation)\n // MUST be called before any early returns to satisfy React hooks rules\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Build mapping from series key (label) to original field name (memoized to prevent object recreation)\n // This is needed because seriesKeys use display labels, not field names\n // MUST be called before any early returns to satisfy React hooks rules\n const seriesKeyToField = useMemo(() => {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n mapping[label] = field\n })\n return mapping\n }, [yAxisFields, getFieldLabel])\n\n try {\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data available</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in line chart</div>\n </div>\n </div>\n )\n }\n\n // Validate chartConfig - support both legacy and new formats\n let xAxisField: string\n let seriesFields: string[] = []\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n } else {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Error</div>\n <div className=\"dc:text-xs\">Invalid or missing chart axis configuration</div>\n </div>\n </div>\n )\n }\n\n if (!xAxisField || yAxisFields.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Error</div>\n <div className=\"dc:text-xs\">Missing required X-axis or Y-axis fields</div>\n </div>\n </div>\n )\n }\n\n // Check if this is comparison data (has __periodIndex metadata)\n const hasComparisonData = isComparisonData(data)\n const priorPeriodStyle = displayConfig?.priorPeriodStyle || 'dashed'\n const priorPeriodOpacity = displayConfig?.priorPeriodOpacity ?? 0.5\n const periodLabels = hasComparisonData ? getPeriodLabels(data) : []\n\n // Transform data based on comparison mode\n let chartData: any[]\n let seriesKeys: string[]\n let effectiveXAxisKey = 'name' // Default X-axis key after transformation\n\n if (hasComparisonData) {\n // For comparison data, always use overlay transformation to align by period day index\n // Both 'separate' and 'overlay' modes use the same data transformation,\n // they differ only in styling (dashed lines, opacity for prior periods in overlay mode)\n const overlayResult = transformForOverlayMode(data, yAxisFields, xAxisField, getFieldLabel)\n chartData = overlayResult.data\n seriesKeys = overlayResult.seriesKeys\n effectiveXAxisKey = '__periodDayIndex'\n } else {\n // Standard mode: use normal transformation\n const standardResult = transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n chartData = standardResult.data\n seriesKeys = standardResult.seriesKeys\n }\n\n // Helper to find field from series key, handling comparison suffixes like \"(Current)\" and \"(Prior)\"\n const findFieldFromSeriesKey = (seriesKey: string): string | undefined => {\n // Direct match first\n if (seriesKeyToField[seriesKey]) {\n return seriesKeyToField[seriesKey]\n }\n // For comparison data, strip the period suffix and any dimension prefix\n // Series keys look like: \"Label (Current)\", \"Label (Prior)\", or \"DimValue - Label (Current)\"\n const withoutSuffix = seriesKey.replace(/\\s*\\((Current|Prior)\\)$/, '')\n // Check if it has a dimension prefix (contains \" - \")\n const parts = withoutSuffix.split(' - ')\n const measureLabel = parts[parts.length - 1] // Last part is the measure label\n return seriesKeyToField[measureLabel]\n }\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n\n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n\n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n\n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No valid data</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No valid data points for line chart after transformation</div>\n </div>\n </div>\n )\n }\n\n return (\n <ChartContainer height={height}>\n <RechartsLineChart data={enhancedChartData} margin={chartMargins} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && (\n <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />\n )}\n <XAxis\n dataKey={effectiveXAxisKey}\n type=\"category\"\n tick={<AngledXAxisTick tickFormatter={\n hasComparisonData\n ? (value: string | number, index: number) => {\n // For comparison data, show the date from the current period\n // formatted according to the query's granularity\n const row = chartData[index]\n if (row?.__displayDate) {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n return formatTimeValue(row.__displayDate, granularity)\n }\n return `Period ${Number(value) + 1}`\n }\n : undefined\n } />}\n height={60}\n />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={leftYAxisFormat ? (value) => formatAxisValue(value, leftYAxisFormat) : undefined}\n label={\n leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n\n // Determine which axis format to use based on series name\n const originalField = findFieldFromSeriesKey(name)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n // Series name is already formatted (e.g., \"Total Lines of Code (Current)\")\n return [formatAxisValue(value, formatConfig), name]\n }}\n labelFormatter={\n hasComparisonData\n ? (label: any, payload: any) => {\n // For comparison data, show the date from the current period\n // formatted according to the query's granularity\n if (payload && payload.length > 0) {\n const row = payload[0]?.payload\n if (row?.__displayDate) {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n return formatTimeValue(row.__displayDate, granularity)\n }\n }\n return `Period ${Number(label) + 1}`\n }\n : undefined\n }\n />\n )}\n {showLegend && (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: '25px' }}\n iconType=\"line\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = findFieldFromSeriesKey(seriesKey)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n\n // Determine if this is a prior period series (for styling)\n const isPriorPeriod = hasComparisonData && isPriorPeriodSeries(seriesKey, periodLabels)\n const strokeDashArray = isPriorPeriod ? getPriorPeriodStrokeDashArray(priorPeriodStyle) : undefined\n const opacity = isPriorPeriod ? priorPeriodOpacity : 1\n\n // When drill is enabled, show persistent dots for better click targets\n const lineColor = (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n\n return (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stroke={lineColor}\n strokeWidth={isPriorPeriod ? 1.5 : 2}\n strokeDasharray={strokeDashArray}\n dot={isPriorPeriod ? false : (props: any) => {\n const { cx, cy, payload, key } = props\n if (cx === undefined || cy === undefined) return null\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n event.preventDefault()\n if (onDataPointClick) {\n onDataPointClick({\n dataPoint: payload,\n clickedField: originalField || seriesKey,\n xValue: payload.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n // When drill is enabled, render clickable dots with background to mask grid\n if (drillEnabled && onDataPointClick) {\n return (\n <g key={key}>\n {/* Background to mask grid lines - uses theme surface color */}\n <circle\n cx={cx}\n cy={cy}\n r={6}\n fill=\"var(--dc-surface)\"\n style={{ pointerEvents: 'none' }}\n />\n {/* Visible dot with click handler */}\n <circle\n cx={cx}\n cy={cy}\n r={4}\n fill=\"var(--dc-surface)\"\n stroke={lineColor}\n strokeWidth={2}\n cursor=\"pointer\"\n onClick={(e: React.MouseEvent<SVGCircleElement>) => {\n handleClick(e as unknown as React.MouseEvent)\n }}\n />\n </g>\n )\n }\n\n // Non-drill mode: simple small dot\n return (\n <circle\n key={key}\n cx={cx}\n cy={cy}\n r={3}\n fill={lineColor}\n />\n )\n }}\n activeDot={false}\n strokeOpacity={\n hoveredLegend\n ? (hoveredLegend === seriesKey ? 1 : 0.3)\n : opacity\n }\n connectNulls={safeDisplayConfig.connectNulls}\n />\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </RechartsLineChart>\n </ChartContainer>\n )\n } catch (error) {\n // 'LineChart rendering error\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Line Chart Error</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : 'Unknown rendering error'}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">Check the data and configuration</div>\n </div>\n </div>\n )\n }\n})\n\nexport default LineChart\n"],"names":["isComparisonData","data","getPeriodLabels","labels","row","getPeriodIndices","indices","a","b","generatePeriodShortLabel","_periodLabel","index","transformForSeparateMode","measures","_timeDimensionKey","periodLabels","seriesKeys","measure","shortLabel","key","detectDimensionFields","timeDimensionKey","metadataFields","firstRow","dimensions","getUniqueDimensionValues","dimensionFields","values","field","transformForOverlayMode","getFieldLabel","periodIndices","hasDimensions","uniqueDimensionValues","groupedByDayIndex","dayIndex","periodIndex","groupedRow","dimensionPrefix","value","displayName","transformedData","dimensionCombinations","generateDimensionCombinations","dimCombo","i","uniqueValues","v","result","fieldValues","generateCombos","current","formatted","formatPeriodDayIndex","displayDate","options","date","isPriorPeriodSeries","seriesKey","getPriorPeriodStrokeDashArray","style","LineChart","React","chartConfig","displayConfig","queryObject","height","colorPalette","onDataPointClick","drillEnabled","hoveredLegend","setHoveredLegend","useState","useCubeFieldLabel","yAxisFields","useMemo","yAxisAssignment","seriesKeyToField","mapping","label","safeDisplayConfig","leftYAxisFormat","rightYAxisFormat","jsx","jsxs","xAxisField","seriesFields","hasComparisonData","priorPeriodStyle","priorPeriodOpacity","chartData","effectiveXAxisKey","overlayResult","standardResult","transformChartDataWithSeries","findFieldFromSeriesKey","parts","measureLabel","hasRightAxis","leftAxisFields","f","rightAxisFields","showLegend","chartMargins","CHART_MARGINS","targetValues","parseTargetValues","spreadTargets","spreadTargetValues","enhancedChartData","dataPoint","ChartContainer","RechartsLineChart","CartesianGrid","XAxis","AngledXAxisTick","granularity","getFieldGranularity","formatTimeValue","YAxis","formatAxisValue","ChartTooltip","name","originalField","formatConfig","payload","Legend","o","axisId","isPriorPeriod","strokeDashArray","opacity","lineColor","CHART_COLORS","Line","props","cx","cy","handleClick","event","e","Fragment","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-line-zi6olZet.js","sources":["../../../src/client/utils/comparisonUtils.ts","../../../src/client/components/charts/LineChart.tsx"],"sourcesContent":["/**\n * Comparison Data Utilities\n * Handles period-over-period comparison data transformation for charts\n *\n * These utilities detect comparison query results (with __periodIndex metadata)\n * and transform them for visualization in either 'separate' or 'overlay' mode.\n */\n\n/**\n * Check if data contains comparison period metadata\n */\nexport function isComparisonData(data: any[]): boolean {\n return data.length > 0 && '__periodIndex' in data[0]\n}\n\n/**\n * Get unique period labels from comparison data\n */\nexport function getPeriodLabels(data: any[]): string[] {\n if (!isComparisonData(data)) return []\n\n const labels = new Set<string>()\n for (const row of data) {\n if (row.__period) {\n labels.add(row.__period)\n }\n }\n return Array.from(labels)\n}\n\n/**\n * Get period indices from comparison data\n */\nexport function getPeriodIndices(data: any[]): number[] {\n if (!isComparisonData(data)) return []\n\n const indices = new Set<number>()\n for (const row of data) {\n if (typeof row.__periodIndex === 'number') {\n indices.add(row.__periodIndex)\n }\n }\n return Array.from(indices).sort((a, b) => a - b)\n}\n\n/**\n * Generate a short label for a period (used in legends)\n * Uses simple \"Current\" / \"Prior\" labels for clarity\n */\nexport function generatePeriodShortLabel(_periodLabel: string, index: number): string {\n return index === 0 ? 'Current' : 'Prior'\n}\n\n/**\n * Transform comparison data for 'separate' mode\n * Returns data with each row having its original measure values\n * Series are created per period (e.g., \"totalLinesOfCode (Current)\", \"totalLinesOfCode (Prior)\")\n */\nexport function transformForSeparateMode(\n data: any[],\n measures: string[],\n _timeDimensionKey: string\n): { data: any[], seriesKeys: string[] } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures }\n }\n\n const periodLabels = getPeriodLabels(data)\n const seriesKeys: string[] = []\n\n // Create series key for each measure + period combination\n for (const measure of measures) {\n for (let i = 0; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n const key = `${measure} (${shortLabel})`\n seriesKeys.push(key)\n }\n }\n\n // Data already has period info, just return as-is for separate mode\n // The chart will group by time dimension and show multiple lines\n return { data, seriesKeys }\n}\n\n/**\n * Detect dimension fields in comparison data\n * Returns fields that are not measures, time dimension, or metadata fields\n */\nfunction detectDimensionFields(\n data: any[],\n measures: string[],\n timeDimensionKey: string\n): string[] {\n if (data.length === 0) return []\n\n const metadataFields = ['__period', '__periodIndex', '__periodDayIndex']\n const firstRow = data[0]\n const dimensions: string[] = []\n\n for (const key of Object.keys(firstRow)) {\n if (\n !measures.includes(key) &&\n key !== timeDimensionKey &&\n !metadataFields.includes(key)\n ) {\n dimensions.push(key)\n }\n }\n\n return dimensions\n}\n\n/**\n * Get unique dimension values from data for a set of dimension fields\n */\nfunction getUniqueDimensionValues(\n data: any[],\n dimensionFields: string[]\n): Map<string, Set<any>> {\n const values = new Map<string, Set<any>>()\n\n for (const field of dimensionFields) {\n values.set(field, new Set())\n }\n\n for (const row of data) {\n for (const field of dimensionFields) {\n if (row[field] !== undefined && row[field] !== null) {\n values.get(field)!.add(row[field])\n }\n }\n }\n\n return values\n}\n\n/**\n * Transform comparison data for 'overlay' mode\n * Pivots data so each row represents a day-of-period index,\n * with separate columns for each period's values.\n *\n * When dimensions are present, creates series keys that include\n * dimension values: \"Engineering - Total Lines of Code (Current)\"\n *\n * Input (without dimensions):\n * [\n * { date: '2024-01-01', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-02', value: 110, __periodIndex: 0, __periodDayIndex: 1 },\n * { date: '2023-01-01', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-02', value: 85, __periodIndex: 1, __periodDayIndex: 1 },\n * ]\n *\n * Output (without dimensions):\n * [\n * { __periodDayIndex: 0, 'value (Current)': 100, 'value (Prior)': 80 },\n * { __periodDayIndex: 1, 'value (Current)': 110, 'value (Prior)': 85 },\n * ]\n *\n * Input (with dimensions):\n * [\n * { date: '2024-01-01', 'Dept.name': 'Engineering', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-01', 'Dept.name': 'Sales', value: 50, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Engineering', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Sales', value: 40, __periodIndex: 1, __periodDayIndex: 0 },\n * ]\n *\n * Output (with dimensions):\n * [\n * {\n * __periodDayIndex: 0,\n * 'Engineering - value (Current)': 100,\n * 'Engineering - value (Prior)': 80,\n * 'Sales - value (Current)': 50,\n * 'Sales - value (Prior)': 40,\n * },\n * ]\n */\nexport function transformForOverlayMode(\n data: any[],\n measures: string[],\n timeDimensionKey: string,\n getFieldLabel?: (fieldName: string) => string\n): { data: any[], seriesKeys: string[], xAxisKey: string } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures, xAxisKey: timeDimensionKey }\n }\n\n const periodLabels = getPeriodLabels(data)\n const periodIndices = getPeriodIndices(data)\n\n // Detect dimension fields in the data\n const dimensionFields = detectDimensionFields(data, measures, timeDimensionKey)\n const hasDimensions = dimensionFields.length > 0\n\n // Get unique dimension values for generating series keys\n const uniqueDimensionValues = hasDimensions\n ? getUniqueDimensionValues(data, dimensionFields)\n : null\n\n // Group data by __periodDayIndex\n const groupedByDayIndex = new Map<number, Record<string, any>>()\n\n for (const row of data) {\n const dayIndex = row.__periodDayIndex\n const periodIndex = row.__periodIndex\n\n if (!groupedByDayIndex.has(dayIndex)) {\n groupedByDayIndex.set(dayIndex, {\n __periodDayIndex: dayIndex,\n // Store the date from the first period (index 0) for reference\n __displayDate: periodIndex === 0 ? row[timeDimensionKey] : undefined\n })\n }\n\n const groupedRow = groupedByDayIndex.get(dayIndex)!\n\n // If this is the first period and we don't have a display date yet, add it\n if (!groupedRow.__displayDate && row[timeDimensionKey]) {\n groupedRow.__displayDate = row[timeDimensionKey]\n }\n\n // Build dimension prefix if dimensions are present\n let dimensionPrefix = ''\n if (hasDimensions) {\n const dimensionValues = dimensionFields.map(field => {\n const value = row[field]\n return getFieldLabel ? getFieldLabel(String(value)) : String(value)\n })\n dimensionPrefix = dimensionValues.join(' / ')\n }\n\n // Add measure values with optional dimension prefix and period suffix\n const shortLabel = generatePeriodShortLabel(periodLabels[periodIndex] || '', periodIndex)\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n const key = dimensionPrefix\n ? `${dimensionPrefix} - ${displayName} (${shortLabel})`\n : `${displayName} (${shortLabel})`\n groupedRow[key] = row[measure]\n }\n }\n\n // Convert to array and sort by day index\n const transformedData = Array.from(groupedByDayIndex.values())\n .sort((a, b) => a.__periodDayIndex - b.__periodDayIndex)\n\n // Generate series keys (using display names to match the data keys)\n const seriesKeys: string[] = []\n\n if (hasDimensions && uniqueDimensionValues) {\n // Generate all combinations of dimension values\n const dimensionCombinations = generateDimensionCombinations(\n dimensionFields,\n uniqueDimensionValues,\n getFieldLabel\n )\n\n // For each dimension combination, create series keys for each measure + period\n for (const dimCombo of dimensionCombinations) {\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n for (let i = 0; i < periodIndices.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i] || '', i)\n seriesKeys.push(`${dimCombo} - ${displayName} (${shortLabel})`)\n }\n }\n }\n } else {\n // No dimensions - generate simple measure + period keys\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n for (let i = 0; i < periodIndices.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i] || '', i)\n seriesKeys.push(`${displayName} (${shortLabel})`)\n }\n }\n }\n\n return {\n data: transformedData,\n seriesKeys,\n xAxisKey: '__periodDayIndex'\n }\n}\n\n/**\n * Generate all combinations of dimension values as formatted strings\n */\nfunction generateDimensionCombinations(\n dimensionFields: string[],\n uniqueValues: Map<string, Set<any>>,\n getFieldLabel?: (fieldName: string) => string\n): string[] {\n if (dimensionFields.length === 0) return []\n\n // For single dimension, just return the values\n if (dimensionFields.length === 1) {\n const field = dimensionFields[0]\n const values = Array.from(uniqueValues.get(field) || [])\n return values.map(v => getFieldLabel ? getFieldLabel(String(v)) : String(v))\n }\n\n // For multiple dimensions, generate cartesian product\n const result: string[] = []\n const fieldValues = dimensionFields.map(field =>\n Array.from(uniqueValues.get(field) || [])\n )\n\n function generateCombos(index: number, current: string[]): void {\n if (index === fieldValues.length) {\n const formatted = current.map(v =>\n getFieldLabel ? getFieldLabel(String(v)) : String(v)\n )\n result.push(formatted.join(' / '))\n return\n }\n\n for (const value of fieldValues[index]) {\n generateCombos(index + 1, [...current, value])\n }\n }\n\n generateCombos(0, [])\n return result\n}\n\n/**\n * Format the period day index for display on X-axis\n * Can show as \"Day 1\", \"Day 2\", etc., or as the original date\n */\nexport function formatPeriodDayIndex(\n dayIndex: number,\n displayDate?: string | Date,\n options?: {\n showDayNumber?: boolean\n dateFormat?: 'short' | 'long'\n }\n): string {\n if (options?.showDayNumber) {\n return `Day ${dayIndex + 1}`\n }\n\n if (displayDate) {\n const date = typeof displayDate === 'string' ? new Date(displayDate) : displayDate\n if (!isNaN(date.getTime())) {\n return date.toLocaleDateString('en-US', {\n month: options?.dateFormat === 'long' ? 'long' : 'short',\n day: 'numeric'\n })\n }\n }\n\n return `${dayIndex + 1}`\n}\n\n/**\n * Check if a series key represents a prior period (not the first period)\n * Used for applying different styling to prior period lines\n */\nexport function isPriorPeriodSeries(seriesKey: string, periodLabels: string[]): boolean {\n if (periodLabels.length < 2) return false\n\n // Check if the series key contains any label other than the first period's\n for (let i = 1; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n if (seriesKey.includes(`(${shortLabel})`)) {\n return true\n }\n }\n\n // Also check for \"(Prior\" pattern\n return seriesKey.includes('(Prior')\n}\n\n/**\n * Get the stroke dash array for prior period styling\n */\nexport function getPriorPeriodStrokeDashArray(\n style: 'solid' | 'dashed' | 'dotted' = 'dashed'\n): string | undefined {\n switch (style) {\n case 'solid':\n return undefined\n case 'dashed':\n return '5 5'\n case 'dotted':\n return '2 2'\n default:\n return '5 5'\n }\n}\n","import React, { useState, useMemo } from 'react'\nimport { LineChart as RechartsLineChart, Line, XAxis, YAxis, CartesianGrid, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport AngledXAxisTick from './AngledXAxisTick'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, formatAxisValue, formatTimeValue, getFieldGranularity } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport {\n isComparisonData,\n getPeriodLabels,\n transformForOverlayMode,\n isPriorPeriodSeries,\n getPriorPeriodStrokeDashArray\n} from '../../utils/comparisonUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst LineChart = React.memo(function LineChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Extract Y-axis fields early for use in useMemo hooks\n // This ensures hooks are always called in the same order\n const yAxisFields = useMemo(() => {\n if (chartConfig?.yAxis) {\n return Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n }\n if (chartConfig?.y) {\n return Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n }\n return []\n }, [chartConfig?.yAxis, chartConfig?.y])\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig (memoized to prevent object recreation)\n // MUST be called before any early returns to satisfy React hooks rules\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Build mapping from series key (label) to original field name (memoized to prevent object recreation)\n // This is needed because seriesKeys use display labels, not field names\n // MUST be called before any early returns to satisfy React hooks rules\n const seriesKeyToField = useMemo(() => {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n mapping[label] = field\n })\n return mapping\n }, [yAxisFields, getFieldLabel])\n\n try {\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data available</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in line chart</div>\n </div>\n </div>\n )\n }\n\n // Validate chartConfig - support both legacy and new formats\n let xAxisField: string\n let seriesFields: string[] = []\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n } else {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Error</div>\n <div className=\"dc:text-xs\">Invalid or missing chart axis configuration</div>\n </div>\n </div>\n )\n }\n\n if (!xAxisField || yAxisFields.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Error</div>\n <div className=\"dc:text-xs\">Missing required X-axis or Y-axis fields</div>\n </div>\n </div>\n )\n }\n\n // Check if this is comparison data (has __periodIndex metadata)\n const hasComparisonData = isComparisonData(data)\n const priorPeriodStyle = displayConfig?.priorPeriodStyle || 'dashed'\n const priorPeriodOpacity = displayConfig?.priorPeriodOpacity ?? 0.5\n const periodLabels = hasComparisonData ? getPeriodLabels(data) : []\n\n // Transform data based on comparison mode\n let chartData: any[]\n let seriesKeys: string[]\n let effectiveXAxisKey = 'name' // Default X-axis key after transformation\n\n if (hasComparisonData) {\n // For comparison data, always use overlay transformation to align by period day index\n // Both 'separate' and 'overlay' modes use the same data transformation,\n // they differ only in styling (dashed lines, opacity for prior periods in overlay mode)\n const overlayResult = transformForOverlayMode(data, yAxisFields, xAxisField, getFieldLabel)\n chartData = overlayResult.data\n seriesKeys = overlayResult.seriesKeys\n effectiveXAxisKey = '__periodDayIndex'\n } else {\n // Standard mode: use normal transformation\n const standardResult = transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n chartData = standardResult.data\n seriesKeys = standardResult.seriesKeys\n }\n\n // Helper to find field from series key, handling comparison suffixes like \"(Current)\" and \"(Prior)\"\n const findFieldFromSeriesKey = (seriesKey: string): string | undefined => {\n // Direct match first\n if (seriesKeyToField[seriesKey]) {\n return seriesKeyToField[seriesKey]\n }\n // For comparison data, strip the period suffix and any dimension prefix\n // Series keys look like: \"Label (Current)\", \"Label (Prior)\", or \"DimValue - Label (Current)\"\n const withoutSuffix = seriesKey.replace(/\\s*\\((Current|Prior)\\)$/, '')\n // Check if it has a dimension prefix (contains \" - \")\n const parts = withoutSuffix.split(' - ')\n const measureLabel = parts[parts.length - 1] // Last part is the measure label\n return seriesKeyToField[measureLabel]\n }\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n\n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n\n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n\n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No valid data</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No valid data points for line chart after transformation</div>\n </div>\n </div>\n )\n }\n\n return (\n <ChartContainer height={height}>\n <RechartsLineChart data={enhancedChartData} margin={chartMargins} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && (\n <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />\n )}\n <XAxis\n dataKey={effectiveXAxisKey}\n type=\"category\"\n tick={<AngledXAxisTick tickFormatter={\n hasComparisonData\n ? (value: string | number, index: number) => {\n // For comparison data, show the date from the current period\n // formatted according to the query's granularity\n const row = chartData[index]\n if (row?.__displayDate) {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n return formatTimeValue(row.__displayDate, granularity)\n }\n return `Period ${Number(value) + 1}`\n }\n : undefined\n } />}\n height={60}\n />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={leftYAxisFormat ? (value) => formatAxisValue(value, leftYAxisFormat) : undefined}\n label={\n leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n\n // Determine which axis format to use based on series name\n const originalField = findFieldFromSeriesKey(name)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n // Series name is already formatted (e.g., \"Total Lines of Code (Current)\")\n return [formatAxisValue(value, formatConfig), name]\n }}\n labelFormatter={\n hasComparisonData\n ? (label: any, payload: any) => {\n // For comparison data, show the date from the current period\n // formatted according to the query's granularity\n if (payload && payload.length > 0) {\n const row = payload[0]?.payload\n if (row?.__displayDate) {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n return formatTimeValue(row.__displayDate, granularity)\n }\n }\n return `Period ${Number(label) + 1}`\n }\n : undefined\n }\n />\n )}\n {showLegend && (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: '25px' }}\n iconType=\"line\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = findFieldFromSeriesKey(seriesKey)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n\n // Determine if this is a prior period series (for styling)\n const isPriorPeriod = hasComparisonData && isPriorPeriodSeries(seriesKey, periodLabels)\n const strokeDashArray = isPriorPeriod ? getPriorPeriodStrokeDashArray(priorPeriodStyle) : undefined\n const opacity = isPriorPeriod ? priorPeriodOpacity : 1\n\n // When drill is enabled, show persistent dots for better click targets\n const lineColor = (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n\n return (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stroke={lineColor}\n strokeWidth={isPriorPeriod ? 1.5 : 2}\n strokeDasharray={strokeDashArray}\n dot={isPriorPeriod ? false : (props: any) => {\n const { cx, cy, payload, key } = props\n if (cx === undefined || cy === undefined) return null\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n event.preventDefault()\n if (onDataPointClick) {\n onDataPointClick({\n dataPoint: payload,\n clickedField: originalField || seriesKey,\n xValue: payload.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n // When drill is enabled, render clickable dots with background to mask grid\n if (drillEnabled && onDataPointClick) {\n return (\n <g key={key}>\n {/* Background to mask grid lines - uses theme surface color */}\n <circle\n cx={cx}\n cy={cy}\n r={6}\n fill=\"var(--dc-surface)\"\n style={{ pointerEvents: 'none' }}\n />\n {/* Visible dot with click handler */}\n <circle\n cx={cx}\n cy={cy}\n r={4}\n fill=\"var(--dc-surface)\"\n stroke={lineColor}\n strokeWidth={2}\n cursor=\"pointer\"\n onClick={(e: React.MouseEvent<SVGCircleElement>) => {\n handleClick(e as unknown as React.MouseEvent)\n }}\n />\n </g>\n )\n }\n\n // Non-drill mode: simple small dot\n return (\n <circle\n key={key}\n cx={cx}\n cy={cy}\n r={3}\n fill={lineColor}\n />\n )\n }}\n activeDot={false}\n strokeOpacity={\n hoveredLegend\n ? (hoveredLegend === seriesKey ? 1 : 0.3)\n : opacity\n }\n connectNulls={safeDisplayConfig.connectNulls}\n />\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </RechartsLineChart>\n </ChartContainer>\n )\n } catch (error) {\n // 'LineChart rendering error\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Line Chart Error</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : 'Unknown rendering error'}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">Check the data and configuration</div>\n </div>\n </div>\n )\n }\n})\n\nexport default LineChart\n"],"names":["isComparisonData","data","getPeriodLabels","labels","row","getPeriodIndices","indices","a","b","generatePeriodShortLabel","_periodLabel","index","transformForSeparateMode","measures","_timeDimensionKey","periodLabels","seriesKeys","measure","shortLabel","key","detectDimensionFields","timeDimensionKey","metadataFields","firstRow","dimensions","getUniqueDimensionValues","dimensionFields","values","field","transformForOverlayMode","getFieldLabel","periodIndices","hasDimensions","uniqueDimensionValues","groupedByDayIndex","dayIndex","periodIndex","groupedRow","dimensionPrefix","value","displayName","transformedData","dimensionCombinations","generateDimensionCombinations","dimCombo","i","uniqueValues","v","result","fieldValues","generateCombos","current","formatted","formatPeriodDayIndex","displayDate","options","date","isPriorPeriodSeries","seriesKey","getPriorPeriodStrokeDashArray","style","LineChart","React","chartConfig","displayConfig","queryObject","height","colorPalette","onDataPointClick","drillEnabled","hoveredLegend","setHoveredLegend","useState","useCubeFieldLabel","yAxisFields","useMemo","yAxisAssignment","seriesKeyToField","mapping","label","safeDisplayConfig","leftYAxisFormat","rightYAxisFormat","jsx","jsxs","xAxisField","seriesFields","hasComparisonData","priorPeriodStyle","priorPeriodOpacity","chartData","effectiveXAxisKey","overlayResult","standardResult","transformChartDataWithSeries","findFieldFromSeriesKey","parts","measureLabel","hasRightAxis","leftAxisFields","f","rightAxisFields","showLegend","chartMargins","CHART_MARGINS","targetValues","parseTargetValues","spreadTargets","spreadTargetValues","enhancedChartData","dataPoint","ChartContainer","RechartsLineChart","CartesianGrid","XAxis","AngledXAxisTick","granularity","getFieldGranularity","formatTimeValue","YAxis","formatAxisValue","ChartTooltip","name","originalField","formatConfig","payload","Legend","o","axisId","isPriorPeriod","strokeDashArray","opacity","lineColor","CHART_COLORS","Line","props","cx","cy","handleClick","event","e","Fragment","error"],"mappings":"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"}
|
|
@@ -135,9 +135,9 @@ const m = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set(), f = {
|
|
|
135
135
|
}
|
|
136
136
|
// Charts with no external deps: table, activityGrid, kpiNumber, kpiDelta, kpiText, markdown, retentionHeatmap, boxPlot
|
|
137
137
|
}, o = {
|
|
138
|
-
bar: () => import("./chart-bar-
|
|
139
|
-
line: () => import("./chart-line-
|
|
140
|
-
area: () => import("./chart-area-
|
|
138
|
+
bar: () => import("./chart-bar-Blypx8O4.js").then((a) => a.a),
|
|
139
|
+
line: () => import("./chart-line-zi6olZet.js").then((a) => a.h),
|
|
140
|
+
area: () => import("./chart-area-BJAgusst.js"),
|
|
141
141
|
pie: () => import("./chart-pie-C4SuxKSN.js"),
|
|
142
142
|
scatter: () => import("./chart-scatter-DOVu1TNq.js"),
|
|
143
143
|
radar: () => import("./chart-radar-BW3Z_-Ly.js"),
|
|
@@ -239,4 +239,4 @@ export {
|
|
|
239
239
|
v as i,
|
|
240
240
|
k as p
|
|
241
241
|
};
|
|
242
|
-
//# sourceMappingURL=charts-loader-
|
|
242
|
+
//# sourceMappingURL=charts-loader-CH0_S06T.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"charts-loader-HYQFVOo4.js","sources":["../../../src/client/components/charts/MissingDependencyFallback.tsx","../../../src/client/charts/ChartLoader.tsx"],"sourcesContent":["interface MissingDependencyFallbackProps {\n chartType: string\n packageName: string\n installCommand: string\n height?: string | number\n}\n\n/**\n * Fallback component shown when a chart's optional dependency is not installed.\n * Provides clear instructions on how to install the missing package.\n */\nexport function MissingDependencyFallback({\n chartType,\n packageName,\n installCommand,\n height = 200\n}: MissingDependencyFallbackProps) {\n return (\n <div\n className=\"dc-missing-dependency-fallback\"\n style={{\n height: typeof height === 'number' ? `${height}px` : height,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n padding: '1.5rem',\n textAlign: 'center',\n border: '1px dashed var(--dc-border, #e5e7eb)',\n borderRadius: '0.5rem',\n backgroundColor: 'var(--dc-surface, #f9fafb)'\n }}\n >\n <div style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>📦</div>\n <h3 style={{\n fontSize: '1.125rem',\n fontWeight: 600,\n marginBottom: '0.5rem',\n color: 'var(--dc-text, #111827)'\n }}>\n Missing Dependency\n </h3>\n <p style={{\n fontSize: '0.875rem',\n color: 'var(--dc-text-secondary, #6b7280)',\n marginBottom: '1rem',\n maxWidth: '28rem'\n }}>\n The <code style={{\n padding: '0.125rem 0.375rem',\n backgroundColor: 'var(--dc-surface-secondary, #f3f4f6)',\n borderRadius: '0.25rem',\n fontFamily: 'monospace',\n fontSize: '0.75rem'\n }}>{chartType}</code> chart requires the <code style={{\n padding: '0.125rem 0.375rem',\n backgroundColor: 'var(--dc-surface-secondary, #f3f4f6)',\n borderRadius: '0.25rem',\n fontFamily: 'monospace',\n fontSize: '0.75rem'\n }}>{packageName}</code> package.\n </p>\n <div style={{\n backgroundColor: 'var(--dc-surface-secondary, #f3f4f6)',\n borderRadius: '0.5rem',\n padding: '0.75rem 1rem',\n fontFamily: 'monospace',\n fontSize: '0.875rem',\n color: 'var(--dc-text, #111827)'\n }}>\n <span style={{\n color: 'var(--dc-text-muted, #9ca3af)',\n userSelect: 'none'\n }}>$ </span>\n {installCommand}\n </div>\n <p style={{\n fontSize: '0.75rem',\n color: 'var(--dc-text-muted, #9ca3af)',\n marginTop: '0.75rem'\n }}>\n After installing, restart your development server.\n </p>\n </div>\n )\n}\n","/**\n * Lazy Chart Loader\n *\n * Provides React.lazy-based dynamic loading for chart components.\n * This enables code splitting - each chart type loads only when needed.\n *\n * Handles missing optional dependencies gracefully by showing a fallback\n * component instead of crashing the application.\n */\n\nimport { lazy, Suspense, ComponentType, ReactNode, LazyExoticComponent } from 'react'\nimport type { ChartType, ChartProps } from '../types'\nimport { MissingDependencyFallback } from '../components/charts/MissingDependencyFallback'\n\n// Type for lazy-loaded chart components\ntype LazyChartComponent = ComponentType<ChartProps>\n\n// Chart loader cache to prevent re-creating lazy components\nconst chartLoaderCache = new Map<ChartType, LazyExoticComponent<LazyChartComponent>>()\n\n// Track which chart types have failed to load due to missing dependencies\nconst failedChartTypes = new Set<ChartType>()\n\n/**\n * Maps chart types to their optional peer dependencies.\n * Charts not listed here have no external dependencies (table, KPIs, markdown).\n */\nconst chartDependencyMap: Partial<Record<ChartType, { packageName: string; installCommand: string }>> = {\n // Recharts-based charts\n bar: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n line: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n area: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n pie: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n scatter: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n radar: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n radialBar: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n treemap: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n bubble: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n funnel: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n sankey: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n sunburst: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n // Nivo-based charts\n heatmap: {\n packageName: '@nivo/heatmap',\n installCommand: 'npm install @nivo/heatmap'\n }\n // Charts with no external deps: table, activityGrid, kpiNumber, kpiDelta, kpiText, markdown, retentionHeatmap, boxPlot\n}\n\n// Dynamic import functions for each chart type\nconst chartImportMap: Record<ChartType, () => Promise<{ default: LazyChartComponent }>> = {\n bar: () => import('../components/charts/BarChart'),\n line: () => import('../components/charts/LineChart'),\n area: () => import('../components/charts/AreaChart'),\n pie: () => import('../components/charts/PieChart'),\n scatter: () => import('../components/charts/ScatterChart'),\n radar: () => import('../components/charts/RadarChart'),\n radialBar: () => import('../components/charts/RadialBarChart'),\n treemap: () => import('../components/charts/TreeMapChart'),\n bubble: () => import('../components/charts/BubbleChart'),\n table: () => import('../components/charts/DataTable'),\n activityGrid: () => import('../components/charts/ActivityGridChart'),\n kpiNumber: () => import('../components/charts/KpiNumber'),\n kpiDelta: () => import('../components/charts/KpiDelta'),\n kpiText: () => import('../components/charts/KpiText'),\n markdown: () => import('../components/charts/MarkdownChart'),\n funnel: () => import('../components/charts/FunnelChart'),\n sankey: () => import('../components/charts/SankeyChart'),\n sunburst: () => import('../components/charts/SunburstChart'),\n heatmap: () => import('../components/charts/HeatMapChart'),\n retentionHeatmap: () => import('../components/charts/RetentionHeatmap'),\n retentionCombined: () => import('../components/charts/RetentionCombinedChart'),\n boxPlot: () => import('../components/charts/BoxPlotChart'),\n}\n\n/**\n * Creates a fallback component for a chart type with missing dependencies.\n */\nfunction createFallbackComponent(chartType: ChartType): LazyChartComponent {\n const depInfo = chartDependencyMap[chartType]\n\n const FallbackComponent: LazyChartComponent = ({ height }) => (\n <MissingDependencyFallback\n chartType={chartType}\n packageName={depInfo?.packageName || 'unknown'}\n installCommand={depInfo?.installCommand || `npm install [package-name]`}\n height={height}\n />\n )\n\n FallbackComponent.displayName = `${chartType}Fallback`\n return FallbackComponent\n}\n\n/**\n * Wraps a chart import function with error handling.\n * If the import fails (e.g., missing dependency), returns a fallback component.\n */\nfunction createSafeImport(\n chartType: ChartType,\n importFn: () => Promise<{ default: LazyChartComponent }>\n): () => Promise<{ default: LazyChartComponent }> {\n return async () => {\n try {\n return await importFn()\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `[drizzle-cube] Failed to load ${chartType} chart:`,\n error instanceof Error ? error.message : error\n )\n\n // Track that this chart type failed\n failedChartTypes.add(chartType)\n\n // Return the fallback component wrapped in the expected format\n return { default: createFallbackComponent(chartType) }\n }\n }\n}\n\n/**\n * Get or create a lazy component for a chart type.\n * Handles import failures gracefully by returning a fallback component.\n */\nfunction getLazyChart(chartType: ChartType): LazyExoticComponent<LazyChartComponent> {\n if (!chartLoaderCache.has(chartType)) {\n const importFn = chartImportMap[chartType]\n if (!importFn) {\n throw new Error(`Unknown chart type: ${chartType}`)\n }\n // Wrap the import with error handling for graceful degradation\n const safeImport = createSafeImport(chartType, importFn)\n chartLoaderCache.set(chartType, lazy(safeImport))\n }\n return chartLoaderCache.get(chartType)!\n}\n\n/**\n * Check if a chart type is supported\n */\nexport function isValidChartType(chartType: string): chartType is ChartType {\n return chartType in chartImportMap\n}\n\n// Props for the LazyChart wrapper\nexport interface LazyChartProps extends ChartProps {\n chartType: ChartType\n fallback?: ReactNode\n}\n\n/**\n * Default loading placeholder for charts\n */\nfunction DefaultChartFallback({ height }: { height?: string | number }) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height: typeof height === 'number' ? `${height}px` : height || '200px' }}\n >\n <div className=\"dc:animate-pulse bg-dc-surface-secondary dc:rounded dc:w-full dc:h-full dc:min-h-[100px]\" />\n </div>\n )\n}\n\n/**\n * Lazy Chart Component\n *\n * Renders a chart component with React.lazy dynamic loading.\n * The chart type determines which chart component is loaded.\n *\n * @example\n * ```tsx\n * <LazyChart\n * chartType=\"bar\"\n * data={chartData}\n * chartConfig={{ yAxis: ['value'] }}\n * height={300}\n * />\n * ```\n */\nexport function LazyChart({\n chartType,\n fallback,\n height,\n ...chartProps\n}: LazyChartProps) {\n const ChartComponent = getLazyChart(chartType)\n\n return (\n <Suspense fallback={fallback ?? <DefaultChartFallback height={height} />}>\n <ChartComponent height={height} {...chartProps} />\n </Suspense>\n )\n}\n\n/**\n * Preload a chart type\n *\n * Triggers the dynamic import without rendering.\n * Useful for prefetching charts that will likely be needed.\n *\n * @example\n * ```tsx\n * // Preload bar chart on hover\n * onMouseEnter={() => preloadChart('bar')}\n * ```\n */\nexport function preloadChart(chartType: ChartType): void {\n const importFn = chartImportMap[chartType]\n if (importFn) {\n importFn()\n }\n}\n\n/**\n * Preload multiple chart types\n *\n * @example\n * ```tsx\n * // Preload common charts on app init\n * useEffect(() => {\n * preloadCharts(['bar', 'line', 'pie'])\n * }, [])\n * ```\n */\nexport function preloadCharts(chartTypes: ChartType[]): void {\n chartTypes.forEach(preloadChart)\n}\n\n/**\n * Get all available chart types\n */\nexport function getAvailableChartTypes(): ChartType[] {\n return Object.keys(chartImportMap) as ChartType[]\n}\n\n/**\n * Check if a chart type has loaded successfully.\n * Returns false if the chart failed to load due to missing dependencies.\n *\n * Note: This only returns accurate results after the chart has been attempted to load.\n * Use this for conditional UI logic (e.g., hiding unavailable chart types).\n */\nexport function isChartTypeAvailable(chartType: ChartType): boolean {\n return !failedChartTypes.has(chartType)\n}\n\n/**\n * Get list of chart types that failed to load due to missing dependencies.\n */\nexport function getUnavailableChartTypes(): ChartType[] {\n return Array.from(failedChartTypes)\n}\n"],"names":["MissingDependencyFallback","chartType","packageName","installCommand","height","jsxs","jsx","chartLoaderCache","failedChartTypes","chartDependencyMap","chartImportMap","n","createFallbackComponent","depInfo","FallbackComponent","createSafeImport","importFn","error","getLazyChart","safeImport","lazy","isValidChartType","DefaultChartFallback","LazyChart","fallback","chartProps","ChartComponent","Suspense","preloadChart","preloadCharts","chartTypes","getAvailableChartTypes","isChartTypeAvailable","getUnavailableChartTypes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"charts-loader-CH0_S06T.js","sources":["../../../src/client/components/charts/MissingDependencyFallback.tsx","../../../src/client/charts/ChartLoader.tsx"],"sourcesContent":["interface MissingDependencyFallbackProps {\n chartType: string\n packageName: string\n installCommand: string\n height?: string | number\n}\n\n/**\n * Fallback component shown when a chart's optional dependency is not installed.\n * Provides clear instructions on how to install the missing package.\n */\nexport function MissingDependencyFallback({\n chartType,\n packageName,\n installCommand,\n height = 200\n}: MissingDependencyFallbackProps) {\n return (\n <div\n className=\"dc-missing-dependency-fallback\"\n style={{\n height: typeof height === 'number' ? `${height}px` : height,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n padding: '1.5rem',\n textAlign: 'center',\n border: '1px dashed var(--dc-border, #e5e7eb)',\n borderRadius: '0.5rem',\n backgroundColor: 'var(--dc-surface, #f9fafb)'\n }}\n >\n <div style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>📦</div>\n <h3 style={{\n fontSize: '1.125rem',\n fontWeight: 600,\n marginBottom: '0.5rem',\n color: 'var(--dc-text, #111827)'\n }}>\n Missing Dependency\n </h3>\n <p style={{\n fontSize: '0.875rem',\n color: 'var(--dc-text-secondary, #6b7280)',\n marginBottom: '1rem',\n maxWidth: '28rem'\n }}>\n The <code style={{\n padding: '0.125rem 0.375rem',\n backgroundColor: 'var(--dc-surface-secondary, #f3f4f6)',\n borderRadius: '0.25rem',\n fontFamily: 'monospace',\n fontSize: '0.75rem'\n }}>{chartType}</code> chart requires the <code style={{\n padding: '0.125rem 0.375rem',\n backgroundColor: 'var(--dc-surface-secondary, #f3f4f6)',\n borderRadius: '0.25rem',\n fontFamily: 'monospace',\n fontSize: '0.75rem'\n }}>{packageName}</code> package.\n </p>\n <div style={{\n backgroundColor: 'var(--dc-surface-secondary, #f3f4f6)',\n borderRadius: '0.5rem',\n padding: '0.75rem 1rem',\n fontFamily: 'monospace',\n fontSize: '0.875rem',\n color: 'var(--dc-text, #111827)'\n }}>\n <span style={{\n color: 'var(--dc-text-muted, #9ca3af)',\n userSelect: 'none'\n }}>$ </span>\n {installCommand}\n </div>\n <p style={{\n fontSize: '0.75rem',\n color: 'var(--dc-text-muted, #9ca3af)',\n marginTop: '0.75rem'\n }}>\n After installing, restart your development server.\n </p>\n </div>\n )\n}\n","/**\n * Lazy Chart Loader\n *\n * Provides React.lazy-based dynamic loading for chart components.\n * This enables code splitting - each chart type loads only when needed.\n *\n * Handles missing optional dependencies gracefully by showing a fallback\n * component instead of crashing the application.\n */\n\nimport { lazy, Suspense, ComponentType, ReactNode, LazyExoticComponent } from 'react'\nimport type { ChartType, ChartProps } from '../types'\nimport { MissingDependencyFallback } from '../components/charts/MissingDependencyFallback'\n\n// Type for lazy-loaded chart components\ntype LazyChartComponent = ComponentType<ChartProps>\n\n// Chart loader cache to prevent re-creating lazy components\nconst chartLoaderCache = new Map<ChartType, LazyExoticComponent<LazyChartComponent>>()\n\n// Track which chart types have failed to load due to missing dependencies\nconst failedChartTypes = new Set<ChartType>()\n\n/**\n * Maps chart types to their optional peer dependencies.\n * Charts not listed here have no external dependencies (table, KPIs, markdown).\n */\nconst chartDependencyMap: Partial<Record<ChartType, { packageName: string; installCommand: string }>> = {\n // Recharts-based charts\n bar: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n line: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n area: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n pie: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n scatter: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n radar: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n radialBar: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n treemap: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n bubble: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n funnel: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n sankey: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n sunburst: {\n packageName: 'recharts',\n installCommand: 'npm install recharts'\n },\n // Nivo-based charts\n heatmap: {\n packageName: '@nivo/heatmap',\n installCommand: 'npm install @nivo/heatmap'\n }\n // Charts with no external deps: table, activityGrid, kpiNumber, kpiDelta, kpiText, markdown, retentionHeatmap, boxPlot\n}\n\n// Dynamic import functions for each chart type\nconst chartImportMap: Record<ChartType, () => Promise<{ default: LazyChartComponent }>> = {\n bar: () => import('../components/charts/BarChart'),\n line: () => import('../components/charts/LineChart'),\n area: () => import('../components/charts/AreaChart'),\n pie: () => import('../components/charts/PieChart'),\n scatter: () => import('../components/charts/ScatterChart'),\n radar: () => import('../components/charts/RadarChart'),\n radialBar: () => import('../components/charts/RadialBarChart'),\n treemap: () => import('../components/charts/TreeMapChart'),\n bubble: () => import('../components/charts/BubbleChart'),\n table: () => import('../components/charts/DataTable'),\n activityGrid: () => import('../components/charts/ActivityGridChart'),\n kpiNumber: () => import('../components/charts/KpiNumber'),\n kpiDelta: () => import('../components/charts/KpiDelta'),\n kpiText: () => import('../components/charts/KpiText'),\n markdown: () => import('../components/charts/MarkdownChart'),\n funnel: () => import('../components/charts/FunnelChart'),\n sankey: () => import('../components/charts/SankeyChart'),\n sunburst: () => import('../components/charts/SunburstChart'),\n heatmap: () => import('../components/charts/HeatMapChart'),\n retentionHeatmap: () => import('../components/charts/RetentionHeatmap'),\n retentionCombined: () => import('../components/charts/RetentionCombinedChart'),\n boxPlot: () => import('../components/charts/BoxPlotChart'),\n}\n\n/**\n * Creates a fallback component for a chart type with missing dependencies.\n */\nfunction createFallbackComponent(chartType: ChartType): LazyChartComponent {\n const depInfo = chartDependencyMap[chartType]\n\n const FallbackComponent: LazyChartComponent = ({ height }) => (\n <MissingDependencyFallback\n chartType={chartType}\n packageName={depInfo?.packageName || 'unknown'}\n installCommand={depInfo?.installCommand || `npm install [package-name]`}\n height={height}\n />\n )\n\n FallbackComponent.displayName = `${chartType}Fallback`\n return FallbackComponent\n}\n\n/**\n * Wraps a chart import function with error handling.\n * If the import fails (e.g., missing dependency), returns a fallback component.\n */\nfunction createSafeImport(\n chartType: ChartType,\n importFn: () => Promise<{ default: LazyChartComponent }>\n): () => Promise<{ default: LazyChartComponent }> {\n return async () => {\n try {\n return await importFn()\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `[drizzle-cube] Failed to load ${chartType} chart:`,\n error instanceof Error ? error.message : error\n )\n\n // Track that this chart type failed\n failedChartTypes.add(chartType)\n\n // Return the fallback component wrapped in the expected format\n return { default: createFallbackComponent(chartType) }\n }\n }\n}\n\n/**\n * Get or create a lazy component for a chart type.\n * Handles import failures gracefully by returning a fallback component.\n */\nfunction getLazyChart(chartType: ChartType): LazyExoticComponent<LazyChartComponent> {\n if (!chartLoaderCache.has(chartType)) {\n const importFn = chartImportMap[chartType]\n if (!importFn) {\n throw new Error(`Unknown chart type: ${chartType}`)\n }\n // Wrap the import with error handling for graceful degradation\n const safeImport = createSafeImport(chartType, importFn)\n chartLoaderCache.set(chartType, lazy(safeImport))\n }\n return chartLoaderCache.get(chartType)!\n}\n\n/**\n * Check if a chart type is supported\n */\nexport function isValidChartType(chartType: string): chartType is ChartType {\n return chartType in chartImportMap\n}\n\n// Props for the LazyChart wrapper\nexport interface LazyChartProps extends ChartProps {\n chartType: ChartType\n fallback?: ReactNode\n}\n\n/**\n * Default loading placeholder for charts\n */\nfunction DefaultChartFallback({ height }: { height?: string | number }) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height: typeof height === 'number' ? `${height}px` : height || '200px' }}\n >\n <div className=\"dc:animate-pulse bg-dc-surface-secondary dc:rounded dc:w-full dc:h-full dc:min-h-[100px]\" />\n </div>\n )\n}\n\n/**\n * Lazy Chart Component\n *\n * Renders a chart component with React.lazy dynamic loading.\n * The chart type determines which chart component is loaded.\n *\n * @example\n * ```tsx\n * <LazyChart\n * chartType=\"bar\"\n * data={chartData}\n * chartConfig={{ yAxis: ['value'] }}\n * height={300}\n * />\n * ```\n */\nexport function LazyChart({\n chartType,\n fallback,\n height,\n ...chartProps\n}: LazyChartProps) {\n const ChartComponent = getLazyChart(chartType)\n\n return (\n <Suspense fallback={fallback ?? <DefaultChartFallback height={height} />}>\n <ChartComponent height={height} {...chartProps} />\n </Suspense>\n )\n}\n\n/**\n * Preload a chart type\n *\n * Triggers the dynamic import without rendering.\n * Useful for prefetching charts that will likely be needed.\n *\n * @example\n * ```tsx\n * // Preload bar chart on hover\n * onMouseEnter={() => preloadChart('bar')}\n * ```\n */\nexport function preloadChart(chartType: ChartType): void {\n const importFn = chartImportMap[chartType]\n if (importFn) {\n importFn()\n }\n}\n\n/**\n * Preload multiple chart types\n *\n * @example\n * ```tsx\n * // Preload common charts on app init\n * useEffect(() => {\n * preloadCharts(['bar', 'line', 'pie'])\n * }, [])\n * ```\n */\nexport function preloadCharts(chartTypes: ChartType[]): void {\n chartTypes.forEach(preloadChart)\n}\n\n/**\n * Get all available chart types\n */\nexport function getAvailableChartTypes(): ChartType[] {\n return Object.keys(chartImportMap) as ChartType[]\n}\n\n/**\n * Check if a chart type has loaded successfully.\n * Returns false if the chart failed to load due to missing dependencies.\n *\n * Note: This only returns accurate results after the chart has been attempted to load.\n * Use this for conditional UI logic (e.g., hiding unavailable chart types).\n */\nexport function isChartTypeAvailable(chartType: ChartType): boolean {\n return !failedChartTypes.has(chartType)\n}\n\n/**\n * Get list of chart types that failed to load due to missing dependencies.\n */\nexport function getUnavailableChartTypes(): ChartType[] {\n return Array.from(failedChartTypes)\n}\n"],"names":["MissingDependencyFallback","chartType","packageName","installCommand","height","jsxs","jsx","chartLoaderCache","failedChartTypes","chartDependencyMap","chartImportMap","n","createFallbackComponent","depInfo","FallbackComponent","createSafeImport","importFn","error","getLazyChart","safeImport","lazy","isValidChartType","DefaultChartFallback","LazyChart","fallback","chartProps","ChartComponent","Suspense","preloadChart","preloadCharts","chartTypes","getAvailableChartTypes","isChartTypeAvailable","getUnavailableChartTypes"],"mappings":"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"}
|