drizzle-cube 0.2.11 → 0.2.13

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 (76) hide show
  1. package/dist/adapters/compiler-CMwSRhTS.cjs +22 -0
  2. package/dist/adapters/{compiler-gcKytLwd.js → compiler-DrkCCzf0.js} +16 -11
  3. package/dist/adapters/express/index.cjs +1 -1
  4. package/dist/adapters/express/index.js +8 -8
  5. package/dist/adapters/fastify/index.cjs +1 -1
  6. package/dist/adapters/fastify/index.js +9 -9
  7. package/dist/adapters/hono/index.cjs +1 -1
  8. package/dist/adapters/hono/index.js +11 -11
  9. package/dist/adapters/nextjs/index.cjs +1 -1
  10. package/dist/adapters/nextjs/index.js +59 -59
  11. package/dist/client/charts.js +11 -11
  12. package/dist/client/chunks/{chart-activitygridchart-D17Fxiuf.js → chart-activitygridchart-CUGN9Xq9.js} +3 -2
  13. package/dist/client/chunks/chart-activitygridchart-CUGN9Xq9.js.map +1 -0
  14. package/dist/client/chunks/{chart-areachart-udSbAzl1.js → chart-areachart-B4tknnsY.js} +25 -25
  15. package/dist/client/chunks/{chart-areachart-udSbAzl1.js.map → chart-areachart-B4tknnsY.js.map} +1 -1
  16. package/dist/client/chunks/{chart-axisformatcontrols-DqSa245M.js → chart-axisformatcontrols-Ch_IYF94.js} +18 -18
  17. package/dist/client/chunks/chart-axisformatcontrols-Ch_IYF94.js.map +1 -0
  18. package/dist/client/chunks/{chart-barchart-CDIpqCKS.js → chart-barchart-D_op06r-.js} +6 -6
  19. package/dist/client/chunks/{chart-barchart-CDIpqCKS.js.map → chart-barchart-D_op06r-.js.map} +1 -1
  20. package/dist/client/chunks/{chart-bubblechart-CivK_yfh.js → chart-bubblechart-BsaIXUbS.js} +3 -3
  21. package/dist/client/chunks/chart-bubblechart-BsaIXUbS.js.map +1 -0
  22. package/dist/client/chunks/{chart-charttooltip-BVEdz4Q-.js → chart-charttooltip-Bx3I8jQv.js} +2 -2
  23. package/dist/client/chunks/{chart-charttooltip-BVEdz4Q-.js.map → chart-charttooltip-Bx3I8jQv.js.map} +1 -1
  24. package/dist/client/chunks/{chart-datatable-NHE7BTMr.js → chart-datatable-C7MS9q4Y.js} +2 -2
  25. package/dist/client/chunks/{chart-datatable-NHE7BTMr.js.map → chart-datatable-C7MS9q4Y.js.map} +1 -1
  26. package/dist/client/chunks/{chart-kpidelta-D-FR2o4V.js → chart-kpidelta-7-KOmb3w.js} +62 -60
  27. package/dist/client/chunks/chart-kpidelta-7-KOmb3w.js.map +1 -0
  28. package/dist/client/chunks/{chart-kpinumber-DSH8RJxb.js → chart-kpinumber-HOPfcK2N.js} +4 -4
  29. package/dist/client/chunks/{chart-kpinumber-DSH8RJxb.js.map → chart-kpinumber-HOPfcK2N.js.map} +1 -1
  30. package/dist/client/chunks/{chart-kpitext-Z9oh0bJq.js → chart-kpitext-BZkC9u3A.js} +24 -24
  31. package/dist/client/chunks/{chart-kpitext-Z9oh0bJq.js.map → chart-kpitext-BZkC9u3A.js.map} +1 -1
  32. package/dist/client/chunks/{chart-linechart-D4r0uD1j.js → chart-linechart-DqFmLbRe.js} +7 -7
  33. package/dist/client/chunks/{chart-linechart-D4r0uD1j.js.map → chart-linechart-DqFmLbRe.js.map} +1 -1
  34. package/dist/client/chunks/chart-markdownchart-9n_TemoB.js +256 -0
  35. package/dist/client/chunks/chart-markdownchart-9n_TemoB.js.map +1 -0
  36. package/dist/client/chunks/{chart-piechart-BhttUWuH.js → chart-piechart-CrXFd9pE.js} +6 -6
  37. package/dist/client/chunks/{chart-piechart-BhttUWuH.js.map → chart-piechart-CrXFd9pE.js.map} +1 -1
  38. package/dist/client/chunks/{chart-radarchart-DnqlfoGr.js → chart-radarchart-tar2GBkO.js} +5 -5
  39. package/dist/client/chunks/{chart-radarchart-DnqlfoGr.js.map → chart-radarchart-tar2GBkO.js.map} +1 -1
  40. package/dist/client/chunks/{chart-radialbarchart-BFxxiqLw.js → chart-radialbarchart-ab8Swtal.js} +5 -5
  41. package/dist/client/chunks/{chart-radialbarchart-BFxxiqLw.js.map → chart-radialbarchart-ab8Swtal.js.map} +1 -1
  42. package/dist/client/chunks/{chart-scatterchart-MN4SM-w7.js → chart-scatterchart-BP06BeU5.js} +5 -5
  43. package/dist/client/chunks/{chart-scatterchart-MN4SM-w7.js.map → chart-scatterchart-BP06BeU5.js.map} +1 -1
  44. package/dist/client/chunks/{chart-treemapchart-Nozh2m26.js → chart-treemapchart-DAiixITm.js} +31 -31
  45. package/dist/client/chunks/{chart-treemapchart-Nozh2m26.js.map → chart-treemapchart-DAiixITm.js.map} +1 -1
  46. package/dist/client/chunks/{charts-BSDHSv4l.js → charts-CHzWeaY1.js} +26 -26
  47. package/dist/client/chunks/charts-CHzWeaY1.js.map +1 -0
  48. package/dist/client/chunks/{components-CbDovlG-.js → components-DnM9CCUS.js} +2453 -2445
  49. package/dist/client/chunks/components-DnM9CCUS.js.map +1 -0
  50. package/dist/client/chunks/{index-th92_8oL.js → index-DlsvcKXf.js} +135 -135
  51. package/dist/client/chunks/index-DlsvcKXf.js.map +1 -0
  52. package/dist/client/components/AnalysisBuilder/AnalysisAxisDropZone.d.ts +5 -5
  53. package/dist/client/components/AnalysisBuilder/SectionHeading.d.ts +2 -7
  54. package/dist/client/components/AnalysisBuilder/types.d.ts +8 -8
  55. package/dist/client/components.js +2 -2
  56. package/dist/client/hooks/useResponsiveDashboard.d.ts +2 -8
  57. package/dist/client/hooks.js +2 -2
  58. package/dist/client/hooks.js.map +1 -1
  59. package/dist/client/icons/types.d.ts +2 -2
  60. package/dist/client/index.js +3 -3
  61. package/dist/client/providers.js +1 -1
  62. package/dist/client/styles.css +1 -1
  63. package/dist/client-bundle-stats.html +1 -1
  64. package/dist/server/index.cjs +2 -2
  65. package/dist/server/index.js +16 -11
  66. package/package.json +3 -3
  67. package/dist/adapters/compiler-DP1pPIcg.cjs +0 -22
  68. package/dist/client/chunks/chart-activitygridchart-D17Fxiuf.js.map +0 -1
  69. package/dist/client/chunks/chart-axisformatcontrols-DqSa245M.js.map +0 -1
  70. package/dist/client/chunks/chart-bubblechart-CivK_yfh.js.map +0 -1
  71. package/dist/client/chunks/chart-kpidelta-D-FR2o4V.js.map +0 -1
  72. package/dist/client/chunks/chart-markdownchart-C3FAQFuO.js +0 -254
  73. package/dist/client/chunks/chart-markdownchart-C3FAQFuO.js.map +0 -1
  74. package/dist/client/chunks/charts-BSDHSv4l.js.map +0 -1
  75. package/dist/client/chunks/components-CbDovlG-.js.map +0 -1
  76. package/dist/client/chunks/index-th92_8oL.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-bubblechart-BsaIXUbS.js","sources":["../../../src/client/components/charts/BubbleChart.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { select, scaleLinear, scaleSqrt, scaleOrdinal, scaleQuantize, extent, max, axisBottom, axisLeft, type ScaleOrdinal, type ScaleQuantize } from 'd3'\nimport { CHART_COLORS, CHART_COLORS_GRADIENT, CHART_MARGINS } from '../../utils/chartConstants'\nimport { formatTimeValue, getFieldGranularity, parseNumericValue, isValidNumericValue, formatAxisValue } from '../../utils/chartUtils'\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { getTheme, watchThemeChanges, type Theme } from '../../theme'\nimport type { ChartProps } from '../../types'\n\ninterface BubbleData {\n x: number\n xLabel?: string // Formatted label for time dimensions\n y: number\n size: number\n color?: string | number\n label: string\n series?: string\n}\n\nexport default function BubbleChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const svgRef = useRef<SVGSVGElement | null>(null)\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [, setHoveredBubble] = useState<string | null>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n const [dimensionsReady, setDimensionsReady] = useState(false)\n const [currentTheme, setCurrentTheme] = useState<Theme>('light')\n const { getFieldLabel } = useCubeContext()\n\n // Watch for theme changes\n useEffect(() => {\n setCurrentTheme(getTheme())\n const unwatch = watchThemeChanges((theme) => {\n setCurrentTheme(theme)\n })\n return unwatch\n }, [])\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n minBubbleSize: displayConfig?.minBubbleSize ?? 5,\n maxBubbleSize: displayConfig?.maxBubbleSize ?? 50,\n bubbleOpacity: displayConfig?.bubbleOpacity ?? 0.7,\n xAxisFormat: displayConfig?.xAxisFormat,\n leftYAxisFormat: displayConfig?.leftYAxisFormat\n }\n\n // Enhanced dimension measurement with retry mechanism\n useLayoutEffect(() => {\n let retryCount = 0\n const maxRetries = 10\n let rafId: number\n let timeoutId: ReturnType<typeof setTimeout>\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n \n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n setDimensionsReady(true)\n return true\n }\n }\n return false\n }\n \n // Immediate measurement\n const success = updateDimensions()\n \n if (!success && retryCount < maxRetries) {\n // Retry with requestAnimationFrame\n const retryWithRaf = () => {\n const rafSuccess = updateDimensions()\n \n if (!rafSuccess && retryCount < maxRetries) {\n retryCount++\n // Use setTimeout for additional retries with increasing delays\n timeoutId = setTimeout(() => {\n rafId = requestAnimationFrame(retryWithRaf)\n }, 50 * retryCount) // Increasing delay: 50ms, 100ms, 150ms, etc.\n }\n }\n \n rafId = requestAnimationFrame(retryWithRaf)\n }\n \n return () => {\n if (rafId) cancelAnimationFrame(rafId)\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [])\n\n // Enhanced ResizeObserver for dynamic resizing with immediate initialization\n useEffect(() => {\n let resizeObserver: ResizeObserver | null = null\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n if (!dimensionsReady) {\n setDimensionsReady(true)\n }\n }\n }\n }\n \n // Initialize ResizeObserver immediately\n if (containerRef.current) {\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect\n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n if (!dimensionsReady) {\n setDimensionsReady(true)\n }\n }\n }\n })\n \n resizeObserver.observe(containerRef.current)\n \n // Also try immediate measurement as fallback\n updateDimensions()\n }\n\n // Window resize as additional fallback\n window.addEventListener('resize', updateDimensions)\n \n return () => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n window.removeEventListener('resize', updateDimensions)\n }\n }, [dimensionsReady])\n\n useEffect(() => {\n if (!data || data.length === 0 || !svgRef.current || !dimensionsReady || dimensions.width === 0) {\n return\n }\n\n // Clear previous chart\n select(svgRef.current).selectAll('*').remove()\n\n\n // Validate chartConfig - only new format supported\n if (!chartConfig?.xAxis || !chartConfig?.yAxis || !chartConfig?.series) {\n return\n }\n\n const xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n const yAxisField = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis[0] : chartConfig.yAxis\n const seriesField = Array.isArray(chartConfig.series) ? chartConfig.series[0] : chartConfig.series\n const sizeFieldName = Array.isArray(chartConfig.sizeField) ? chartConfig.sizeField[0] : chartConfig.sizeField || yAxisField\n const colorFieldName = Array.isArray(chartConfig.colorField) ? chartConfig.colorField[0] : chartConfig.colorField\n\n\n if (!xAxisField || !yAxisField || !seriesField || !sizeFieldName) {\n return\n }\n\n // Transform data for bubble chart\n // Null handling: Filter out bubbles where x, y, or size are null\n const xGranularity = getFieldGranularity(queryObject, xAxisField)\n\n // Check if x-axis field is a time dimension\n const isTimeDimension = queryObject?.timeDimensions?.some(\n (td: { dimension: string }) => td.dimension === xAxisField\n ) || false\n\n const bubbleData: BubbleData[] = data\n .map(item => {\n const rawXValue = item[xAxisField]\n let xNum: number\n let xLabel: string\n\n if (isTimeDimension && rawXValue) {\n // For time dimensions, convert to timestamp for proper numeric positioning\n const dateStr = String(rawXValue)\n // Try to parse as date - handle ISO format and PostgreSQL format\n let date: Date\n if (dateStr.match(/^\\d{4}-\\d{2}-\\d{2}[T ]/)) {\n // Full timestamp format\n let isoStr = dateStr\n if (dateStr.includes(' ')) {\n isoStr = dateStr.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n date = new Date(isoStr)\n } else {\n date = new Date(dateStr)\n }\n\n xNum = isNaN(date.getTime()) ? parseFloat(dateStr) : date.getTime()\n xLabel = formatTimeValue(rawXValue, xGranularity)\n } else {\n // Non-time value - use as-is\n const formattedValue = formatTimeValue(rawXValue, xGranularity) || rawXValue\n xNum = typeof formattedValue === 'string' ? parseFloat(formattedValue) : formattedValue\n xLabel = String(formattedValue)\n }\n\n const yValue = parseNumericValue(item[yAxisField])\n const sizeValue = parseNumericValue(item[sizeFieldName])\n const seriesValue = item[seriesField]\n\n return {\n x: xNum,\n xLabel, // Store formatted label for tooltip display\n y: yValue as number, // Type assertion: filter below ensures this is never null\n size: sizeValue !== null ? Math.abs(sizeValue) : 0, // Ensure positive size\n color: colorFieldName ? item[colorFieldName] : seriesValue,\n series: seriesValue,\n label: `${seriesValue || 'Unknown'}`,\n isValid: isValidNumericValue(xNum) && yValue !== null && sizeValue !== null && sizeValue > 0\n }\n })\n .filter(d => d.isValid && d.size > 0) // Filter out bubbles with invalid coordinates or no size\n\n if (bubbleData.length === 0) return\n\n const margin = { \n ...CHART_MARGINS, \n left: CHART_MARGINS.left + 30, // Add extra 30px left margin for Y-axis label\n bottom: (safeDisplayConfig.showLegend && colorFieldName) ? 100 : 40 // Add extra space for legend\n }\n const width = dimensions.width - margin.left - margin.right\n const chartHeight = dimensions.height - margin.top - margin.bottom\n\n const svg = select(svgRef.current)\n .attr('width', dimensions.width)\n .attr('height', dimensions.height)\n\n const g = svg.append('g')\n .attr('transform', `translate(${margin.left},${margin.top})`)\n\n // Set up scales\n const xScale = scaleLinear()\n .domain(extent(bubbleData, d => d.x) as [number, number])\n .range([0, width])\n .nice()\n\n const yScale = scaleLinear()\n .domain(extent(bubbleData, d => d.y) as [number, number])\n .range([chartHeight, 0])\n .nice()\n\n const sizeScale = scaleSqrt()\n .domain([0, max(bubbleData, d => d.size) as number])\n .range([safeDisplayConfig.minBubbleSize, safeDisplayConfig.maxBubbleSize])\n\n // Set up color scale\n let colorScale: ScaleOrdinal<string, string> | ScaleQuantize<string>\n let isNumericColorField = false\n let uniqueColors: string[] = []\n \n if (colorFieldName && bubbleData.length > 0) {\n // Check if color field is numeric for color scaling (same logic as TreeMapChart)\n const colorValues = bubbleData.map(item => {\n const value = item.color\n return typeof value === 'string' ? parseFloat(value) : value\n }).filter((val): val is number => !isNaN(val as number))\n \n isNumericColorField = colorValues.length === bubbleData.length && colorValues.every(val => typeof val === 'number')\n \n if (isNumericColorField) {\n // Use D3 quantize scale for better color distribution with small ranges\n const minValue = Math.min(...colorValues)\n const maxValue = Math.max(...colorValues)\n \n // Create D3 quantize color scale - maps continuous data to discrete color bands\n colorScale = scaleQuantize<string>()\n .domain([minValue, maxValue])\n .range(colorPalette?.gradient || CHART_COLORS_GRADIENT)\n } else {\n // Categorical color field - use series colors\n uniqueColors = [...new Set(bubbleData.map(d => String(d.color)))]\n colorScale = scaleOrdinal<string>()\n .domain(uniqueColors)\n .range(colorPalette?.colors || CHART_COLORS)\n }\n } else {\n // Single color for all bubbles\n colorScale = scaleOrdinal<string>()\n .domain(['default'])\n .range([CHART_COLORS[0]])\n }\n\n // Get theme colors from CSS variables\n const getThemeColor = (varName: string, fallback: string) => {\n const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return value || fallback\n }\n\n const isDark = currentTheme !== 'light'\n const textColor = isDark\n ? getThemeColor('--dc-text-muted', '#cbd5e1') // Lighter text for dark mode\n : getThemeColor('--dc-text-secondary', '#374151') // Darker text for light mode\n const gridColor = isDark\n ? getThemeColor('--dc-border', '#475569') // Lighter grid for dark mode\n : '#9ca3af' // Much darker gray for light mode visibility\n\n // Add grid\n if (safeDisplayConfig.showGrid) {\n // X-axis grid\n const xGrid = g.append('g')\n .attr('class', 'grid')\n .attr('transform', `translate(0,${chartHeight})`)\n .call(axisBottom(xScale)\n .tickSize(-chartHeight)\n .tickFormat(() => '')\n )\n\n xGrid.selectAll('line')\n .style('stroke', gridColor)\n .style('stroke-dasharray', '3,3')\n .style('opacity', 0.3)\n\n xGrid.select('.domain')\n .style('stroke', 'none')\n\n // Y-axis grid\n const yGrid = g.append('g')\n .attr('class', 'grid')\n .call(axisLeft(yScale)\n .tickSize(-width)\n .tickFormat(() => '')\n )\n\n yGrid.selectAll('line')\n .style('stroke', gridColor)\n .style('stroke-dasharray', '3,3')\n .style('opacity', 0.3)\n\n yGrid.select('.domain')\n .style('stroke', 'none')\n }\n\n // Add X axis with proper time formatting if needed\n const xAxisGenerator = axisBottom(xScale)\n\n // If it's a time dimension, format the tick labels\n if (isTimeDimension) {\n xAxisGenerator.tickFormat((d) => {\n const date = new Date(d as number)\n if (isNaN(date.getTime())) return String(d)\n\n // Format based on granularity\n switch (xGranularity?.toLowerCase()) {\n case 'year':\n return String(date.getUTCFullYear())\n case 'quarter': {\n const q = Math.floor(date.getUTCMonth() / 3) + 1\n return `${date.getUTCFullYear()}-Q${q}`\n }\n case 'month':\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`\n case 'week':\n case 'day':\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}`\n case 'hour':\n return `${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')} ${String(date.getUTCHours()).padStart(2, '0')}:00`\n default:\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`\n }\n })\n } else if (safeDisplayConfig.xAxisFormat) {\n // Apply custom formatting for non-time X-axis\n xAxisGenerator.tickFormat((d) => formatAxisValue(d as number, safeDisplayConfig.xAxisFormat))\n }\n\n const xAxis = g.append('g')\n .attr('transform', `translate(0,${chartHeight})`)\n .call(xAxisGenerator)\n\n xAxis.selectAll('text')\n .style('fill', textColor)\n\n xAxis.selectAll('line, path')\n .style('stroke', gridColor)\n\n xAxis.append('text')\n .attr('x', width / 2)\n .attr('y', 35)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(safeDisplayConfig.xAxisFormat?.label || getFieldLabel(xAxisField))\n\n // Add Y axis with optional formatting\n const yAxisGenerator = axisLeft(yScale)\n if (safeDisplayConfig.leftYAxisFormat) {\n yAxisGenerator.tickFormat((d) => formatAxisValue(d as number, safeDisplayConfig.leftYAxisFormat))\n }\n const yAxis = g.append('g')\n .call(yAxisGenerator)\n\n yAxis.selectAll('text')\n .style('fill', textColor)\n\n yAxis.selectAll('line, path')\n .style('stroke', gridColor)\n\n yAxis.append('text')\n .attr('transform', 'rotate(-90)')\n .attr('y', -35)\n .attr('x', -chartHeight / 2)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(safeDisplayConfig.leftYAxisFormat?.label || getFieldLabel(yAxisField))\n\n // Create tooltip\n const tooltip = select('body').append('div')\n .attr('class', 'bubble-chart-tooltip')\n .style('position', 'absolute')\n .style('padding', '8px')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none')\n .style('opacity', 0)\n .style('z-index', 1000)\n\n // Add bubbles\n const bubbles = g.selectAll('.bubble')\n .data(bubbleData)\n .enter().append('circle')\n .attr('class', 'bubble')\n .attr('cx', d => xScale(d.x))\n .attr('cy', d => yScale(d.y))\n .attr('r', d => sizeScale(d.size))\n .style('fill', d => {\n if (colorFieldName && d.color !== undefined) {\n return isNumericColorField\n ? (colorScale as ScaleQuantize<string>)(d.color as number)\n : (colorScale as ScaleOrdinal<string, string>)(String(d.color))\n }\n return CHART_COLORS[0]\n })\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n .style('stroke', '#fff')\n .style('stroke-width', 1)\n .style('cursor', 'pointer')\n\n // Add hover effects\n if (safeDisplayConfig.showTooltip) {\n bubbles\n .on('mouseover', function(event, d) {\n select(this)\n .transition()\n .duration(200)\n .style('opacity', 1)\n .attr('r', sizeScale(d.size) * 1.1)\n\n const tooltipContent = [\n `<strong>${d.series || 'Unknown'}</strong>`,\n `${getFieldLabel(xAxisField)}: ${d.xLabel || (safeDisplayConfig.xAxisFormat ? formatAxisValue(d.x, safeDisplayConfig.xAxisFormat) : d.x)}`,\n `${getFieldLabel(yAxisField)}: ${safeDisplayConfig.leftYAxisFormat ? formatAxisValue(d.y, safeDisplayConfig.leftYAxisFormat) : d.y}`,\n `${getFieldLabel(sizeFieldName)}: ${safeDisplayConfig.leftYAxisFormat ? formatAxisValue(d.size, safeDisplayConfig.leftYAxisFormat) : d.size}`,\n colorFieldName && d.color ? `${getFieldLabel(colorFieldName)}: ${d.color}` : ''\n ].filter(Boolean).join('<br>')\n\n tooltip\n .html(tooltipContent)\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n .transition()\n .duration(200)\n .style('opacity', 1)\n\n setHoveredBubble(d.label)\n })\n .on('mousemove', function(event) {\n tooltip\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n })\n .on('mouseout', function(_event, d) {\n select(this)\n .transition()\n .duration(200)\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n .attr('r', sizeScale(d.size))\n\n tooltip\n .transition()\n .duration(200)\n .style('opacity', 0)\n\n setHoveredBubble(null)\n })\n }\n\n // Add legend if needed\n if (safeDisplayConfig.showLegend && colorFieldName) {\n if (isNumericColorField) {\n // Create gradient legend for numeric color field\n const legendWidth = 200\n const legendHeight = 20\n const minValue = Math.min(...bubbleData.map(d => d.color as number))\n const maxValue = Math.max(...bubbleData.map(d => d.color as number))\n \n const legend = g.append('g')\n .attr('class', 'color-legend')\n .attr('transform', `translate(${width / 2 - legendWidth / 2}, ${chartHeight + 60})`)\n\n // Create gradient definition\n const defs = svg.append('defs')\n const gradient = defs.append('linearGradient')\n .attr('id', 'color-scale-gradient')\n .attr('x1', '0%')\n .attr('y1', '0%')\n .attr('x2', '100%')\n .attr('y2', '0%')\n\n // Add color stops for the gradient\n const gradientColors = colorPalette?.gradient || CHART_COLORS_GRADIENT\n gradientColors.forEach((color, i) => {\n gradient.append('stop')\n .attr('offset', `${(i / (gradientColors.length - 1)) * 100}%`)\n .attr('stop-color', color)\n })\n\n // Add the gradient rectangle\n legend.append('rect')\n .attr('width', legendWidth)\n .attr('height', legendHeight)\n .style('fill', 'url(#color-scale-gradient)')\n .style('stroke', '#ccc')\n .style('stroke-width', 1)\n\n // Add min value label\n legend.append('text')\n .attr('x', 0)\n .attr('y', legendHeight + 15)\n .attr('text-anchor', 'start')\n .style('font-size', '11px')\n .style('fill', textColor)\n .text(safeDisplayConfig.leftYAxisFormat ? formatAxisValue(minValue, safeDisplayConfig.leftYAxisFormat) : minValue.toFixed(2))\n\n // Add max value label\n legend.append('text')\n .attr('x', legendWidth)\n .attr('y', legendHeight + 15)\n .attr('text-anchor', 'end')\n .style('font-size', '11px')\n .style('fill', textColor)\n .text(safeDisplayConfig.leftYAxisFormat ? formatAxisValue(maxValue, safeDisplayConfig.leftYAxisFormat) : maxValue.toFixed(2))\n\n // Add field name label\n legend.append('text')\n .attr('x', legendWidth / 2)\n .attr('y', -5)\n .attr('text-anchor', 'middle')\n .style('font-size', '12px')\n .style('font-weight', 'bold')\n .style('fill', textColor)\n .text(getFieldLabel(colorFieldName))\n\n } else {\n // Original categorical legend\n const legendItems = uniqueColors\n\n if (legendItems.length > 0) {\n const legend = g.append('g')\n .attr('class', 'legend')\n .attr('transform', `translate(${width / 2 - (legendItems.length * 80) / 2}, ${chartHeight + 60})`)\n\n const legendItem = legend.selectAll('.legend-item')\n .data(legendItems)\n .enter().append('g')\n .attr('class', 'legend-item')\n .attr('transform', (_d, i) => `translate(${i * 80}, 0)`)\n .style('cursor', 'pointer')\n\n legendItem.append('circle')\n .attr('cx', 5)\n .attr('cy', 5)\n .attr('r', 5)\n .style('fill', d => (colorScale as ScaleOrdinal<string, string>)(d as string))\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n\n legendItem.append('text')\n .attr('x', 15)\n .attr('y', 5)\n .attr('dy', '.35em')\n .style('font-size', '11px')\n .style('fill', textColor)\n .text(d => String(d))\n\n // Legend hover effects\n legendItem\n .on('mouseover', function(_event, legendKey) {\n // Highlight matching bubbles\n bubbles\n .transition()\n .duration(200)\n .style('opacity', d => {\n const matches = colorFieldName && String(d.color) === legendKey\n return matches ? 1 : 0.2\n })\n })\n .on('mouseout', function() {\n // Reset all bubbles\n bubbles\n .transition()\n .duration(200)\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n })\n }\n }\n }\n\n // Cleanup function\n return () => {\n tooltip.remove()\n }\n }, [data, chartConfig, displayConfig, queryObject, dimensions, dimensionsReady, safeDisplayConfig.showLegend, safeDisplayConfig.showGrid, safeDisplayConfig.showTooltip, safeDisplayConfig.minBubbleSize, safeDisplayConfig.maxBubbleSize, safeDisplayConfig.bubbleOpacity, colorPalette, currentTheme])\n\n if (!data || data.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data points to display in bubble chart</div>\n </div>\n </div>\n )\n }\n\n // Validate that we have required fields\n const hasValidConfig = chartConfig?.xAxis && chartConfig?.yAxis && chartConfig?.series\n if (!hasValidConfig) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Required</div>\n <div className=\"text-xs\">Bubble chart requires xAxis, yAxis, series, and sizeField dimensions</div>\n <div className=\"text-xs mt-1\">Optional: colorField for bubble coloring</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full flex-1 flex flex-col relative\" style={{ height, minHeight: '250px', overflow: 'hidden' }}>\n <div ref={containerRef} className=\"w-full h-full relative\">\n <svg ref={svgRef} className=\"w-full h-full\" />\n {!dimensionsReady && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"text-dc-text-muted text-sm\">Measuring chart dimensions...</div>\n </div>\n )}\n </div>\n </div>\n )\n}"],"names":["BubbleChart","data","chartConfig","displayConfig","queryObject","height","colorPalette","svgRef","useRef","containerRef","setHoveredBubble","useState","dimensions","setDimensions","dimensionsReady","setDimensionsReady","currentTheme","setCurrentTheme","getFieldLabel","useCubeContext","useEffect","getTheme","watchThemeChanges","theme","safeDisplayConfig","useLayoutEffect","retryCount","maxRetries","rafId","timeoutId","updateDimensions","width","retryWithRaf","resizeObserver","entries","entry","select","xAxisField","yAxisField","seriesField","sizeFieldName","colorFieldName","xGranularity","getFieldGranularity","isTimeDimension","td","bubbleData","item","rawXValue","xNum","xLabel","dateStr","date","isoStr","formatTimeValue","formattedValue","yValue","parseNumericValue","sizeValue","seriesValue","isValidNumericValue","d","margin","CHART_MARGINS","chartHeight","svg","g","xScale","scaleLinear","extent","yScale","sizeScale","scaleSqrt","max","colorScale","isNumericColorField","uniqueColors","colorValues","value","val","minValue","maxValue","scaleQuantize","CHART_COLORS_GRADIENT","scaleOrdinal","CHART_COLORS","getThemeColor","varName","fallback","isDark","textColor","gridColor","xGrid","axisBottom","yGrid","axisLeft","xAxisGenerator","q","formatAxisValue","xAxis","yAxisGenerator","yAxis","tooltip","bubbles","event","tooltipContent","_event","legend","gradient","gradientColors","color","i","legendItems","legendItem","_d","legendKey","jsx","jsxs"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as t } from "react/jsx-runtime";
2
2
  import { Tooltip as e } from "recharts";
3
- import { n as p } from "./chart-activitygridchart-D17Fxiuf.js";
3
+ import { n as p } from "./chart-activitygridchart-CUGN9Xq9.js";
4
4
  const i = (r, o) => r == null ? ["No data", o] : [p(r), o];
5
5
  function d({ formatter: r, labelFormatter: o }) {
6
6
  return /* @__PURE__ */ t(
@@ -23,4 +23,4 @@ function d({ formatter: r, labelFormatter: o }) {
23
23
  export {
24
24
  d as C
25
25
  };
26
- //# sourceMappingURL=chart-charttooltip-BVEdz4Q-.js.map
26
+ //# sourceMappingURL=chart-charttooltip-Bx3I8jQv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-charttooltip-BVEdz4Q-.js","sources":["../../../src/client/components/charts/ChartTooltip.tsx"],"sourcesContent":["import React from 'react'\nimport { Tooltip } from 'recharts'\nimport { formatNumericValue } from '../../utils/chartUtils'\n\ninterface ChartTooltipProps {\n formatter?: (value: any, name: any, props: any) => [React.ReactText, React.ReactText]\n labelFormatter?: (label: any) => React.ReactText\n}\n\n// Default formatter that rounds numeric values to at most 2 decimal places\nconst defaultFormatter = (value: any, name: any): [React.ReactText, React.ReactText] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatNumericValue(value), name]\n}\n\nexport default function ChartTooltip({ formatter, labelFormatter }: ChartTooltipProps) {\n return (\n <Tooltip\n formatter={formatter || defaultFormatter}\n labelFormatter={labelFormatter}\n contentStyle={{\n backgroundColor: 'white',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n fontSize: '0.875rem',\n color: '#1f2937',\n boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n padding: '8px 12px'\n }}\n />\n )\n}"],"names":["defaultFormatter","value","name","formatNumericValue","ChartTooltip","formatter","labelFormatter","jsx","Tooltip"],"mappings":";;;AAUA,MAAMA,IAAmB,CAACC,GAAYC,MAChCD,KAAU,OACL,CAAC,WAAWC,CAAI,IAElB,CAACC,EAAmBF,CAAK,GAAGC,CAAI;AAGzC,SAAwBE,EAAa,EAAE,WAAAC,GAAW,gBAAAC,KAAqC;AACrF,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAWH,KAAaL;AAAA,MACxB,gBAAAM;AAAA,MACA,cAAc;AAAA,QACZ,iBAAiB;AAAA,QACjB,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,UAAU;AAAA,QACV,OAAO;AAAA,QACP,WAAW;AAAA,QACX,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"chart-charttooltip-Bx3I8jQv.js","sources":["../../../src/client/components/charts/ChartTooltip.tsx"],"sourcesContent":["import React from 'react'\nimport { Tooltip } from 'recharts'\nimport { formatNumericValue } from '../../utils/chartUtils'\n\ninterface ChartTooltipProps {\n formatter?: (value: any, name: any, props: any) => [React.ReactText, React.ReactText]\n labelFormatter?: (label: any) => React.ReactText\n}\n\n// Default formatter that rounds numeric values to at most 2 decimal places\nconst defaultFormatter = (value: any, name: any): [React.ReactText, React.ReactText] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatNumericValue(value), name]\n}\n\nexport default function ChartTooltip({ formatter, labelFormatter }: ChartTooltipProps) {\n return (\n <Tooltip\n formatter={formatter || defaultFormatter}\n labelFormatter={labelFormatter}\n contentStyle={{\n backgroundColor: 'white',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n fontSize: '0.875rem',\n color: '#1f2937',\n boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n padding: '8px 12px'\n }}\n />\n )\n}"],"names":["defaultFormatter","value","name","formatNumericValue","ChartTooltip","formatter","labelFormatter","jsx","Tooltip"],"mappings":";;;AAUA,MAAMA,IAAmB,CAACC,GAAYC,MAChCD,KAAU,OACL,CAAC,WAAWC,CAAI,IAElB,CAACC,EAAmBF,CAAK,GAAGC,CAAI;AAGzC,SAAwBE,EAAa,EAAE,WAAAC,GAAW,gBAAAC,KAAqC;AACrF,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAWH,KAAaL;AAAA,MACxB,gBAAAM;AAAA,MACA,cAAc;AAAA,QACZ,iBAAiB;AAAA,QACjB,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,UAAU;AAAA,QACV,OAAO;AAAA,QACP,WAAW;AAAA,QACX,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,EAAA;AAGN;"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as l, jsxs as d } from "react/jsx-runtime";
2
2
  import { useMemo as y } from "react";
3
- import { c as w, u as k, f as g } from "./chart-activitygridchart-D17Fxiuf.js";
3
+ import { c as w, u as k, f as g } from "./chart-activitygridchart-CUGN9Xq9.js";
4
4
  import { a as F } from "./chart-activitygridchart-config-AVBoHdRn.js";
5
5
  function S(e) {
6
6
  if (!e) return [];
@@ -280,4 +280,4 @@ function $(e, t) {
280
280
  export {
281
281
  z as default
282
282
  };
283
- //# sourceMappingURL=chart-datatable-NHE7BTMr.js.map
283
+ //# sourceMappingURL=chart-datatable-C7MS9q4Y.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-datatable-NHE7BTMr.js","sources":["../../../src/client/utils/pivotUtils.ts","../../../src/client/components/charts/DataTable.tsx"],"sourcesContent":["/**\n * Pivot utilities for DataTable time dimension pivoting\n *\n * When a query includes a time dimension with granularity, transforms flat data\n * into a pivoted structure with time periods as columns.\n */\n\nimport type { CubeQuery } from '../types'\nimport type { CubeMeta } from '../hooks/useCubeMeta'\nimport { formatTimeValue } from './chartUtils'\n\n/**\n * Derives ordered column list from a CubeQuery object.\n * Order: dimensions, timeDimensions (as field names), measures\n *\n * @param queryObject The CubeQuery object\n * @returns Array of field names in order\n */\nexport function getOrderedColumnsFromQuery(queryObject?: CubeQuery): string[] {\n if (!queryObject) return []\n\n const columns: string[] = []\n\n // Add regular dimensions first\n if (queryObject.dimensions) {\n columns.push(...queryObject.dimensions)\n }\n\n // Add time dimensions\n if (queryObject.timeDimensions) {\n queryObject.timeDimensions.forEach(td => {\n if (!columns.includes(td.dimension)) {\n columns.push(td.dimension)\n }\n })\n }\n\n // Add measures last\n if (queryObject.measures) {\n columns.push(...queryObject.measures)\n }\n\n return columns\n}\n\n/**\n * Configuration for pivoting based on query structure\n */\nexport interface PivotConfig {\n /** Time dimension field name (e.g., \"Sales.date\") */\n timeDimension: string\n /** Time granularity (e.g., \"month\", \"day\", \"year\") */\n granularity: string\n /** Non-time dimension fields */\n dimensions: string[]\n /** Measure fields */\n measures: string[]\n}\n\n/**\n * Column definition for pivoted table\n */\nexport interface PivotColumn {\n /** Column key for data access */\n key: string\n /** Display label for column header */\n label: string\n /** Whether this is a time column (vs row identifier column) */\n isTimeColumn: boolean\n /** Whether this is the measure column */\n isMeasureColumn?: boolean\n}\n\n/**\n * Row in the pivoted table\n */\nexport interface PivotRow {\n /** Unique row identifier */\n id: string\n /** The measure field name (for icon lookup) */\n measureField: string\n /** Values keyed by column key */\n values: Record<string, any>\n /** Whether this is the first row in a dimension group (for row spanning) */\n isFirstInGroup?: boolean\n /** Number of rows to span for dimension cells (only set on first row in group) */\n dimensionRowSpan?: number\n}\n\n/**\n * Result of pivoting table data\n */\nexport interface PivotedTableData {\n /** Whether data was pivoted (has time dimension with granularity) */\n isPivoted: boolean\n /** Column definitions for the pivoted table */\n columns: PivotColumn[]\n /** Rows of pivoted data */\n rows: PivotRow[]\n}\n\n/**\n * Determines if a query has a time dimension with granularity that should trigger pivoting\n * @param queryObject The CubeQuery object\n * @param xAxisOverride Optional array of fields to use for filtering dimensions and measures\n * (for respecting chartConfig.xAxis configuration)\n * @returns PivotConfig if pivoting should occur, null otherwise\n */\nexport function hasTimeDimensionForPivot(\n queryObject?: CubeQuery,\n xAxisOverride?: string[]\n): PivotConfig | null {\n if (!queryObject?.timeDimensions?.length) return null\n\n // Find the first time dimension with granularity\n const timeDim = queryObject.timeDimensions.find(td => td.granularity)\n if (!timeDim?.granularity) return null\n\n // Must have at least one measure to pivot\n if (!queryObject.measures?.length) return null\n\n let dimensions: string[]\n let measures: string[]\n\n if (xAxisOverride && xAxisOverride.length > 0) {\n // Filter dimensions from xAxisOverride (excluding time dimension and measures)\n dimensions = xAxisOverride.filter(field => {\n // Exclude the time dimension being pivoted (it becomes columns)\n if (field === timeDim.dimension) return false\n // Exclude measures (they become row values, not dimension columns)\n if (queryObject.measures?.includes(field)) return false\n return true\n })\n\n // Filter measures from xAxisOverride - only show measures that are in xAxis\n const measuresInXAxis = xAxisOverride.filter(field =>\n queryObject.measures?.includes(field)\n )\n // If xAxis contains measures, use only those; otherwise fall back to all measures\n measures = measuresInXAxis.length > 0 ? measuresInXAxis : queryObject.measures\n } else {\n dimensions = queryObject.dimensions || []\n measures = queryObject.measures\n }\n\n // Must have at least one measure after filtering\n if (measures.length === 0) return null\n\n return {\n timeDimension: timeDim.dimension,\n granularity: timeDim.granularity,\n dimensions,\n measures\n }\n}\n\n/**\n * Extracts unique time values from data and sorts them chronologically\n */\nfunction extractAndSortTimeValues(\n data: any[],\n timeDimension: string,\n granularity: string\n): string[] {\n const timeSet = new Set<string>()\n\n data.forEach(row => {\n const rawTime = row[timeDimension]\n if (rawTime != null) {\n const formattedTime = formatTimeValue(rawTime, granularity)\n timeSet.add(formattedTime)\n }\n })\n\n // Sort chronologically - ISO date strings sort correctly alphabetically\n return Array.from(timeSet).sort()\n}\n\n/**\n * Builds column definitions for pivoted table\n * Order: Measure (if multiple) -> Dimensions -> Time columns\n */\nfunction buildColumns(\n config: PivotConfig,\n timeValues: string[],\n getFieldLabel: (field: string) => string\n): PivotColumn[] {\n const columns: PivotColumn[] = []\n\n // Add measure column first (if multiple measures)\n if (config.measures.length > 1) {\n columns.push({\n key: '__measure__',\n label: 'Measure',\n isTimeColumn: false,\n isMeasureColumn: true\n })\n }\n\n // Add dimension columns\n config.dimensions.forEach(dim => {\n columns.push({\n key: dim,\n label: getFieldLabel(dim),\n isTimeColumn: false\n })\n })\n\n // Add time columns (already sorted chronologically)\n timeValues.forEach(timeVal => {\n columns.push({\n key: timeVal,\n label: timeVal,\n isTimeColumn: true\n })\n })\n\n return columns\n}\n\n/**\n * Groups data by dimension values, then by time period\n * Returns Map<dimensionKey, Map<formattedTime, dataRow>>\n */\nfunction groupByDimensions(\n data: any[],\n config: PivotConfig\n): Map<string, Map<string, any>> {\n const grouped = new Map<string, Map<string, any>>()\n\n data.forEach(row => {\n // Build dimension key from all dimension values\n const dimKey = config.dimensions.length > 0\n ? config.dimensions.map(dim => String(row[dim] ?? '')).join('|')\n : '__all__'\n\n // Get or create time map for this dimension combo\n if (!grouped.has(dimKey)) {\n grouped.set(dimKey, new Map())\n }\n\n // Store data point by formatted time value\n const rawTime = row[config.timeDimension]\n if (rawTime != null) {\n const formattedTime = formatTimeValue(rawTime, config.granularity)\n grouped.get(dimKey)!.set(formattedTime, row)\n }\n })\n\n return grouped\n}\n\n/**\n * Builds pivoted rows from grouped data\n * Rows are grouped by measure first (all Revenue rows together, all Quantity rows together)\n * Then within each measure group, rows are ordered by dimension values\n */\nfunction buildPivotedRows(\n data: any[],\n config: PivotConfig,\n timeValues: string[],\n getFieldLabel: (field: string) => string\n): PivotRow[] {\n // Group data by dimensions and time\n const grouped = groupByDimensions(data, config)\n const dimensionKeys = Array.from(grouped.keys())\n\n const rows: PivotRow[] = []\n const measureCount = config.measures.length\n const dimensionCount = dimensionKeys.length\n\n // Iterate over measures first, then dimensions\n // This groups all rows for one measure together\n config.measures.forEach((measure) => {\n dimensionKeys.forEach((dimensionKey, dimIndex) => {\n const timeData = grouped.get(dimensionKey)!\n const rowId = measureCount > 1\n ? `${measure}|${dimensionKey}`\n : dimensionKey\n\n const values: Record<string, any> = {}\n\n // Add dimension values\n const dimValues = dimensionKey === '__all__' ? [] : dimensionKey.split('|')\n config.dimensions.forEach((dim, idx) => {\n values[dim] = dimValues[idx] ?? ''\n })\n\n // Add measure name if multiple measures (for display in Measure column)\n if (measureCount > 1) {\n values['__measure__'] = getFieldLabel(measure)\n }\n\n // Add time period values\n timeValues.forEach(timeVal => {\n const dataPoint = timeData.get(timeVal)\n values[timeVal] = dataPoint?.[measure] ?? null\n })\n\n // Track grouping for row spanning (when multiple measures)\n // First row of each measure group should span all dimension rows\n const isFirstInGroup = dimIndex === 0\n const measureRowSpan = isFirstInGroup && measureCount > 1 ? dimensionCount : undefined\n\n rows.push({\n id: rowId,\n measureField: measure,\n values,\n isFirstInGroup,\n dimensionRowSpan: measureRowSpan\n })\n })\n })\n\n return rows\n}\n\n/**\n * Pivots flat data into time-columned table structure\n *\n * @param data Raw data array from query result\n * @param config Pivot configuration\n * @param getFieldLabel Function to get display label for a field\n * @param meta Optional cube metadata for looking up measure types\n * @returns Pivoted table data structure\n */\nexport function pivotTableData(\n data: any[],\n config: PivotConfig,\n getFieldLabel: (field: string) => string,\n _meta?: CubeMeta | null\n): PivotedTableData {\n if (!data || data.length === 0) {\n return { isPivoted: true, columns: [], rows: [] }\n }\n\n // Extract unique time values and sort chronologically\n const timeValues = extractAndSortTimeValues(data, config.timeDimension, config.granularity)\n\n // Build column definitions\n const columns = buildColumns(config, timeValues, getFieldLabel)\n\n // Build pivoted rows\n const rows = buildPivotedRows(data, config, timeValues, getFieldLabel)\n\n return { isPivoted: true, columns, rows }\n}\n\n/**\n * Looks up the measure type from metadata\n *\n * @param measureField The fully qualified measure field name (e.g., \"Sales.revenue\")\n * @param meta Cube metadata\n * @returns The measure type (e.g., \"sum\", \"count\", \"avg\") or undefined\n */\nexport function getMeasureType(measureField: string, meta: CubeMeta | null): string | undefined {\n if (!meta?.cubes) return undefined\n\n for (const cube of meta.cubes) {\n const measure = cube.measures.find(m => m.name === measureField)\n if (measure) {\n return measure.type\n }\n }\n\n return undefined\n}\n","/**\n * Data Table component with time dimension pivoting\n *\n * When a query includes a time dimension with granularity, the table\n * automatically pivots to show time periods as columns.\n */\n\nimport { useMemo } from 'react'\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { getMeasureTypeIcon } from '../../icons'\nimport {\n hasTimeDimensionForPivot,\n pivotTableData,\n getMeasureType,\n getOrderedColumnsFromQuery,\n type PivotedTableData,\n type PivotColumn,\n type PivotRow\n} from '../../utils/pivotUtils'\nimport { formatAxisValue } from '../../utils/chartUtils'\nimport type { ChartProps, AxisFormatConfig } from '../../types'\n\nexport default function DataTable({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = 300\n}: ChartProps) {\n const { getFieldLabel, meta } = useCubeContext()\n\n // Detect if we should pivot based on query structure\n // Pass chartConfig.xAxis to respect user-configured column ordering\n const pivotConfig = useMemo(\n () => hasTimeDimensionForPivot(queryObject, chartConfig?.xAxis),\n [queryObject, chartConfig?.xAxis]\n )\n\n // Check if pivoting is enabled (default: true when time dimension present)\n const enablePivot = displayConfig?.pivotTimeDimension !== false\n\n // Compute pivoted data if applicable\n const pivotedData = useMemo<PivotedTableData | null>(() => {\n if (!pivotConfig || !enablePivot) return null\n return pivotTableData(data, pivotConfig, getFieldLabel, meta)\n }, [data, pivotConfig, enablePivot, getFieldLabel, meta])\n\n // Empty state\n if (!data || data.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data to display in table</div>\n </div>\n </div>\n )\n }\n\n // Render pivoted table if applicable\n if (pivotedData?.isPivoted && pivotedData.columns.length > 0) {\n return (\n <PivotedTable\n pivotedData={pivotedData}\n height={height}\n meta={meta}\n leftYAxisFormat={displayConfig?.leftYAxisFormat}\n />\n )\n }\n\n // Fallback to flat table rendering\n return (\n <FlatTable\n data={data}\n chartConfig={chartConfig}\n queryObject={queryObject}\n height={height}\n getFieldLabel={getFieldLabel}\n leftYAxisFormat={displayConfig?.leftYAxisFormat}\n />\n )\n}\n\n/**\n * Pivoted table component - renders time dimension as columns\n */\nfunction PivotedTable({\n pivotedData,\n height,\n meta,\n leftYAxisFormat\n}: {\n pivotedData: PivotedTableData\n height: number | string\n meta: any\n leftYAxisFormat?: AxisFormatConfig\n}) {\n const { columns, rows } = pivotedData\n\n if (columns.length === 0 || rows.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data to display in table</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full overflow-auto\" style={{ height }}>\n <table className=\"min-w-full divide-y border-dc-border\">\n <thead className=\"bg-dc-surface-secondary sticky top-0\">\n <tr>\n {columns.map((col: PivotColumn) => (\n <th\n key={col.key}\n className={`px-3 py-2 text-xs font-medium text-dc-text-muted uppercase tracking-wider whitespace-nowrap ${\n col.isTimeColumn ? 'text-right' : 'text-left'\n }`}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"bg-dc-surface divide-y border-dc-border\">\n {rows.map((row: PivotRow) => (\n <PivotedTableRow\n key={row.id}\n row={row}\n columns={columns}\n meta={meta}\n leftYAxisFormat={leftYAxisFormat}\n />\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * Single row in the pivoted table\n * Supports row spanning for measure cells when grouped by measure\n */\nfunction PivotedTableRow({\n row,\n columns,\n meta,\n leftYAxisFormat\n}: {\n row: PivotRow\n columns: PivotColumn[]\n meta: any\n leftYAxisFormat?: AxisFormatConfig\n}) {\n // Get measure icon for this row\n const measureType = getMeasureType(row.measureField, meta)\n const MeasureIcon = getMeasureTypeIcon(measureType)\n\n return (\n <tr className=\"hover:bg-dc-surface-secondary\">\n {columns.map((col: PivotColumn) => {\n const value = row.values[col.key]\n\n // Measure column - show icon + label with row spanning\n if (col.isMeasureColumn) {\n // Skip this cell if not first in measure group\n if (row.isFirstInGroup === false) {\n return null\n }\n\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text align-top\"\n rowSpan={row.dimensionRowSpan}\n >\n <div className=\"flex items-center\">\n <MeasureIcon className=\"w-3.5 h-3.5 mr-1.5 text-dc-text-muted shrink-0\" />\n <span>{value}</span>\n </div>\n </td>\n )\n }\n\n // Time column - right-aligned, formatted values (these are measure values)\n if (col.isTimeColumn) {\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-right text-dc-text\"\n >\n {formatPivotCellValue(value, leftYAxisFormat)}\n </td>\n )\n }\n\n // Dimension column - left-aligned (no row spanning) - no number formatting\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text\"\n >\n {formatPivotCellValue(value)}\n </td>\n )\n })}\n </tr>\n )\n}\n\n/**\n * Format cell value for pivoted table display\n * Shows \"-\" for null/undefined values\n */\nfunction formatPivotCellValue(value: any, formatConfig?: AxisFormatConfig): string {\n if (value === null || value === undefined) return '-'\n if (typeof value === 'number') {\n // Use formatAxisValue if config provided\n if (formatConfig) {\n return formatAxisValue(value, formatConfig)\n }\n // Format with locale and up to 2 decimal places\n if (Number.isInteger(value)) {\n return value.toLocaleString()\n }\n return parseFloat(value.toFixed(2)).toLocaleString()\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No'\n }\n return String(value)\n}\n\n/**\n * Flat table component - original non-pivoted table rendering\n */\nfunction FlatTable({\n data,\n chartConfig,\n queryObject,\n height,\n getFieldLabel,\n leftYAxisFormat\n}: {\n data: any[]\n chartConfig?: { xAxis?: string[] }\n queryObject?: ChartProps['queryObject']\n height: number | string\n getFieldLabel: (field: string) => string\n leftYAxisFormat?: AxisFormatConfig\n}) {\n // Get all columns available in data\n const allColumns = Object.keys(data[0] || {})\n\n // Determine column order with proper fallback:\n // 1. If xAxis is configured, use that order\n // 2. Otherwise, derive order from queryObject (dimensions + timeDimensions + measures)\n // 3. Fallback: Object.keys order\n const columns = useMemo(() => {\n // If xAxis is configured, use that order (filtered to existing columns)\n if (chartConfig?.xAxis && chartConfig.xAxis.length > 0) {\n return chartConfig.xAxis.filter(col => allColumns.includes(col))\n }\n\n // Derive order from queryObject\n const queryOrder = getOrderedColumnsFromQuery(queryObject)\n if (queryOrder.length > 0) {\n // Filter to only columns that exist in data\n const ordered = queryOrder.filter(col => allColumns.includes(col))\n // Add any columns in data that weren't in query (edge case)\n const remaining = allColumns.filter(col => !ordered.includes(col))\n return [...ordered, ...remaining]\n }\n\n // Final fallback: Object.keys order\n return allColumns\n }, [chartConfig?.xAxis, queryObject, allColumns])\n\n if (columns.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No columns available</div>\n <div className=\"text-xs text-dc-text-secondary\">Data structure is invalid</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full overflow-auto\" style={{ height }}>\n <table className=\"min-w-full divide-y border-dc-border\">\n <thead className=\"bg-dc-surface-secondary sticky top-0\">\n <tr>\n {columns.map((column) => (\n <th\n key={column}\n className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\"\n >\n {getFieldLabel(column)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"bg-dc-surface divide-y border-dc-border\">\n {data.map((row, index) => (\n <tr key={index} className=\"hover:bg-dc-surface-secondary\">\n {columns.map((column) => (\n <td\n key={column}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text\"\n >\n {formatCellValue(row[column], leftYAxisFormat)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * Format cell value for flat table display\n */\nfunction formatCellValue(value: any, formatConfig?: AxisFormatConfig): string {\n if (value == null) return ''\n if (typeof value === 'number') {\n // Use formatAxisValue if config provided\n if (formatConfig) {\n return formatAxisValue(value, formatConfig)\n }\n return value.toLocaleString()\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No'\n }\n return String(value)\n}\n"],"names":["getOrderedColumnsFromQuery","queryObject","columns","td","hasTimeDimensionForPivot","xAxisOverride","timeDim","dimensions","measures","field","measuresInXAxis","extractAndSortTimeValues","data","timeDimension","granularity","timeSet","row","rawTime","formattedTime","formatTimeValue","buildColumns","config","timeValues","getFieldLabel","dim","timeVal","groupByDimensions","grouped","dimKey","buildPivotedRows","dimensionKeys","rows","measureCount","dimensionCount","measure","dimensionKey","dimIndex","timeData","rowId","values","dimValues","idx","dataPoint","isFirstInGroup","measureRowSpan","pivotTableData","_meta","getMeasureType","measureField","meta","cube","m","DataTable","chartConfig","displayConfig","height","useCubeContext","pivotConfig","useMemo","enablePivot","pivotedData","jsx","jsxs","PivotedTable","FlatTable","leftYAxisFormat","col","PivotedTableRow","measureType","MeasureIcon","getMeasureTypeIcon","value","formatPivotCellValue","formatConfig","formatAxisValue","allColumns","queryOrder","ordered","remaining","column","index","formatCellValue"],"mappings":"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"}
1
+ {"version":3,"file":"chart-datatable-C7MS9q4Y.js","sources":["../../../src/client/utils/pivotUtils.ts","../../../src/client/components/charts/DataTable.tsx"],"sourcesContent":["/**\n * Pivot utilities for DataTable time dimension pivoting\n *\n * When a query includes a time dimension with granularity, transforms flat data\n * into a pivoted structure with time periods as columns.\n */\n\nimport type { CubeQuery } from '../types'\nimport type { CubeMeta } from '../hooks/useCubeMeta'\nimport { formatTimeValue } from './chartUtils'\n\n/**\n * Derives ordered column list from a CubeQuery object.\n * Order: dimensions, timeDimensions (as field names), measures\n *\n * @param queryObject The CubeQuery object\n * @returns Array of field names in order\n */\nexport function getOrderedColumnsFromQuery(queryObject?: CubeQuery): string[] {\n if (!queryObject) return []\n\n const columns: string[] = []\n\n // Add regular dimensions first\n if (queryObject.dimensions) {\n columns.push(...queryObject.dimensions)\n }\n\n // Add time dimensions\n if (queryObject.timeDimensions) {\n queryObject.timeDimensions.forEach(td => {\n if (!columns.includes(td.dimension)) {\n columns.push(td.dimension)\n }\n })\n }\n\n // Add measures last\n if (queryObject.measures) {\n columns.push(...queryObject.measures)\n }\n\n return columns\n}\n\n/**\n * Configuration for pivoting based on query structure\n */\nexport interface PivotConfig {\n /** Time dimension field name (e.g., \"Sales.date\") */\n timeDimension: string\n /** Time granularity (e.g., \"month\", \"day\", \"year\") */\n granularity: string\n /** Non-time dimension fields */\n dimensions: string[]\n /** Measure fields */\n measures: string[]\n}\n\n/**\n * Column definition for pivoted table\n */\nexport interface PivotColumn {\n /** Column key for data access */\n key: string\n /** Display label for column header */\n label: string\n /** Whether this is a time column (vs row identifier column) */\n isTimeColumn: boolean\n /** Whether this is the measure column */\n isMeasureColumn?: boolean\n}\n\n/**\n * Row in the pivoted table\n */\nexport interface PivotRow {\n /** Unique row identifier */\n id: string\n /** The measure field name (for icon lookup) */\n measureField: string\n /** Values keyed by column key */\n values: Record<string, any>\n /** Whether this is the first row in a dimension group (for row spanning) */\n isFirstInGroup?: boolean\n /** Number of rows to span for dimension cells (only set on first row in group) */\n dimensionRowSpan?: number\n}\n\n/**\n * Result of pivoting table data\n */\nexport interface PivotedTableData {\n /** Whether data was pivoted (has time dimension with granularity) */\n isPivoted: boolean\n /** Column definitions for the pivoted table */\n columns: PivotColumn[]\n /** Rows of pivoted data */\n rows: PivotRow[]\n}\n\n/**\n * Determines if a query has a time dimension with granularity that should trigger pivoting\n * @param queryObject The CubeQuery object\n * @param xAxisOverride Optional array of fields to use for filtering dimensions and measures\n * (for respecting chartConfig.xAxis configuration)\n * @returns PivotConfig if pivoting should occur, null otherwise\n */\nexport function hasTimeDimensionForPivot(\n queryObject?: CubeQuery,\n xAxisOverride?: string[]\n): PivotConfig | null {\n if (!queryObject?.timeDimensions?.length) return null\n\n // Find the first time dimension with granularity\n const timeDim = queryObject.timeDimensions.find(td => td.granularity)\n if (!timeDim?.granularity) return null\n\n // Must have at least one measure to pivot\n if (!queryObject.measures?.length) return null\n\n let dimensions: string[]\n let measures: string[]\n\n if (xAxisOverride && xAxisOverride.length > 0) {\n // Filter dimensions from xAxisOverride (excluding time dimension and measures)\n dimensions = xAxisOverride.filter(field => {\n // Exclude the time dimension being pivoted (it becomes columns)\n if (field === timeDim.dimension) return false\n // Exclude measures (they become row values, not dimension columns)\n if (queryObject.measures?.includes(field)) return false\n return true\n })\n\n // Filter measures from xAxisOverride - only show measures that are in xAxis\n const measuresInXAxis = xAxisOverride.filter(field =>\n queryObject.measures?.includes(field)\n )\n // If xAxis contains measures, use only those; otherwise fall back to all measures\n measures = measuresInXAxis.length > 0 ? measuresInXAxis : queryObject.measures\n } else {\n dimensions = queryObject.dimensions || []\n measures = queryObject.measures\n }\n\n // Must have at least one measure after filtering\n if (measures.length === 0) return null\n\n return {\n timeDimension: timeDim.dimension,\n granularity: timeDim.granularity,\n dimensions,\n measures\n }\n}\n\n/**\n * Extracts unique time values from data and sorts them chronologically\n */\nfunction extractAndSortTimeValues(\n data: any[],\n timeDimension: string,\n granularity: string\n): string[] {\n const timeSet = new Set<string>()\n\n data.forEach(row => {\n const rawTime = row[timeDimension]\n if (rawTime != null) {\n const formattedTime = formatTimeValue(rawTime, granularity)\n timeSet.add(formattedTime)\n }\n })\n\n // Sort chronologically - ISO date strings sort correctly alphabetically\n return Array.from(timeSet).sort()\n}\n\n/**\n * Builds column definitions for pivoted table\n * Order: Measure (if multiple) -> Dimensions -> Time columns\n */\nfunction buildColumns(\n config: PivotConfig,\n timeValues: string[],\n getFieldLabel: (field: string) => string\n): PivotColumn[] {\n const columns: PivotColumn[] = []\n\n // Add measure column first (if multiple measures)\n if (config.measures.length > 1) {\n columns.push({\n key: '__measure__',\n label: 'Measure',\n isTimeColumn: false,\n isMeasureColumn: true\n })\n }\n\n // Add dimension columns\n config.dimensions.forEach(dim => {\n columns.push({\n key: dim,\n label: getFieldLabel(dim),\n isTimeColumn: false\n })\n })\n\n // Add time columns (already sorted chronologically)\n timeValues.forEach(timeVal => {\n columns.push({\n key: timeVal,\n label: timeVal,\n isTimeColumn: true\n })\n })\n\n return columns\n}\n\n/**\n * Groups data by dimension values, then by time period\n * Returns Map<dimensionKey, Map<formattedTime, dataRow>>\n */\nfunction groupByDimensions(\n data: any[],\n config: PivotConfig\n): Map<string, Map<string, any>> {\n const grouped = new Map<string, Map<string, any>>()\n\n data.forEach(row => {\n // Build dimension key from all dimension values\n const dimKey = config.dimensions.length > 0\n ? config.dimensions.map(dim => String(row[dim] ?? '')).join('|')\n : '__all__'\n\n // Get or create time map for this dimension combo\n if (!grouped.has(dimKey)) {\n grouped.set(dimKey, new Map())\n }\n\n // Store data point by formatted time value\n const rawTime = row[config.timeDimension]\n if (rawTime != null) {\n const formattedTime = formatTimeValue(rawTime, config.granularity)\n grouped.get(dimKey)!.set(formattedTime, row)\n }\n })\n\n return grouped\n}\n\n/**\n * Builds pivoted rows from grouped data\n * Rows are grouped by measure first (all Revenue rows together, all Quantity rows together)\n * Then within each measure group, rows are ordered by dimension values\n */\nfunction buildPivotedRows(\n data: any[],\n config: PivotConfig,\n timeValues: string[],\n getFieldLabel: (field: string) => string\n): PivotRow[] {\n // Group data by dimensions and time\n const grouped = groupByDimensions(data, config)\n const dimensionKeys = Array.from(grouped.keys())\n\n const rows: PivotRow[] = []\n const measureCount = config.measures.length\n const dimensionCount = dimensionKeys.length\n\n // Iterate over measures first, then dimensions\n // This groups all rows for one measure together\n config.measures.forEach((measure) => {\n dimensionKeys.forEach((dimensionKey, dimIndex) => {\n const timeData = grouped.get(dimensionKey)!\n const rowId = measureCount > 1\n ? `${measure}|${dimensionKey}`\n : dimensionKey\n\n const values: Record<string, any> = {}\n\n // Add dimension values\n const dimValues = dimensionKey === '__all__' ? [] : dimensionKey.split('|')\n config.dimensions.forEach((dim, idx) => {\n values[dim] = dimValues[idx] ?? ''\n })\n\n // Add measure name if multiple measures (for display in Measure column)\n if (measureCount > 1) {\n values['__measure__'] = getFieldLabel(measure)\n }\n\n // Add time period values\n timeValues.forEach(timeVal => {\n const dataPoint = timeData.get(timeVal)\n values[timeVal] = dataPoint?.[measure] ?? null\n })\n\n // Track grouping for row spanning (when multiple measures)\n // First row of each measure group should span all dimension rows\n const isFirstInGroup = dimIndex === 0\n const measureRowSpan = isFirstInGroup && measureCount > 1 ? dimensionCount : undefined\n\n rows.push({\n id: rowId,\n measureField: measure,\n values,\n isFirstInGroup,\n dimensionRowSpan: measureRowSpan\n })\n })\n })\n\n return rows\n}\n\n/**\n * Pivots flat data into time-columned table structure\n *\n * @param data Raw data array from query result\n * @param config Pivot configuration\n * @param getFieldLabel Function to get display label for a field\n * @param meta Optional cube metadata for looking up measure types\n * @returns Pivoted table data structure\n */\nexport function pivotTableData(\n data: any[],\n config: PivotConfig,\n getFieldLabel: (field: string) => string,\n _meta?: CubeMeta | null\n): PivotedTableData {\n if (!data || data.length === 0) {\n return { isPivoted: true, columns: [], rows: [] }\n }\n\n // Extract unique time values and sort chronologically\n const timeValues = extractAndSortTimeValues(data, config.timeDimension, config.granularity)\n\n // Build column definitions\n const columns = buildColumns(config, timeValues, getFieldLabel)\n\n // Build pivoted rows\n const rows = buildPivotedRows(data, config, timeValues, getFieldLabel)\n\n return { isPivoted: true, columns, rows }\n}\n\n/**\n * Looks up the measure type from metadata\n *\n * @param measureField The fully qualified measure field name (e.g., \"Sales.revenue\")\n * @param meta Cube metadata\n * @returns The measure type (e.g., \"sum\", \"count\", \"avg\") or undefined\n */\nexport function getMeasureType(measureField: string, meta: CubeMeta | null): string | undefined {\n if (!meta?.cubes) return undefined\n\n for (const cube of meta.cubes) {\n const measure = cube.measures.find(m => m.name === measureField)\n if (measure) {\n return measure.type\n }\n }\n\n return undefined\n}\n","/**\n * Data Table component with time dimension pivoting\n *\n * When a query includes a time dimension with granularity, the table\n * automatically pivots to show time periods as columns.\n */\n\nimport { useMemo } from 'react'\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { getMeasureTypeIcon } from '../../icons'\nimport {\n hasTimeDimensionForPivot,\n pivotTableData,\n getMeasureType,\n getOrderedColumnsFromQuery,\n type PivotedTableData,\n type PivotColumn,\n type PivotRow\n} from '../../utils/pivotUtils'\nimport { formatAxisValue } from '../../utils/chartUtils'\nimport type { ChartProps, AxisFormatConfig } from '../../types'\n\nexport default function DataTable({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = 300\n}: ChartProps) {\n const { getFieldLabel, meta } = useCubeContext()\n\n // Detect if we should pivot based on query structure\n // Pass chartConfig.xAxis to respect user-configured column ordering\n const pivotConfig = useMemo(\n () => hasTimeDimensionForPivot(queryObject, chartConfig?.xAxis),\n [queryObject, chartConfig?.xAxis]\n )\n\n // Check if pivoting is enabled (default: true when time dimension present)\n const enablePivot = displayConfig?.pivotTimeDimension !== false\n\n // Compute pivoted data if applicable\n const pivotedData = useMemo<PivotedTableData | null>(() => {\n if (!pivotConfig || !enablePivot) return null\n return pivotTableData(data, pivotConfig, getFieldLabel, meta)\n }, [data, pivotConfig, enablePivot, getFieldLabel, meta])\n\n // Empty state\n if (!data || data.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data to display in table</div>\n </div>\n </div>\n )\n }\n\n // Render pivoted table if applicable\n if (pivotedData?.isPivoted && pivotedData.columns.length > 0) {\n return (\n <PivotedTable\n pivotedData={pivotedData}\n height={height}\n meta={meta}\n leftYAxisFormat={displayConfig?.leftYAxisFormat}\n />\n )\n }\n\n // Fallback to flat table rendering\n return (\n <FlatTable\n data={data}\n chartConfig={chartConfig}\n queryObject={queryObject}\n height={height}\n getFieldLabel={getFieldLabel}\n leftYAxisFormat={displayConfig?.leftYAxisFormat}\n />\n )\n}\n\n/**\n * Pivoted table component - renders time dimension as columns\n */\nfunction PivotedTable({\n pivotedData,\n height,\n meta,\n leftYAxisFormat\n}: {\n pivotedData: PivotedTableData\n height: number | string\n meta: any\n leftYAxisFormat?: AxisFormatConfig\n}) {\n const { columns, rows } = pivotedData\n\n if (columns.length === 0 || rows.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data to display in table</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full overflow-auto\" style={{ height }}>\n <table className=\"min-w-full divide-y border-dc-border\">\n <thead className=\"bg-dc-surface-secondary sticky top-0\">\n <tr>\n {columns.map((col: PivotColumn) => (\n <th\n key={col.key}\n className={`px-3 py-2 text-xs font-medium text-dc-text-muted uppercase tracking-wider whitespace-nowrap ${\n col.isTimeColumn ? 'text-right' : 'text-left'\n }`}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"bg-dc-surface divide-y border-dc-border\">\n {rows.map((row: PivotRow) => (\n <PivotedTableRow\n key={row.id}\n row={row}\n columns={columns}\n meta={meta}\n leftYAxisFormat={leftYAxisFormat}\n />\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * Single row in the pivoted table\n * Supports row spanning for measure cells when grouped by measure\n */\nfunction PivotedTableRow({\n row,\n columns,\n meta,\n leftYAxisFormat\n}: {\n row: PivotRow\n columns: PivotColumn[]\n meta: any\n leftYAxisFormat?: AxisFormatConfig\n}) {\n // Get measure icon for this row\n const measureType = getMeasureType(row.measureField, meta)\n const MeasureIcon = getMeasureTypeIcon(measureType)\n\n return (\n <tr className=\"hover:bg-dc-surface-secondary\">\n {columns.map((col: PivotColumn) => {\n const value = row.values[col.key]\n\n // Measure column - show icon + label with row spanning\n if (col.isMeasureColumn) {\n // Skip this cell if not first in measure group\n if (row.isFirstInGroup === false) {\n return null\n }\n\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text align-top\"\n rowSpan={row.dimensionRowSpan}\n >\n <div className=\"flex items-center\">\n <MeasureIcon className=\"w-3.5 h-3.5 mr-1.5 text-dc-text-muted shrink-0\" />\n <span>{value}</span>\n </div>\n </td>\n )\n }\n\n // Time column - right-aligned, formatted values (these are measure values)\n if (col.isTimeColumn) {\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-right text-dc-text\"\n >\n {formatPivotCellValue(value, leftYAxisFormat)}\n </td>\n )\n }\n\n // Dimension column - left-aligned (no row spanning) - no number formatting\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text\"\n >\n {formatPivotCellValue(value)}\n </td>\n )\n })}\n </tr>\n )\n}\n\n/**\n * Format cell value for pivoted table display\n * Shows \"-\" for null/undefined values\n */\nfunction formatPivotCellValue(value: any, formatConfig?: AxisFormatConfig): string {\n if (value === null || value === undefined) return '-'\n if (typeof value === 'number') {\n // Use formatAxisValue if config provided\n if (formatConfig) {\n return formatAxisValue(value, formatConfig)\n }\n // Format with locale and up to 2 decimal places\n if (Number.isInteger(value)) {\n return value.toLocaleString()\n }\n return parseFloat(value.toFixed(2)).toLocaleString()\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No'\n }\n return String(value)\n}\n\n/**\n * Flat table component - original non-pivoted table rendering\n */\nfunction FlatTable({\n data,\n chartConfig,\n queryObject,\n height,\n getFieldLabel,\n leftYAxisFormat\n}: {\n data: any[]\n chartConfig?: { xAxis?: string[] }\n queryObject?: ChartProps['queryObject']\n height: number | string\n getFieldLabel: (field: string) => string\n leftYAxisFormat?: AxisFormatConfig\n}) {\n // Get all columns available in data\n const allColumns = Object.keys(data[0] || {})\n\n // Determine column order with proper fallback:\n // 1. If xAxis is configured, use that order\n // 2. Otherwise, derive order from queryObject (dimensions + timeDimensions + measures)\n // 3. Fallback: Object.keys order\n const columns = useMemo(() => {\n // If xAxis is configured, use that order (filtered to existing columns)\n if (chartConfig?.xAxis && chartConfig.xAxis.length > 0) {\n return chartConfig.xAxis.filter(col => allColumns.includes(col))\n }\n\n // Derive order from queryObject\n const queryOrder = getOrderedColumnsFromQuery(queryObject)\n if (queryOrder.length > 0) {\n // Filter to only columns that exist in data\n const ordered = queryOrder.filter(col => allColumns.includes(col))\n // Add any columns in data that weren't in query (edge case)\n const remaining = allColumns.filter(col => !ordered.includes(col))\n return [...ordered, ...remaining]\n }\n\n // Final fallback: Object.keys order\n return allColumns\n }, [chartConfig?.xAxis, queryObject, allColumns])\n\n if (columns.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No columns available</div>\n <div className=\"text-xs text-dc-text-secondary\">Data structure is invalid</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full overflow-auto\" style={{ height }}>\n <table className=\"min-w-full divide-y border-dc-border\">\n <thead className=\"bg-dc-surface-secondary sticky top-0\">\n <tr>\n {columns.map((column) => (\n <th\n key={column}\n className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\"\n >\n {getFieldLabel(column)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"bg-dc-surface divide-y border-dc-border\">\n {data.map((row, index) => (\n <tr key={index} className=\"hover:bg-dc-surface-secondary\">\n {columns.map((column) => (\n <td\n key={column}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text\"\n >\n {formatCellValue(row[column], leftYAxisFormat)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * Format cell value for flat table display\n */\nfunction formatCellValue(value: any, formatConfig?: AxisFormatConfig): string {\n if (value == null) return ''\n if (typeof value === 'number') {\n // Use formatAxisValue if config provided\n if (formatConfig) {\n return formatAxisValue(value, formatConfig)\n }\n return value.toLocaleString()\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No'\n }\n return String(value)\n}\n"],"names":["getOrderedColumnsFromQuery","queryObject","columns","td","hasTimeDimensionForPivot","xAxisOverride","timeDim","dimensions","measures","field","measuresInXAxis","extractAndSortTimeValues","data","timeDimension","granularity","timeSet","row","rawTime","formattedTime","formatTimeValue","buildColumns","config","timeValues","getFieldLabel","dim","timeVal","groupByDimensions","grouped","dimKey","buildPivotedRows","dimensionKeys","rows","measureCount","dimensionCount","measure","dimensionKey","dimIndex","timeData","rowId","values","dimValues","idx","dataPoint","isFirstInGroup","measureRowSpan","pivotTableData","_meta","getMeasureType","measureField","meta","cube","m","DataTable","chartConfig","displayConfig","height","useCubeContext","pivotConfig","useMemo","enablePivot","pivotedData","jsx","jsxs","PivotedTable","FlatTable","leftYAxisFormat","col","PivotedTableRow","measureType","MeasureIcon","getMeasureTypeIcon","value","formatPivotCellValue","formatConfig","formatAxisValue","allColumns","queryOrder","ordered","remaining","column","index","formatCellValue"],"mappings":"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"}