drizzle-cube 0.3.21 → 0.3.22
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/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +1 -1
- package/dist/adapters/{mcp-transport-B37JTeww.cjs → mcp-transport-49vIZe0U.cjs} +91 -91
- package/dist/adapters/{mcp-transport-DHBUNdYg.js → mcp-transport-CxemGJYK.js} +2379 -2344
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/client/charts/chartConfigs.d.ts +21 -0
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/{RetentionCombinedChart-DsWhPI0q.js → RetentionCombinedChart-DpEKFYsd.js} +3 -3
- package/dist/client/chunks/RetentionCombinedChart-DpEKFYsd.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-DcZgXtPK.js → analysis-builder-BCAr4mEO.js} +9 -9
- package/dist/client/chunks/{analysis-builder-DcZgXtPK.js.map → analysis-builder-BCAr4mEO.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-ZnrPzt_d.js → analysis-builder-shared-D-5OhHaS.js} +5 -5
- package/dist/client/chunks/{analysis-builder-shared-ZnrPzt_d.js.map → analysis-builder-shared-D-5OhHaS.js.map} +1 -1
- package/dist/client/chunks/{chart-activity-grid-BUc21L0U.js → chart-activity-grid-CCGyWo1c.js} +116 -106
- package/dist/client/chunks/chart-activity-grid-CCGyWo1c.js.map +1 -0
- package/dist/client/chunks/chart-area-INsj4GFi.js +233 -0
- package/dist/client/chunks/chart-area-INsj4GFi.js.map +1 -0
- package/dist/client/chunks/chart-bar-BKRPTqiM.js +228 -0
- package/dist/client/chunks/chart-bar-BKRPTqiM.js.map +1 -0
- package/dist/client/chunks/{chart-bubble-CO7qvWR9.js → chart-bubble-BGGAQQUQ.js} +2 -2
- package/dist/client/chunks/{chart-bubble-CO7qvWR9.js.map → chart-bubble-BGGAQQUQ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-BBSNCbkb.js → chart-config-activity-grid-CAlo1cHA.js} +3 -2
- package/dist/client/chunks/{chart-config-activity-grid-BBSNCbkb.js.map → chart-config-activity-grid-CAlo1cHA.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bar-BJKGnfLt.js → chart-config-bar-soxw6m2o.js} +2 -1
- package/dist/client/chunks/chart-config-bar-soxw6m2o.js.map +1 -0
- package/dist/client/chunks/{chart-config-line-DR0ThxZy.js → chart-config-line-D5ME6w0v.js} +2 -1
- package/dist/client/chunks/chart-config-line-D5ME6w0v.js.map +1 -0
- package/dist/client/chunks/{chart-config-pie-BM5lgH-w.js → chart-config-pie-DlHa2jTy.js} +2 -1
- package/dist/client/chunks/chart-config-pie-DlHa2jTy.js.map +1 -0
- package/dist/client/chunks/{chart-config-tree-map-CLmRvvMR.js → chart-config-tree-map-IRAYf9YM.js} +3 -2
- package/dist/client/chunks/{chart-config-tree-map-CLmRvvMR.js.map → chart-config-tree-map-IRAYf9YM.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-bclSKgkZ.js → chart-data-table-BcH_h6kZ.js} +3 -3
- package/dist/client/chunks/{chart-data-table-bclSKgkZ.js.map → chart-data-table-BcH_h6kZ.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-FvDvq015.js → chart-funnel-DI8RMacf.js} +3 -3
- package/dist/client/chunks/chart-funnel-DI8RMacf.js.map +1 -0
- package/dist/client/chunks/{chart-heat-map-GpFE-PFB.js → chart-heat-map-D3xNV9ep.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-GpFE-PFB.js.map → chart-heat-map-D3xNV9ep.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-jmz-CK8X.js → chart-kpi-delta-BJMQKPor.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-jmz-CK8X.js.map → chart-kpi-delta-BJMQKPor.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-DbSmomE8.js → chart-kpi-number-B8u4tWmu.js} +2 -2
- package/dist/client/chunks/{chart-kpi-number-DbSmomE8.js.map → chart-kpi-number-B8u4tWmu.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-erI9U7PZ.js → chart-kpi-text--r1d4zAz.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-erI9U7PZ.js.map → chart-kpi-text--r1d4zAz.js.map} +1 -1
- package/dist/client/chunks/chart-line-DgFmGdWW.js +414 -0
- package/dist/client/chunks/chart-line-DgFmGdWW.js.map +1 -0
- package/dist/client/chunks/chart-pie-DC7axSwd.js +137 -0
- package/dist/client/chunks/chart-pie-DC7axSwd.js.map +1 -0
- package/dist/client/chunks/{chart-radar-BE6xsFiF.js → chart-radar-BDKgpLw5.js} +33 -33
- package/dist/client/chunks/chart-radar-BDKgpLw5.js.map +1 -0
- package/dist/client/chunks/{chart-radial-bar-BEEwtFDc.js → chart-radial-bar-BYNng7Nz.js} +7 -6
- package/dist/client/chunks/chart-radial-bar-BYNng7Nz.js.map +1 -0
- package/dist/client/chunks/{chart-sankey-Dt3KaYrH.js → chart-sankey-CpsKerey.js} +2 -2
- package/dist/client/chunks/{chart-sankey-Dt3KaYrH.js.map → chart-sankey-CpsKerey.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-gAlYkQcW.js → chart-scatter-CXqFltJg.js} +11 -11
- package/dist/client/chunks/chart-scatter-CXqFltJg.js.map +1 -0
- package/dist/client/chunks/{chart-sunburst-D0Lvdjwu.js → chart-sunburst-DSsO2CzY.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-D0Lvdjwu.js.map → chart-sunburst-DSsO2CzY.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-Bv_PYe0c.js → chart-tree-map-D_SeBBD-.js} +77 -57
- package/dist/client/chunks/chart-tree-map-D_SeBBD-.js.map +1 -0
- package/dist/client/chunks/{chartConfigRegistry-BumUIPw4.js → chartConfigRegistry-DNEbwgTc.js} +6 -6
- package/dist/client/chunks/{chartConfigRegistry-BumUIPw4.js.map → chartConfigRegistry-DNEbwgTc.js.map} +1 -1
- package/dist/client/chunks/{charts-DqWRT0TE.js → charts-CsEtJy5f.js} +17 -17
- package/dist/client/chunks/charts-CsEtJy5f.js.map +1 -0
- package/dist/client/chunks/{charts-core-BfxnhMfd.js → charts-core-8jDh3mKC.js} +64 -63
- package/dist/client/chunks/charts-core-8jDh3mKC.js.map +1 -0
- package/dist/client/chunks/{charts-loader-DCGbL50r.js → charts-loader-sNk3q8UX.js} +20 -20
- package/dist/client/chunks/{charts-loader-DCGbL50r.js.map → charts-loader-sNk3q8UX.js.map} +1 -1
- package/dist/client/chunks/{components-NmBmOEqV.js → components-BsV0_0jR.js} +3579 -2880
- package/dist/client/chunks/components-BsV0_0jR.js.map +1 -0
- package/dist/client/chunks/{hooks-D7APQ8uS.js → hooks-CKYzVf_7.js} +3 -3
- package/dist/client/chunks/{hooks-D7APQ8uS.js.map → hooks-CKYzVf_7.js.map} +1 -1
- package/dist/client/chunks/{index-CBvXpG92.js → index-_2PSgbkC.js} +270 -261
- package/dist/client/chunks/index-_2PSgbkC.js.map +1 -0
- package/dist/client/chunks/{providers-Cj7PQfXn.js → providers-BBrUJB2U.js} +2 -2
- package/dist/client/chunks/{providers-Cj7PQfXn.js.map → providers-BBrUJB2U.js.map} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-ZSi3voVl.js → useDirtyStateTracking-DDQ_Lbki.js} +2 -2
- package/dist/client/chunks/{useDirtyStateTracking-ZSi3voVl.js.map → useDirtyStateTracking-DDQ_Lbki.js.map} +1 -1
- package/dist/client/components/DrillBreadcrumb.d.ts +6 -0
- package/dist/client/components/DrillMenu.d.ts +8 -0
- package/dist/client/components.js +2 -2
- package/dist/client/hooks/useDrillInteraction.d.ts +9 -0
- package/dist/client/hooks.js +3 -3
- package/dist/client/index.js +9 -9
- package/dist/client/providers.js +1 -1
- package/dist/client/styles.css +1 -1
- package/dist/client/types/drill.d.ts +240 -0
- package/dist/client/types.d.ts +53 -2
- package/dist/client/utils/drillQueryBuilder.d.ts +41 -0
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +25 -25
- package/dist/server/index.d.ts +78 -0
- package/dist/server/index.js +2117 -2082
- package/package.json +1 -1
- package/dist/client/chunks/RetentionCombinedChart-DsWhPI0q.js.map +0 -1
- package/dist/client/chunks/chart-activity-grid-BUc21L0U.js.map +0 -1
- package/dist/client/chunks/chart-area-B_64FScj.js +0 -190
- package/dist/client/chunks/chart-area-B_64FScj.js.map +0 -1
- package/dist/client/chunks/chart-bar-Ctiy2tpQ.js +0 -216
- package/dist/client/chunks/chart-bar-Ctiy2tpQ.js.map +0 -1
- package/dist/client/chunks/chart-config-bar-BJKGnfLt.js.map +0 -1
- package/dist/client/chunks/chart-config-line-DR0ThxZy.js.map +0 -1
- package/dist/client/chunks/chart-config-pie-BM5lgH-w.js.map +0 -1
- package/dist/client/chunks/chart-funnel-FvDvq015.js.map +0 -1
- package/dist/client/chunks/chart-line-B0YOZ88n.js +0 -364
- package/dist/client/chunks/chart-line-B0YOZ88n.js.map +0 -1
- package/dist/client/chunks/chart-pie-CImB6r4F.js +0 -125
- package/dist/client/chunks/chart-pie-CImB6r4F.js.map +0 -1
- package/dist/client/chunks/chart-radar-BE6xsFiF.js.map +0 -1
- package/dist/client/chunks/chart-radial-bar-BEEwtFDc.js.map +0 -1
- package/dist/client/chunks/chart-scatter-gAlYkQcW.js.map +0 -1
- package/dist/client/chunks/chart-tree-map-Bv_PYe0c.js.map +0 -1
- package/dist/client/chunks/charts-DqWRT0TE.js.map +0 -1
- package/dist/client/chunks/charts-core-BfxnhMfd.js.map +0 -1
- package/dist/client/chunks/components-NmBmOEqV.js.map +0 -1
- package/dist/client/chunks/index-CBvXpG92.js.map +0 -1
package/dist/client/chunks/{chart-sunburst-D0Lvdjwu.js.map → chart-sunburst-DSsO2CzY.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-sunburst-D0Lvdjwu.js","sources":["../../../src/client/components/charts/SunburstChart.tsx"],"sourcesContent":["/**\n * SunburstChart Component\n *\n * Visualizes flow data using a radial sunburst diagram showing paths from a starting step.\n * Works with the same data as SankeyChart but displays it as hierarchical rings.\n *\n * The chart displays:\n * - Center: Starting step (layer 0)\n * - Outward rings: Steps after the starting step (layers 1, 2, 3...)\n * - Values indicating count of entities following each path\n *\n * Note: Unlike Sankey, Sunburst only shows \"after\" steps for cleaner visualization.\n */\n\nimport React, { useMemo, useRef, useState, useEffect } from 'react'\nimport { SunburstChart as RechartsSunburst, ResponsiveContainer, Tooltip } from 'recharts'\nimport { CHART_COLORS } from '../../utils/chartConstants'\nimport type { ChartProps } from '../../types'\nimport type { FlowChartData, SankeyNode, SankeyLink } from '../../types/flow'\nimport { isSankeyData } from '../../types/flow'\n\n/**\n * Hierarchical data structure for Recharts Sunburst\n */\ninterface SunburstNode {\n name: string\n value?: number\n fill?: string\n children?: SunburstNode[]\n /** Original event name (before path prefix was added) */\n originalName?: string\n}\n\n\n/**\n * Extract FlowChartData from various data formats\n */\nfunction extractFlowData(data: unknown[]): FlowChartData | null {\n if (!data || data.length === 0) return null\n\n // If first element is already FlowChartData (server returns as single-row array)\n if (isSankeyData(data[0])) {\n return data[0] as FlowChartData\n }\n\n // If data itself is FlowChartData shape\n if (isSankeyData(data)) {\n return data as unknown as FlowChartData\n }\n\n // Check if data is an array with nodes and links at top level\n const asAny = data as unknown as Record<string, unknown>\n if (asAny.nodes && asAny.links) {\n return asAny as unknown as FlowChartData\n }\n\n return null\n}\n\n/**\n * Transform FlowChartData (nodes + links) into hierarchical Sunburst format\n * Only includes layer 0 (starting) and positive layers (after steps)\n *\n * The transformation builds a tree where:\n * - Root = starting event(s) at layer 0\n * - Children = events linked from parent, following the flow\n * - Each path in the tree represents a unique user journey\n */\nfunction transformToSunburstFormat(\n data: FlowChartData,\n colorPalette?: string[]\n): SunburstNode | null {\n const { nodes, links } = data\n\n if (!nodes || nodes.length === 0) return null\n\n // Filter to only include layer 0 and positive layers (after steps)\n const afterNodes = nodes.filter((n) => n.layer >= 0)\n if (afterNodes.length === 0) return null\n\n // Use theme colors - either from palette or default CHART_COLORS\n const colors = colorPalette || CHART_COLORS\n\n // Get unique event names and create a color map\n // This ensures each event type gets a consistent, distinct color\n const uniqueNames = [...new Set(afterNodes.map((n) => n.name))]\n const colorMap = new Map<string, string>()\n uniqueNames.forEach((name, index) => {\n colorMap.set(name, colors[index % colors.length])\n })\n\n // Create a map of node IDs for quick lookup\n const nodeMap = new Map<string, SankeyNode>()\n afterNodes.forEach((node) => nodeMap.set(node.id, node))\n\n // Create a map of links from source to targets\n // Key: source node ID, Value: array of links from that source\n const linksBySource = new Map<string, SankeyLink[]>()\n links.forEach((link) => {\n // Only include links where source is in our afterNodes set\n if (!nodeMap.has(link.source)) return\n const sourceLinks = linksBySource.get(link.source) || []\n sourceLinks.push(link)\n linksBySource.set(link.source, sourceLinks)\n })\n\n // Find max layer for determining depth\n const maxLayer = Math.max(...afterNodes.map((n) => n.layer))\n\n // Counter for generating unique IDs\n let nodeCounter = 0\n\n /**\n * Recursively build children for a node by following outgoing links\n * Each link becomes a child node in the tree\n *\n * @param nodeId - The source node ID to build children from\n * @param currentLayer - Current layer depth\n * @param pathPrefix - Path from root to this node (for unique naming)\n */\n function buildChildren(nodeId: string, currentLayer: number, pathPrefix: string): SunburstNode[] {\n if (currentLayer >= maxLayer) return []\n\n const outgoingLinks = linksBySource.get(nodeId) || []\n if (outgoingLinks.length === 0) return []\n\n // Filter and map links to children\n const children: SunburstNode[] = []\n\n for (const link of outgoingLinks) {\n const targetNode = nodeMap.get(link.target)\n\n // Only include links to nodes in the next layer\n if (!targetNode || targetNode.layer !== currentLayer + 1) continue\n\n // Generate a unique name by including counter to avoid React key collisions\n nodeCounter++\n const uniqueName = `${targetNode.name}_${nodeCounter}`\n\n // Recursively build grandchildren with updated path\n const newPath = pathPrefix ? `${pathPrefix}→${targetNode.name}` : targetNode.name\n const grandchildren = buildChildren(link.target, currentLayer + 1, newPath)\n\n const child: SunburstNode = {\n name: uniqueName,\n originalName: targetNode.name,\n value: link.value,\n fill: colorMap.get(targetNode.name) || colors[0],\n }\n\n if (grandchildren.length > 0) {\n child.children = grandchildren\n }\n\n children.push(child)\n }\n\n return children\n }\n\n // Get starting nodes (layer 0)\n const startingNodes = afterNodes.filter((n) => n.layer === 0)\n if (startingNodes.length === 0) return null\n\n // Build the tree starting from layer 0 nodes\n if (startingNodes.length === 1) {\n // Single starting node - use it as root\n const startNode = startingNodes[0]\n const children = buildChildren(startNode.id, 0, startNode.name)\n\n const result: SunburstNode = {\n name: startNode.name,\n originalName: startNode.name,\n value: startNode.value || children.reduce((sum, c) => sum + (c.value || 0), 0),\n fill: colorMap.get(startNode.name) || colors[0],\n }\n\n if (children.length > 0) {\n result.children = children\n }\n\n return result\n }\n\n // Multiple starting nodes - create a virtual root\n const rootChildren = startingNodes.map((startNode, index) => {\n nodeCounter++\n const children = buildChildren(startNode.id, 0, startNode.name)\n\n const child: SunburstNode = {\n name: `${startNode.name}_root_${index}`,\n originalName: startNode.name,\n value: startNode.value || children.reduce((sum, c) => sum + (c.value || 0), 0),\n fill: colorMap.get(startNode.name) || colors[0],\n }\n\n if (children.length > 0) {\n child.children = children\n }\n\n return child\n })\n\n return {\n name: 'Start',\n originalName: 'Start',\n children: rootChildren,\n }\n}\n\n/**\n * Custom tooltip for Sunburst chart\n * Shows the original event name (not the unique key used internally)\n */\nfunction SunburstTooltip({\n active,\n payload,\n}: {\n active?: boolean\n payload?: Array<{ payload: SunburstNode }>\n}) {\n if (!active || !payload || payload.length === 0) return null\n\n const data = payload[0].payload\n // Use originalName if available, otherwise fall back to name\n const displayName = data.originalName || data.name\n\n return (\n <div className=\"bg-dc-surface dc:border border-dc-border dc:rounded-md dc:px-3 dc:py-2 dc:shadow-lg dc:text-sm\">\n <div className=\"dc:font-medium text-dc-text\">{displayName}</div>\n {data.value !== undefined && (\n <div className=\"text-dc-text-secondary dc:mt-1\">\n <span className=\"dc:font-medium\">{data.value.toLocaleString()}</span> entities\n </div>\n )}\n </div>\n )\n}\n\n/**\n * SunburstChart Component\n *\n * Renders a sunburst diagram visualization from FlowChartData.\n * Shows hierarchical flow paths radiating from a central starting step.\n */\nconst SunburstChart = React.memo(function SunburstChart({\n data,\n height = '100%',\n colorPalette,\n displayConfig,\n}: ChartProps) {\n // Track chart area dimensions (not the full container which includes footer)\n const chartAreaRef = useRef<HTMLDivElement>(null)\n const [chartSize, setChartSize] = useState({ width: 400, height: 400 })\n\n useEffect(() => {\n const updateSize = () => {\n if (chartAreaRef.current) {\n setChartSize({\n width: chartAreaRef.current.offsetWidth,\n height: chartAreaRef.current.offsetHeight,\n })\n }\n }\n updateSize()\n window.addEventListener('resize', updateSize)\n\n // Use ResizeObserver for more accurate size tracking\n const resizeObserver = new ResizeObserver(updateSize)\n if (chartAreaRef.current) {\n resizeObserver.observe(chartAreaRef.current)\n }\n\n return () => {\n window.removeEventListener('resize', updateSize)\n resizeObserver.disconnect()\n }\n }, [])\n\n // Get display config options\n const displayConfigAny = displayConfig as Record<string, unknown> | undefined\n const innerRadius = (displayConfigAny?.innerRadius as number) ?? 40\n\n // Extract and transform data\n const sunburstData = useMemo(() => {\n const extracted = extractFlowData(data || [])\n if (!extracted) return null\n\n return transformToSunburstFormat(extracted, colorPalette?.colors || CHART_COLORS)\n }, [data, colorPalette])\n\n // Calculate summary stats from original flow data\n const summaryStats = useMemo(() => {\n const extracted = extractFlowData(data || [])\n if (!extracted) return null\n\n // Only count after nodes (layer >= 0)\n const afterNodes = extracted.nodes.filter((n) => n.layer >= 0)\n const afterLinks = extracted.links.filter((link) => {\n const sourceNode = extracted.nodes.find((n) => n.id === link.source)\n return sourceNode && sourceNode.layer >= 0\n })\n\n const totalEntities = extracted.nodes\n .filter((n) => n.layer === 0)\n .reduce((sum, n) => sum + (n.value || 0), 0)\n\n return {\n nodeCount: afterNodes.length,\n linkCount: afterLinks.length,\n totalEntities,\n }\n }, [data])\n\n // Handle no data\n if (!data || data.length === 0 || !sunburstData) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\"\n style={{ height }}\n >\n <div className=\"text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No flow data</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n Configure a flow analysis with a starting step and event dimension\n </div>\n </div>\n </div>\n )\n }\n\n // Calculate outer radius based on chart area size\n const minDimension = Math.min(chartSize.width, chartSize.height)\n const outerRadius = Math.max(minDimension / 2 - 40, 100)\n\n // Get root node info for center label\n const rootName = sunburstData.originalName || sunburstData.name\n const rootValue = sunburstData.value\n\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n {/* Sunburst Diagram */}\n <div ref={chartAreaRef} className=\"dc:flex-1 dc:min-h-0 dc:relative\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RechartsSunburst\n data={sunburstData}\n dataKey=\"value\"\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n stroke=\"var(--dc-bg)\"\n >\n <Tooltip content={<SunburstTooltip />} />\n </RechartsSunburst>\n </ResponsiveContainer>\n\n {/* Center label showing the root node (starting event) */}\n {innerRadius > 0 && (\n <div\n className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none\"\n style={{ zIndex: 10 }}\n >\n <div className=\"text-center\">\n <div className=\"dc:text-sm dc:font-semibold text-dc-text\">{rootName}</div>\n {rootValue !== undefined && (\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {rootValue.toLocaleString()}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Summary Footer */}\n {!displayConfigAny?.hideSummaryFooter && summaryStats && (\n <div className=\"dc:flex-shrink-0 dc:px-4 dc:py-2 dc:border-t border-dc-border bg-dc-surface-secondary\">\n <div className=\"dc:flex dc:items-center dc:justify-between dc:text-sm\">\n <div className=\"text-dc-text-muted\">\n <span className=\"dc:font-medium\">{summaryStats.nodeCount}</span> events (after)\n </div>\n <div className=\"text-dc-text\">\n <span className=\"text-dc-text-muted\">Paths:</span>{' '}\n <span className=\"dc:font-medium\">{summaryStats.linkCount}</span>\n </div>\n <div className=\"text-dc-text-muted\">\n <span className=\"dc:font-medium\">{summaryStats.totalEntities.toLocaleString()}</span>{' '}\n starting entities\n </div>\n </div>\n </div>\n )}\n </div>\n )\n})\n\nexport default SunburstChart\n"],"names":["extractFlowData","data","isSankeyData","asAny","transformToSunburstFormat","colorPalette","nodes","links","afterNodes","n","colors","CHART_COLORS","uniqueNames","colorMap","name","index","nodeMap","node","linksBySource","link","sourceLinks","maxLayer","nodeCounter","buildChildren","nodeId","currentLayer","pathPrefix","outgoingLinks","children","targetNode","uniqueName","grandchildren","child","startingNodes","startNode","result","sum","c","SunburstTooltip","active","payload","displayName","jsxs","jsx","SunburstChart","React","height","displayConfig","chartAreaRef","useRef","chartSize","setChartSize","useState","useEffect","updateSize","resizeObserver","displayConfigAny","innerRadius","sunburstData","useMemo","extracted","summaryStats","afterLinks","sourceNode","totalEntities","minDimension","outerRadius","rootName","rootValue","ResponsiveContainer","RechartsSunburst","Tooltip"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-sunburst-DSsO2CzY.js","sources":["../../../src/client/components/charts/SunburstChart.tsx"],"sourcesContent":["/**\n * SunburstChart Component\n *\n * Visualizes flow data using a radial sunburst diagram showing paths from a starting step.\n * Works with the same data as SankeyChart but displays it as hierarchical rings.\n *\n * The chart displays:\n * - Center: Starting step (layer 0)\n * - Outward rings: Steps after the starting step (layers 1, 2, 3...)\n * - Values indicating count of entities following each path\n *\n * Note: Unlike Sankey, Sunburst only shows \"after\" steps for cleaner visualization.\n */\n\nimport React, { useMemo, useRef, useState, useEffect } from 'react'\nimport { SunburstChart as RechartsSunburst, ResponsiveContainer, Tooltip } from 'recharts'\nimport { CHART_COLORS } from '../../utils/chartConstants'\nimport type { ChartProps } from '../../types'\nimport type { FlowChartData, SankeyNode, SankeyLink } from '../../types/flow'\nimport { isSankeyData } from '../../types/flow'\n\n/**\n * Hierarchical data structure for Recharts Sunburst\n */\ninterface SunburstNode {\n name: string\n value?: number\n fill?: string\n children?: SunburstNode[]\n /** Original event name (before path prefix was added) */\n originalName?: string\n}\n\n\n/**\n * Extract FlowChartData from various data formats\n */\nfunction extractFlowData(data: unknown[]): FlowChartData | null {\n if (!data || data.length === 0) return null\n\n // If first element is already FlowChartData (server returns as single-row array)\n if (isSankeyData(data[0])) {\n return data[0] as FlowChartData\n }\n\n // If data itself is FlowChartData shape\n if (isSankeyData(data)) {\n return data as unknown as FlowChartData\n }\n\n // Check if data is an array with nodes and links at top level\n const asAny = data as unknown as Record<string, unknown>\n if (asAny.nodes && asAny.links) {\n return asAny as unknown as FlowChartData\n }\n\n return null\n}\n\n/**\n * Transform FlowChartData (nodes + links) into hierarchical Sunburst format\n * Only includes layer 0 (starting) and positive layers (after steps)\n *\n * The transformation builds a tree where:\n * - Root = starting event(s) at layer 0\n * - Children = events linked from parent, following the flow\n * - Each path in the tree represents a unique user journey\n */\nfunction transformToSunburstFormat(\n data: FlowChartData,\n colorPalette?: string[]\n): SunburstNode | null {\n const { nodes, links } = data\n\n if (!nodes || nodes.length === 0) return null\n\n // Filter to only include layer 0 and positive layers (after steps)\n const afterNodes = nodes.filter((n) => n.layer >= 0)\n if (afterNodes.length === 0) return null\n\n // Use theme colors - either from palette or default CHART_COLORS\n const colors = colorPalette || CHART_COLORS\n\n // Get unique event names and create a color map\n // This ensures each event type gets a consistent, distinct color\n const uniqueNames = [...new Set(afterNodes.map((n) => n.name))]\n const colorMap = new Map<string, string>()\n uniqueNames.forEach((name, index) => {\n colorMap.set(name, colors[index % colors.length])\n })\n\n // Create a map of node IDs for quick lookup\n const nodeMap = new Map<string, SankeyNode>()\n afterNodes.forEach((node) => nodeMap.set(node.id, node))\n\n // Create a map of links from source to targets\n // Key: source node ID, Value: array of links from that source\n const linksBySource = new Map<string, SankeyLink[]>()\n links.forEach((link) => {\n // Only include links where source is in our afterNodes set\n if (!nodeMap.has(link.source)) return\n const sourceLinks = linksBySource.get(link.source) || []\n sourceLinks.push(link)\n linksBySource.set(link.source, sourceLinks)\n })\n\n // Find max layer for determining depth\n const maxLayer = Math.max(...afterNodes.map((n) => n.layer))\n\n // Counter for generating unique IDs\n let nodeCounter = 0\n\n /**\n * Recursively build children for a node by following outgoing links\n * Each link becomes a child node in the tree\n *\n * @param nodeId - The source node ID to build children from\n * @param currentLayer - Current layer depth\n * @param pathPrefix - Path from root to this node (for unique naming)\n */\n function buildChildren(nodeId: string, currentLayer: number, pathPrefix: string): SunburstNode[] {\n if (currentLayer >= maxLayer) return []\n\n const outgoingLinks = linksBySource.get(nodeId) || []\n if (outgoingLinks.length === 0) return []\n\n // Filter and map links to children\n const children: SunburstNode[] = []\n\n for (const link of outgoingLinks) {\n const targetNode = nodeMap.get(link.target)\n\n // Only include links to nodes in the next layer\n if (!targetNode || targetNode.layer !== currentLayer + 1) continue\n\n // Generate a unique name by including counter to avoid React key collisions\n nodeCounter++\n const uniqueName = `${targetNode.name}_${nodeCounter}`\n\n // Recursively build grandchildren with updated path\n const newPath = pathPrefix ? `${pathPrefix}→${targetNode.name}` : targetNode.name\n const grandchildren = buildChildren(link.target, currentLayer + 1, newPath)\n\n const child: SunburstNode = {\n name: uniqueName,\n originalName: targetNode.name,\n value: link.value,\n fill: colorMap.get(targetNode.name) || colors[0],\n }\n\n if (grandchildren.length > 0) {\n child.children = grandchildren\n }\n\n children.push(child)\n }\n\n return children\n }\n\n // Get starting nodes (layer 0)\n const startingNodes = afterNodes.filter((n) => n.layer === 0)\n if (startingNodes.length === 0) return null\n\n // Build the tree starting from layer 0 nodes\n if (startingNodes.length === 1) {\n // Single starting node - use it as root\n const startNode = startingNodes[0]\n const children = buildChildren(startNode.id, 0, startNode.name)\n\n const result: SunburstNode = {\n name: startNode.name,\n originalName: startNode.name,\n value: startNode.value || children.reduce((sum, c) => sum + (c.value || 0), 0),\n fill: colorMap.get(startNode.name) || colors[0],\n }\n\n if (children.length > 0) {\n result.children = children\n }\n\n return result\n }\n\n // Multiple starting nodes - create a virtual root\n const rootChildren = startingNodes.map((startNode, index) => {\n nodeCounter++\n const children = buildChildren(startNode.id, 0, startNode.name)\n\n const child: SunburstNode = {\n name: `${startNode.name}_root_${index}`,\n originalName: startNode.name,\n value: startNode.value || children.reduce((sum, c) => sum + (c.value || 0), 0),\n fill: colorMap.get(startNode.name) || colors[0],\n }\n\n if (children.length > 0) {\n child.children = children\n }\n\n return child\n })\n\n return {\n name: 'Start',\n originalName: 'Start',\n children: rootChildren,\n }\n}\n\n/**\n * Custom tooltip for Sunburst chart\n * Shows the original event name (not the unique key used internally)\n */\nfunction SunburstTooltip({\n active,\n payload,\n}: {\n active?: boolean\n payload?: Array<{ payload: SunburstNode }>\n}) {\n if (!active || !payload || payload.length === 0) return null\n\n const data = payload[0].payload\n // Use originalName if available, otherwise fall back to name\n const displayName = data.originalName || data.name\n\n return (\n <div className=\"bg-dc-surface dc:border border-dc-border dc:rounded-md dc:px-3 dc:py-2 dc:shadow-lg dc:text-sm\">\n <div className=\"dc:font-medium text-dc-text\">{displayName}</div>\n {data.value !== undefined && (\n <div className=\"text-dc-text-secondary dc:mt-1\">\n <span className=\"dc:font-medium\">{data.value.toLocaleString()}</span> entities\n </div>\n )}\n </div>\n )\n}\n\n/**\n * SunburstChart Component\n *\n * Renders a sunburst diagram visualization from FlowChartData.\n * Shows hierarchical flow paths radiating from a central starting step.\n */\nconst SunburstChart = React.memo(function SunburstChart({\n data,\n height = '100%',\n colorPalette,\n displayConfig,\n}: ChartProps) {\n // Track chart area dimensions (not the full container which includes footer)\n const chartAreaRef = useRef<HTMLDivElement>(null)\n const [chartSize, setChartSize] = useState({ width: 400, height: 400 })\n\n useEffect(() => {\n const updateSize = () => {\n if (chartAreaRef.current) {\n setChartSize({\n width: chartAreaRef.current.offsetWidth,\n height: chartAreaRef.current.offsetHeight,\n })\n }\n }\n updateSize()\n window.addEventListener('resize', updateSize)\n\n // Use ResizeObserver for more accurate size tracking\n const resizeObserver = new ResizeObserver(updateSize)\n if (chartAreaRef.current) {\n resizeObserver.observe(chartAreaRef.current)\n }\n\n return () => {\n window.removeEventListener('resize', updateSize)\n resizeObserver.disconnect()\n }\n }, [])\n\n // Get display config options\n const displayConfigAny = displayConfig as Record<string, unknown> | undefined\n const innerRadius = (displayConfigAny?.innerRadius as number) ?? 40\n\n // Extract and transform data\n const sunburstData = useMemo(() => {\n const extracted = extractFlowData(data || [])\n if (!extracted) return null\n\n return transformToSunburstFormat(extracted, colorPalette?.colors || CHART_COLORS)\n }, [data, colorPalette])\n\n // Calculate summary stats from original flow data\n const summaryStats = useMemo(() => {\n const extracted = extractFlowData(data || [])\n if (!extracted) return null\n\n // Only count after nodes (layer >= 0)\n const afterNodes = extracted.nodes.filter((n) => n.layer >= 0)\n const afterLinks = extracted.links.filter((link) => {\n const sourceNode = extracted.nodes.find((n) => n.id === link.source)\n return sourceNode && sourceNode.layer >= 0\n })\n\n const totalEntities = extracted.nodes\n .filter((n) => n.layer === 0)\n .reduce((sum, n) => sum + (n.value || 0), 0)\n\n return {\n nodeCount: afterNodes.length,\n linkCount: afterLinks.length,\n totalEntities,\n }\n }, [data])\n\n // Handle no data\n if (!data || data.length === 0 || !sunburstData) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\"\n style={{ height }}\n >\n <div className=\"text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No flow data</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n Configure a flow analysis with a starting step and event dimension\n </div>\n </div>\n </div>\n )\n }\n\n // Calculate outer radius based on chart area size\n const minDimension = Math.min(chartSize.width, chartSize.height)\n const outerRadius = Math.max(minDimension / 2 - 40, 100)\n\n // Get root node info for center label\n const rootName = sunburstData.originalName || sunburstData.name\n const rootValue = sunburstData.value\n\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n {/* Sunburst Diagram */}\n <div ref={chartAreaRef} className=\"dc:flex-1 dc:min-h-0 dc:relative\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RechartsSunburst\n data={sunburstData}\n dataKey=\"value\"\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n stroke=\"var(--dc-bg)\"\n >\n <Tooltip content={<SunburstTooltip />} />\n </RechartsSunburst>\n </ResponsiveContainer>\n\n {/* Center label showing the root node (starting event) */}\n {innerRadius > 0 && (\n <div\n className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none\"\n style={{ zIndex: 10 }}\n >\n <div className=\"text-center\">\n <div className=\"dc:text-sm dc:font-semibold text-dc-text\">{rootName}</div>\n {rootValue !== undefined && (\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {rootValue.toLocaleString()}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Summary Footer */}\n {!displayConfigAny?.hideSummaryFooter && summaryStats && (\n <div className=\"dc:flex-shrink-0 dc:px-4 dc:py-2 dc:border-t border-dc-border bg-dc-surface-secondary\">\n <div className=\"dc:flex dc:items-center dc:justify-between dc:text-sm\">\n <div className=\"text-dc-text-muted\">\n <span className=\"dc:font-medium\">{summaryStats.nodeCount}</span> events (after)\n </div>\n <div className=\"text-dc-text\">\n <span className=\"text-dc-text-muted\">Paths:</span>{' '}\n <span className=\"dc:font-medium\">{summaryStats.linkCount}</span>\n </div>\n <div className=\"text-dc-text-muted\">\n <span className=\"dc:font-medium\">{summaryStats.totalEntities.toLocaleString()}</span>{' '}\n starting entities\n </div>\n </div>\n </div>\n )}\n </div>\n )\n})\n\nexport default SunburstChart\n"],"names":["extractFlowData","data","isSankeyData","asAny","transformToSunburstFormat","colorPalette","nodes","links","afterNodes","n","colors","CHART_COLORS","uniqueNames","colorMap","name","index","nodeMap","node","linksBySource","link","sourceLinks","maxLayer","nodeCounter","buildChildren","nodeId","currentLayer","pathPrefix","outgoingLinks","children","targetNode","uniqueName","grandchildren","child","startingNodes","startNode","result","sum","c","SunburstTooltip","active","payload","displayName","jsxs","jsx","SunburstChart","React","height","displayConfig","chartAreaRef","useRef","chartSize","setChartSize","useState","useEffect","updateSize","resizeObserver","displayConfigAny","innerRadius","sunburstData","useMemo","extracted","summaryStats","afterLinks","sourceNode","totalEntities","minDimension","outerRadius","rootName","rootValue","ResponsiveContainer","RechartsSunburst","Tooltip"],"mappings":"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"}
|
|
@@ -1,61 +1,63 @@
|
|
|
1
1
|
import { jsx as n, jsxs as h } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import { Treemap as
|
|
4
|
-
import { scaleQuantize as
|
|
5
|
-
import { u as
|
|
6
|
-
const
|
|
2
|
+
import I, { useState as D } from "react";
|
|
3
|
+
import { Treemap as H } from "recharts";
|
|
4
|
+
import { scaleQuantize as _, scaleOrdinal as U } from "d3";
|
|
5
|
+
import { u as $, g as B, h as A, d as z, c as y, f as v, a as G, b as W } from "./charts-core-8jDh3mKC.js";
|
|
6
|
+
const ee = I.memo(function({
|
|
7
7
|
data: c,
|
|
8
8
|
chartConfig: f,
|
|
9
|
-
displayConfig:
|
|
9
|
+
displayConfig: w = {},
|
|
10
10
|
queryObject: L,
|
|
11
|
-
height:
|
|
12
|
-
colorPalette: p
|
|
11
|
+
height: u = "100%",
|
|
12
|
+
colorPalette: p,
|
|
13
|
+
onDataPointClick: b,
|
|
14
|
+
drillEnabled: Y
|
|
13
15
|
}) {
|
|
14
|
-
const [
|
|
16
|
+
const [j, T] = D(null), C = $();
|
|
15
17
|
try {
|
|
16
18
|
const o = {
|
|
17
|
-
showTooltip:
|
|
18
|
-
showLegend:
|
|
19
|
-
leftYAxisFormat:
|
|
19
|
+
showTooltip: w?.showTooltip ?? !0,
|
|
20
|
+
showLegend: w?.showLegend ?? !0,
|
|
21
|
+
leftYAxisFormat: w?.leftYAxisFormat
|
|
20
22
|
};
|
|
21
23
|
if (!c || c.length === 0)
|
|
22
|
-
return /* @__PURE__ */ n("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted", style: { height:
|
|
24
|
+
return /* @__PURE__ */ n("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted", style: { height: u }, children: /* @__PURE__ */ h("div", { className: "text-center", children: [
|
|
23
25
|
/* @__PURE__ */ n("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "No data available" }),
|
|
24
26
|
/* @__PURE__ */ n("div", { className: "dc:text-xs text-dc-text-secondary", children: "No data points to display in treemap chart" })
|
|
25
27
|
] }) });
|
|
26
|
-
let
|
|
28
|
+
let x, F = !1, a;
|
|
27
29
|
if (f?.xAxis && f?.yAxis) {
|
|
28
30
|
const t = Array.isArray(f.xAxis) ? f.xAxis[0] : f.xAxis, e = Array.isArray(f.yAxis) ? f.yAxis[0] : f.yAxis;
|
|
29
31
|
a = Array.isArray(f.series) ? f.series[0] : f.series;
|
|
30
|
-
const d =
|
|
32
|
+
const d = B(L, t);
|
|
31
33
|
if (a) {
|
|
32
34
|
const r = c.map((s) => {
|
|
33
35
|
const i = s[a];
|
|
34
36
|
return typeof i == "string" ? parseFloat(i) : i;
|
|
35
37
|
}).filter((s) => !isNaN(s));
|
|
36
|
-
if (
|
|
37
|
-
const s = Math.min(...r), i = Math.max(...r), l =
|
|
38
|
-
|
|
39
|
-
const
|
|
38
|
+
if (F = r.length === c.length && r.every((s) => typeof s == "number"), F) {
|
|
39
|
+
const s = Math.min(...r), i = Math.max(...r), l = _().domain([s, i]).range(A);
|
|
40
|
+
x = c.map((m) => {
|
|
41
|
+
const M = typeof m[a] == "string" ? parseFloat(m[a]) : m[a], g = l(M);
|
|
40
42
|
return {
|
|
41
|
-
name:
|
|
43
|
+
name: z(m[t], d) || String(m[t]) || "Unknown",
|
|
42
44
|
size: typeof m[e] == "string" ? parseFloat(m[e]) : m[e] || 0,
|
|
43
|
-
fill:
|
|
45
|
+
fill: g,
|
|
44
46
|
series: String(m[a])
|
|
45
47
|
};
|
|
46
48
|
});
|
|
47
49
|
} else {
|
|
48
|
-
const s = [...new Set(c.map((l) => String(l[a])))], i =
|
|
49
|
-
|
|
50
|
-
name:
|
|
50
|
+
const s = [...new Set(c.map((l) => String(l[a])))], i = U().domain(s).range(p?.colors || y);
|
|
51
|
+
x = c.map((l) => ({
|
|
52
|
+
name: z(l[t], d) || String(l[t]) || "Unknown",
|
|
51
53
|
size: typeof l[e] == "string" ? parseFloat(l[e]) : l[e] || 0,
|
|
52
54
|
fill: i(String(l[a])),
|
|
53
55
|
series: String(l[a])
|
|
54
56
|
}));
|
|
55
57
|
}
|
|
56
58
|
} else
|
|
57
|
-
|
|
58
|
-
name:
|
|
59
|
+
x = c.map((r, s) => ({
|
|
60
|
+
name: z(r[t], d) || String(r[t]) || "Unknown",
|
|
59
61
|
size: typeof r[e] == "string" ? parseFloat(r[e]) : r[e] || 0,
|
|
60
62
|
fill: p?.colors && p.colors[s % p.colors.length] || y[s % y.length]
|
|
61
63
|
}));
|
|
@@ -66,11 +68,11 @@ const J = V.memo(function({
|
|
|
66
68
|
(s) => typeof t[s] == "number" && s !== d
|
|
67
69
|
) || e[1];
|
|
68
70
|
if (!r)
|
|
69
|
-
return /* @__PURE__ */ n("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning", style: { height:
|
|
71
|
+
return /* @__PURE__ */ n("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning", style: { height: u }, children: /* @__PURE__ */ h("div", { className: "text-center", children: [
|
|
70
72
|
/* @__PURE__ */ n("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "Configuration Error" }),
|
|
71
73
|
/* @__PURE__ */ n("div", { className: "dc:text-xs", children: "No numeric field found for treemap chart size" })
|
|
72
74
|
] }) });
|
|
73
|
-
|
|
75
|
+
x = c.map((s, i) => {
|
|
74
76
|
let l = s[d];
|
|
75
77
|
return typeof l == "boolean" ? l = l ? "Active" : "Inactive" : l === "true" || l === "false" ? l = l === "true" ? "Active" : "Inactive" : l = String(l), {
|
|
76
78
|
name: l,
|
|
@@ -79,14 +81,29 @@ const J = V.memo(function({
|
|
|
79
81
|
};
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
|
-
if (
|
|
83
|
-
return /* @__PURE__ */ n("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted", style: { height:
|
|
84
|
+
if (x = x.filter((t) => t.size != null && t.size > 0), x.length === 0)
|
|
85
|
+
return /* @__PURE__ */ n("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted", style: { height: u }, children: /* @__PURE__ */ h("div", { className: "text-center", children: [
|
|
84
86
|
/* @__PURE__ */ n("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "No valid data" }),
|
|
85
87
|
/* @__PURE__ */ n("div", { className: "dc:text-xs text-dc-text-secondary", children: "No valid data points for treemap chart after transformation" })
|
|
86
88
|
] }) });
|
|
87
|
-
const
|
|
89
|
+
const R = (t) => {
|
|
88
90
|
const { x: e, y: d, width: r, height: s, index: i, name: l, size: m } = t;
|
|
89
|
-
|
|
91
|
+
if (r < 20 || s < 20) return null;
|
|
92
|
+
const M = (g) => {
|
|
93
|
+
g.stopPropagation();
|
|
94
|
+
const V = x[i];
|
|
95
|
+
if (V && b) {
|
|
96
|
+
const O = L?.measures?.[0] || f?.yAxis?.[0] || "";
|
|
97
|
+
b({
|
|
98
|
+
dataPoint: V,
|
|
99
|
+
clickedField: O,
|
|
100
|
+
xValue: l,
|
|
101
|
+
position: { x: g.clientX, y: g.clientY },
|
|
102
|
+
nativeEvent: g
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return /* @__PURE__ */ h("g", { children: [
|
|
90
107
|
/* @__PURE__ */ n(
|
|
91
108
|
"rect",
|
|
92
109
|
{
|
|
@@ -95,14 +112,17 @@ const J = V.memo(function({
|
|
|
95
112
|
width: r,
|
|
96
113
|
height: s,
|
|
97
114
|
style: {
|
|
98
|
-
fill:
|
|
99
|
-
fillOpacity:
|
|
115
|
+
fill: x[i]?.fill || p?.colors && p.colors[i % p.colors.length] || y[i % y.length],
|
|
116
|
+
fillOpacity: j !== null ? j === i ? 1 : 0.6 : 0.8,
|
|
100
117
|
stroke: "#fff",
|
|
101
118
|
strokeWidth: 2,
|
|
102
|
-
cursor: "pointer"
|
|
119
|
+
cursor: Y ? "pointer" : "default",
|
|
120
|
+
pointerEvents: "all"
|
|
121
|
+
// Ensure rect captures click events
|
|
103
122
|
},
|
|
104
|
-
onMouseEnter: () =>
|
|
105
|
-
onMouseLeave: () =>
|
|
123
|
+
onMouseEnter: () => T(i),
|
|
124
|
+
onMouseLeave: () => T(null),
|
|
125
|
+
onClick: Y && b ? M : void 0
|
|
106
126
|
}
|
|
107
127
|
),
|
|
108
128
|
/* @__PURE__ */ n(
|
|
@@ -154,7 +174,7 @@ const J = V.memo(function({
|
|
|
154
174
|
textAlign: "center",
|
|
155
175
|
opacity: 0.9
|
|
156
176
|
},
|
|
157
|
-
children: o.leftYAxisFormat ?
|
|
177
|
+
children: o.leftYAxisFormat ? v(m, o.leftYAxisFormat) : typeof m == "number" ? m.toLocaleString() : m
|
|
158
178
|
}
|
|
159
179
|
)
|
|
160
180
|
]
|
|
@@ -163,10 +183,10 @@ const J = V.memo(function({
|
|
|
163
183
|
}
|
|
164
184
|
)
|
|
165
185
|
] });
|
|
166
|
-
},
|
|
186
|
+
}, k = x.some((t) => "series" in t) ? [...new Set(x.map((t) => t.series).filter(Boolean))] : [];
|
|
167
187
|
let N = [];
|
|
168
188
|
if (o.showLegend && a)
|
|
169
|
-
if (
|
|
189
|
+
if (F) {
|
|
170
190
|
const t = Math.min(...c.map((d) => {
|
|
171
191
|
const r = d[a];
|
|
172
192
|
return typeof r == "string" ? parseFloat(r) : r;
|
|
@@ -177,40 +197,40 @@ const J = V.memo(function({
|
|
|
177
197
|
N = A.map((d, r) => {
|
|
178
198
|
const s = r / (A.length - 1), i = t + (e - t) * s;
|
|
179
199
|
return {
|
|
180
|
-
value: o.leftYAxisFormat ?
|
|
200
|
+
value: o.leftYAxisFormat ? v(i, o.leftYAxisFormat) : i.toFixed(2),
|
|
181
201
|
type: "rect",
|
|
182
202
|
color: d
|
|
183
203
|
};
|
|
184
204
|
});
|
|
185
|
-
} else
|
|
205
|
+
} else k.length > 1 && (N = k.map((t, e) => ({
|
|
186
206
|
value: t,
|
|
187
207
|
type: "rect",
|
|
188
208
|
color: y[e % y.length]
|
|
189
209
|
})));
|
|
190
|
-
const
|
|
191
|
-
return /* @__PURE__ */ h("div", { className: "dc:w-full", style: { height:
|
|
192
|
-
/* @__PURE__ */ n(
|
|
193
|
-
|
|
210
|
+
const S = o.showLegend && N.length > 0, E = S ? typeof u == "string" && u.includes("%") ? u : typeof u == "number" ? u + 60 : `calc(${u} + 60px)` : u;
|
|
211
|
+
return /* @__PURE__ */ h("div", { className: "dc:w-full", style: { height: E }, children: [
|
|
212
|
+
/* @__PURE__ */ n(G, { height: S ? "calc(100% - 50px)" : "100%", children: /* @__PURE__ */ n(
|
|
213
|
+
H,
|
|
194
214
|
{
|
|
195
|
-
data:
|
|
215
|
+
data: x,
|
|
196
216
|
dataKey: "size",
|
|
197
217
|
aspectRatio: 4 / 3,
|
|
198
218
|
stroke: "#fff",
|
|
199
|
-
content: /* @__PURE__ */ n(
|
|
219
|
+
content: /* @__PURE__ */ n(R, {}),
|
|
200
220
|
children: o.showTooltip && /* @__PURE__ */ n(
|
|
201
|
-
|
|
221
|
+
W,
|
|
202
222
|
{
|
|
203
|
-
formatter: o.leftYAxisFormat ? (t, e) => [
|
|
223
|
+
formatter: o.leftYAxisFormat ? (t, e) => [v(t, o.leftYAxisFormat), e] : void 0
|
|
204
224
|
}
|
|
205
225
|
)
|
|
206
226
|
}
|
|
207
227
|
) }),
|
|
208
|
-
|
|
228
|
+
S && /* @__PURE__ */ n("div", { className: "dc:flex dc:justify-center dc:items-center dc:mt-4 dc:pb-2", children: F ? (
|
|
209
229
|
// Gradient legend for numeric series
|
|
210
230
|
/* @__PURE__ */ h("div", { className: "dc:flex dc:flex-col dc:items-center", children: [
|
|
211
|
-
/* @__PURE__ */ n("div", { className: "dc:text-xs dc:font-semibold text-dc-text-primary dc:mb-2", children: a ?
|
|
231
|
+
/* @__PURE__ */ n("div", { className: "dc:text-xs dc:font-semibold text-dc-text-primary dc:mb-2", children: a ? C(a) : "" }),
|
|
212
232
|
/* @__PURE__ */ h("div", { className: "dc:flex dc:items-center dc:gap-2", children: [
|
|
213
|
-
/* @__PURE__ */ n("span", { className: "dc:text-xs text-dc-text-muted", children: o.leftYAxisFormat ?
|
|
233
|
+
/* @__PURE__ */ n("span", { className: "dc:text-xs text-dc-text-muted", children: o.leftYAxisFormat ? v(Math.min(...c.map((t) => {
|
|
214
234
|
const e = t[a];
|
|
215
235
|
return typeof e == "string" ? parseFloat(e) : e;
|
|
216
236
|
})), o.leftYAxisFormat) : Math.min(...c.map((t) => {
|
|
@@ -227,7 +247,7 @@ const J = V.memo(function({
|
|
|
227
247
|
}
|
|
228
248
|
}
|
|
229
249
|
),
|
|
230
|
-
/* @__PURE__ */ n("span", { className: "dc:text-xs text-dc-text-muted", children: o.leftYAxisFormat ?
|
|
250
|
+
/* @__PURE__ */ n("span", { className: "dc:text-xs text-dc-text-muted", children: o.leftYAxisFormat ? v(Math.max(...c.map((t) => {
|
|
231
251
|
const e = t[a];
|
|
232
252
|
return typeof e == "string" ? parseFloat(e) : e;
|
|
233
253
|
})), o.leftYAxisFormat) : Math.max(...c.map((t) => {
|
|
@@ -251,7 +271,7 @@ const J = V.memo(function({
|
|
|
251
271
|
) })
|
|
252
272
|
] });
|
|
253
273
|
} catch (o) {
|
|
254
|
-
return /* @__PURE__ */ 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:
|
|
274
|
+
return /* @__PURE__ */ 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: u }, children: /* @__PURE__ */ h("div", { className: "text-center", children: [
|
|
255
275
|
/* @__PURE__ */ n("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "TreeMap Chart Error" }),
|
|
256
276
|
/* @__PURE__ */ n("div", { className: "dc:text-xs dc:mb-2", children: o instanceof Error ? o.message : "Unknown rendering error" }),
|
|
257
277
|
/* @__PURE__ */ n("div", { className: "dc:text-xs text-dc-text-muted", children: "Check the data and configuration" })
|
|
@@ -259,6 +279,6 @@ const J = V.memo(function({
|
|
|
259
279
|
}
|
|
260
280
|
});
|
|
261
281
|
export {
|
|
262
|
-
|
|
282
|
+
ee as default
|
|
263
283
|
};
|
|
264
|
-
//# sourceMappingURL=chart-tree-map-
|
|
284
|
+
//# sourceMappingURL=chart-tree-map-D_SeBBD-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-tree-map-D_SeBBD-.js","sources":["../../../src/client/components/charts/TreeMapChart.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { Treemap } from 'recharts'\nimport { scaleQuantize, scaleOrdinal } from 'd3'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport { CHART_COLORS, CHART_COLORS_GRADIENT } from '../../utils/chartConstants'\nimport { formatTimeValue, getFieldGranularity, formatAxisValue } from '../../utils/chartUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst TreeMapChart = React.memo(function TreeMapChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n \n try {\n const safeDisplayConfig = {\n showTooltip: displayConfig?.showTooltip ?? true,\n showLegend: displayConfig?.showLegend ?? true,\n leftYAxisFormat: displayConfig?.leftYAxisFormat\n }\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=\"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 treemap chart</div>\n </div>\n </div>\n )\n }\n\n let treemapData: Array<{name: string, size: number, fill?: string, series?: string}>\n let isNumericSeries = false\n let seriesField: string | undefined\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format - use chart config\n const xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis // Name/category field\n const yAxisField = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis[0] : chartConfig.yAxis // Size field\n seriesField = Array.isArray(chartConfig.series) ? chartConfig.series[0] : chartConfig.series // Color grouping field\n\n const granularity = getFieldGranularity(queryObject, xAxisField)\n \n if (seriesField) {\n // Check if series field is numeric for color scaling\n const seriesValues = data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n }).filter(val => !isNaN(val))\n \n isNumericSeries = seriesValues.length === data.length && seriesValues.every(val => typeof val === 'number')\n \n \n if (isNumericSeries) {\n // Use D3 quantize scale for better color distribution with small ranges\n const minValue = Math.min(...seriesValues)\n const maxValue = Math.max(...seriesValues)\n \n // Create D3 quantize color scale - maps continuous data to discrete color bands\n const colorScale = scaleQuantize<string>()\n .domain([minValue, maxValue])\n .range(CHART_COLORS_GRADIENT)\n \n treemapData = data.map((item) => {\n const seriesValue = typeof item[seriesField!] === 'string' \n ? parseFloat(item[seriesField!]) \n : item[seriesField!]\n \n const color = colorScale(seriesValue)\n \n return {\n name: formatTimeValue(item[xAxisField], granularity) || String(item[xAxisField]) || 'Unknown',\n size: typeof item[yAxisField] === 'string' \n ? parseFloat(item[yAxisField]) \n : (item[yAxisField] || 0),\n fill: color,\n series: String(item[seriesField!])\n }\n })\n } else {\n // Use D3 ordinal color scale for categorical series\n const uniqueSeriesValues = [...new Set(data.map(item => String(item[seriesField!])))]\n const colorScale = scaleOrdinal<string>()\n .domain(uniqueSeriesValues)\n .range(colorPalette?.colors || CHART_COLORS)\n \n treemapData = data.map((item) => ({\n name: formatTimeValue(item[xAxisField], granularity) || String(item[xAxisField]) || 'Unknown',\n size: typeof item[yAxisField] === 'string' \n ? parseFloat(item[yAxisField]) \n : (item[yAxisField] || 0),\n fill: colorScale(String(item[seriesField!])),\n series: String(item[seriesField!])\n }))\n }\n } else {\n // No series grouping - use index-based colors\n treemapData = data.map((item, index) => ({\n name: formatTimeValue(item[xAxisField], granularity) || String(item[xAxisField]) || 'Unknown',\n size: typeof item[yAxisField] === 'string' \n ? parseFloat(item[yAxisField]) \n : (item[yAxisField] || 0),\n fill: (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) || CHART_COLORS[index % CHART_COLORS.length]\n }))\n }\n } else {\n // Legacy format or auto-detection\n const firstRow = data[0]\n const keys = Object.keys(firstRow)\n \n // Try to find name/label field\n const nameField = keys.find(key => \n typeof firstRow[key] === 'string' ||\n key.toLowerCase().includes('name') ||\n key.toLowerCase().includes('label') ||\n key.toLowerCase().includes('category')\n ) || keys[0]\n\n // Find a numeric field for size - look for 'size' field first, then any numeric\n const sizeField = keys.find(key => key.toLowerCase().includes('size')) ||\n keys.find(key => \n typeof firstRow[key] === 'number' && key !== nameField\n ) || keys[1]\n\n if (!sizeField) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Error</div>\n <div className=\"dc:text-xs\">No numeric field found for treemap chart size</div>\n </div>\n </div>\n )\n }\n\n // Transform data for treemap chart\n treemapData = data.map((item, index) => {\n let name = item[nameField]\n // Handle boolean values with better labels\n if (typeof name === 'boolean') {\n name = name ? 'Active' : 'Inactive'\n } else if (name === 'true' || name === 'false') {\n name = name === 'true' ? 'Active' : 'Inactive'\n } else {\n name = String(name)\n }\n return {\n name,\n size: typeof item[sizeField] === 'string' \n ? parseFloat(item[sizeField]) \n : (item[sizeField] || 0),\n fill: (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) || CHART_COLORS[index % CHART_COLORS.length]\n }\n })\n }\n\n // Filter out zero/null values and ensure positive sizes\n treemapData = treemapData.filter(item => item.size != null && item.size > 0)\n \n if (treemapData.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=\"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 treemap chart after transformation</div>\n </div>\n </div>\n )\n }\n\n // Custom content renderer for treemap cells with HTML overlays\n const CustomizedContent = (props: any) => {\n const { x, y, width, height, index, name, size } = props\n\n if (width < 20 || height < 20) return null // Don't render content for very small cells\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n const cellData = treemapData[index]\n if (cellData && onDataPointClick) {\n // Use query measures for proper field name (chartConfig.yAxis may contain display labels)\n const measureField = queryObject?.measures?.[0] || chartConfig?.yAxis?.[0] || ''\n onDataPointClick({\n dataPoint: cellData,\n clickedField: measureField,\n xValue: name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n return (\n <g>\n <rect\n x={x}\n y={y}\n width={width}\n height={height}\n style={{\n fill: treemapData[index]?.fill || ((colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) || CHART_COLORS[index % CHART_COLORS.length]),\n fillOpacity: hoveredIndex !== null ? (hoveredIndex === index ? 1 : 0.6) : 0.8,\n stroke: '#fff',\n strokeWidth: 2,\n cursor: drillEnabled ? 'pointer' : 'default',\n pointerEvents: 'all' // Ensure rect captures click events\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={drillEnabled && onDataPointClick ? handleClick : undefined}\n />\n <foreignObject \n x={x} \n y={y} \n width={width} \n height={height}\n style={{ pointerEvents: 'none', overflow: 'visible' }}\n >\n <div \n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '4px',\n boxSizing: 'border-box',\n color: '#ffffff',\n textShadow: '0 1px 2px rgba(0,0,0,0.8)',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n overflow: 'hidden'\n }}\n >\n {width > 40 && height > 30 && (\n <div \n style={{\n fontSize: `${Math.max(10, Math.min(width / 8, height / 8, 16))}px`,\n fontWeight: '600',\n textAlign: 'center',\n lineHeight: '1.2',\n marginBottom: width > 60 && height > 45 ? '4px' : '0',\n wordBreak: 'break-word',\n hyphens: 'auto'\n }}\n >\n {name}\n </div>\n )}\n {width > 60 && height > 45 && (\n <div\n style={{\n fontSize: `${Math.max(8, Math.min(width / 10, height / 10, 14))}px`,\n textAlign: 'center',\n opacity: 0.9\n }}\n >\n {safeDisplayConfig.leftYAxisFormat\n ? formatAxisValue(size, safeDisplayConfig.leftYAxisFormat)\n : (typeof size === 'number' ? size.toLocaleString() : size)\n }\n </div>\n )}\n </div>\n </foreignObject>\n </g>\n )\n }\n\n // Check if we have series data for legend\n const hasSeriesData = treemapData.some(item => 'series' in item)\n const uniqueSeries = hasSeriesData \n ? [...new Set(treemapData.map(item => item.series).filter(Boolean))]\n : []\n \n // For numeric series, create a legend showing the color scale\n let legendPayload: any[] = []\n if (safeDisplayConfig.showLegend && seriesField) {\n \n if (isNumericSeries) {\n // Create color scale legend for numeric values\n const minValue = Math.min(...data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n }))\n const maxValue = Math.max(...data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n }))\n \n \n // Create legend entries showing color scale\n legendPayload = CHART_COLORS_GRADIENT.map((color, index) => {\n const ratio = index / (CHART_COLORS_GRADIENT.length - 1)\n const value = minValue + (maxValue - minValue) * ratio\n return {\n value: safeDisplayConfig.leftYAxisFormat\n ? formatAxisValue(value, safeDisplayConfig.leftYAxisFormat)\n : value.toFixed(2),\n type: 'rect',\n color: color\n }\n })\n } else if (uniqueSeries.length > 1) {\n // Use categorical legend for non-numeric series\n legendPayload = uniqueSeries.map((series, index) => ({\n value: series,\n type: 'rect',\n color: CHART_COLORS[index % CHART_COLORS.length]\n }))\n }\n \n }\n\n // Calculate height adjustment for legend\n const hasLegend = safeDisplayConfig.showLegend && legendPayload.length > 0\n const adjustedHeight = hasLegend \n ? (typeof height === 'string' && height.includes('%') \n ? height \n : typeof height === 'number' \n ? height + 60 \n : `calc(${height} + 60px)`)\n : height\n\n return (\n <div className=\"dc:w-full\" style={{ height: adjustedHeight }}>\n <ChartContainer height={hasLegend ? `calc(100% - 50px)` : \"100%\"}>\n <Treemap\n data={treemapData}\n dataKey=\"size\"\n aspectRatio={4/3}\n stroke=\"#fff\"\n content={<CustomizedContent />}\n >\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={safeDisplayConfig.leftYAxisFormat\n ? (value: any, name: string) => [formatAxisValue(value, safeDisplayConfig.leftYAxisFormat), name]\n : undefined\n }\n />\n )}\n </Treemap>\n </ChartContainer>\n \n {/* Custom Legend outside ChartContainer */}\n {hasLegend && (\n <div className=\"dc:flex dc:justify-center dc:items-center dc:mt-4 dc:pb-2\">\n {isNumericSeries ? (\n // Gradient legend for numeric series\n <div className=\"dc:flex dc:flex-col dc:items-center\">\n <div className=\"dc:text-xs dc:font-semibold text-dc-text-primary dc:mb-2\">\n {seriesField ? getFieldLabel(seriesField) : ''}\n </div>\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n <span className=\"dc:text-xs text-dc-text-muted\">\n {safeDisplayConfig.leftYAxisFormat\n ? formatAxisValue(Math.min(...data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n })), safeDisplayConfig.leftYAxisFormat)\n : Math.min(...data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n })).toFixed(2)\n }\n </span>\n <div\n className=\"dc:h-4 dc:rounded-sm\"\n style={{\n width: '200px',\n background: `linear-gradient(to right, ${CHART_COLORS_GRADIENT.join(', ')})`\n }}\n />\n <span className=\"dc:text-xs text-dc-text-muted\">\n {safeDisplayConfig.leftYAxisFormat\n ? formatAxisValue(Math.max(...data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n })), safeDisplayConfig.leftYAxisFormat)\n : Math.max(...data.map(item => {\n const value = item[seriesField!]\n return typeof value === 'string' ? parseFloat(value) : value\n })).toFixed(2)\n }\n </span>\n </div>\n </div>\n ) : (\n // Discrete legend for categorical series\n <div className=\"dc:flex dc:flex-wrap dc:justify-center dc:gap-4\">\n {legendPayload.map((item, index) => (\n <div key={index} className=\"dc:flex dc:items-center dc:gap-2\">\n <div\n className=\"dc:w-3 dc:h-3 rounded-xs\"\n style={{ backgroundColor: item.color }}\n />\n <span className=\"dc:text-xs text-dc-text-muted\">\n {item.value}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )\n } catch (error) {\n // 'TreeMapChart 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=\"text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">TreeMap 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 TreeMapChart"],"names":["TreeMapChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","onDataPointClick","drillEnabled","hoveredIndex","setHoveredIndex","useState","getFieldLabel","useCubeFieldLabel","safeDisplayConfig","jsx","jsxs","treemapData","isNumericSeries","seriesField","xAxisField","yAxisField","granularity","getFieldGranularity","seriesValues","item","value","val","minValue","maxValue","colorScale","scaleQuantize","CHART_COLORS_GRADIENT","seriesValue","color","formatTimeValue","uniqueSeriesValues","scaleOrdinal","CHART_COLORS","index","firstRow","keys","nameField","key","sizeField","name","CustomizedContent","props","x","y","width","size","handleClick","event","cellData","measureField","formatAxisValue","uniqueSeries","legendPayload","ratio","series","hasLegend","adjustedHeight","ChartContainer","Treemap","ChartTooltip","error"],"mappings":"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"}
|
package/dist/client/chunks/{chartConfigRegistry-BumUIPw4.js → chartConfigRegistry-DNEbwgTc.js}
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { barChartConfig as r } from "./chart-config-bar-
|
|
2
|
-
import { lineChartConfig as o } from "./chart-config-line-
|
|
1
|
+
import { barChartConfig as r } from "./chart-config-bar-soxw6m2o.js";
|
|
2
|
+
import { lineChartConfig as o } from "./chart-config-line-D5ME6w0v.js";
|
|
3
3
|
import { areaChartConfig as i } from "./chart-config-area-CyyJOO2T.js";
|
|
4
|
-
import { pieChartConfig as t } from "./chart-config-pie-
|
|
4
|
+
import { pieChartConfig as t } from "./chart-config-pie-DlHa2jTy.js";
|
|
5
5
|
import { scatterChartConfig as a } from "./chart-config-scatter-CWvN2E-X.js";
|
|
6
6
|
import { bubbleChartConfig as m } from "./chart-config-bubble-CuSsCHZ4.js";
|
|
7
7
|
import { radarChartConfig as f } from "./chart-config-radar-BBAVIF0S.js";
|
|
8
8
|
import { radialBarChartConfig as C } from "./chart-config-radial-bar-CTwjDRnB.js";
|
|
9
|
-
import { treemapChartConfig as n } from "./chart-config-tree-map-
|
|
9
|
+
import { treemapChartConfig as n } from "./chart-config-tree-map-IRAYf9YM.js";
|
|
10
10
|
import { dataTableConfig as p } from "./chart-config-data-table-BhgqwoqT.js";
|
|
11
|
-
import { activityGridChartConfig as e } from "./chart-config-activity-grid-
|
|
11
|
+
import { activityGridChartConfig as e } from "./chart-config-activity-grid-CAlo1cHA.js";
|
|
12
12
|
import { kpiNumberConfig as g } from "./chart-config-kpi-number-nVAwDXzq.js";
|
|
13
13
|
import { kpiDeltaConfig as h } from "./chart-config-kpi-delta-yTA5ug_l.js";
|
|
14
14
|
import { kpiTextConfig as b } from "./chart-config-kpi-text-DZjqsx-b.js";
|
|
@@ -41,4 +41,4 @@ const J = {
|
|
|
41
41
|
export {
|
|
42
42
|
J as chartConfigRegistry
|
|
43
43
|
};
|
|
44
|
-
//# sourceMappingURL=chartConfigRegistry-
|
|
44
|
+
//# sourceMappingURL=chartConfigRegistry-DNEbwgTc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chartConfigRegistry-
|
|
1
|
+
{"version":3,"file":"chartConfigRegistry-DNEbwgTc.js","sources":["../../../src/client/charts/chartConfigRegistry.ts"],"sourcesContent":["import { barChartConfig } from '../components/charts/BarChart.config'\nimport { lineChartConfig } from '../components/charts/LineChart.config'\nimport { areaChartConfig } from '../components/charts/AreaChart.config'\nimport { pieChartConfig } from '../components/charts/PieChart.config'\nimport { scatterChartConfig } from '../components/charts/ScatterChart.config'\nimport { bubbleChartConfig } from '../components/charts/BubbleChart.config'\nimport { radarChartConfig } from '../components/charts/RadarChart.config'\nimport { radialBarChartConfig } from '../components/charts/RadialBarChart.config'\nimport { treemapChartConfig } from '../components/charts/TreeMapChart.config'\nimport { dataTableConfig } from '../components/charts/DataTable.config'\nimport { activityGridChartConfig } from '../components/charts/ActivityGridChart.config'\nimport { kpiNumberConfig } from '../components/charts/KpiNumber.config'\nimport { kpiDeltaConfig } from '../components/charts/KpiDelta.config'\nimport { kpiTextConfig } from '../components/charts/KpiText.config'\nimport { markdownConfig } from '../components/charts/MarkdownChart.config'\nimport { funnelChartConfig } from '../components/charts/FunnelChart.config'\nimport { sankeyChartConfig } from '../components/charts/SankeyChart.config'\nimport { sunburstChartConfig } from '../components/charts/SunburstChart.config'\nimport { heatmapChartConfig } from '../components/charts/HeatMapChart.config'\nimport type { ChartConfigRegistry } from './chartConfigs'\n\n/**\n * Registry of all chart type configurations\n */\nexport const chartConfigRegistry: ChartConfigRegistry = {\n bar: barChartConfig,\n line: lineChartConfig,\n area: areaChartConfig,\n pie: pieChartConfig,\n scatter: scatterChartConfig,\n bubble: bubbleChartConfig,\n radar: radarChartConfig,\n radialBar: radialBarChartConfig,\n treemap: treemapChartConfig,\n table: dataTableConfig,\n activityGrid: activityGridChartConfig,\n kpiNumber: kpiNumberConfig,\n kpiDelta: kpiDeltaConfig,\n kpiText: kpiTextConfig,\n markdown: markdownConfig,\n funnel: funnelChartConfig,\n sankey: sankeyChartConfig,\n sunburst: sunburstChartConfig,\n heatmap: heatmapChartConfig,\n}"],"names":["chartConfigRegistry","barChartConfig","lineChartConfig","areaChartConfig","pieChartConfig","scatterChartConfig","bubbleChartConfig","radarChartConfig","radialBarChartConfig","treemapChartConfig","dataTableConfig","activityGridChartConfig","kpiNumberConfig","kpiDeltaConfig","kpiTextConfig","markdownConfig","funnelChartConfig","sankeyChartConfig","sunburstChartConfig","heatmapChartConfig"],"mappings":";;;;;;;;;;;;;;;;;;;AAwBO,MAAMA,IAA2C;AAAA,EACtD,KAAKC;AAAA,EACL,MAAMC;AAAA,EACN,MAAMC;AAAA,EACN,KAAKC;AAAA,EACL,SAASC;AAAA,EACT,QAAQC;AAAA,EACR,OAAOC;AAAA,EACP,WAAWC;AAAA,EACX,SAASC;AAAA,EACT,OAAOC;AAAA,EACP,cAAcC;AAAA,EACd,WAAWC;AAAA,EACX,UAAUC;AAAA,EACV,SAASC;AAAA,EACT,UAAUC;AAAA,EACV,QAAQC;AAAA,EACR,QAAQC;AAAA,EACR,UAAUC;AAAA,EACV,SAASC;AACX;"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import "./charts-loader-
|
|
1
|
+
import "./charts-loader-sNk3q8UX.js";
|
|
2
2
|
import { useState as f, useEffect as c } from "react";
|
|
3
|
-
import "./charts-core-
|
|
4
|
-
import "./chart-bar-
|
|
5
|
-
import "./chart-line-
|
|
6
|
-
import "./chart-area-
|
|
7
|
-
import "./chart-pie-
|
|
8
|
-
import "./chart-scatter-
|
|
9
|
-
import "./chart-radar-
|
|
10
|
-
import "./chart-radial-bar-
|
|
11
|
-
import "./chart-tree-map-
|
|
12
|
-
import "./chart-data-table-
|
|
3
|
+
import "./charts-core-8jDh3mKC.js";
|
|
4
|
+
import "./chart-bar-BKRPTqiM.js";
|
|
5
|
+
import "./chart-line-DgFmGdWW.js";
|
|
6
|
+
import "./chart-area-INsj4GFi.js";
|
|
7
|
+
import "./chart-pie-DC7axSwd.js";
|
|
8
|
+
import "./chart-scatter-CXqFltJg.js";
|
|
9
|
+
import "./chart-radar-BDKgpLw5.js";
|
|
10
|
+
import "./chart-radial-bar-BYNng7Nz.js";
|
|
11
|
+
import "./chart-tree-map-D_SeBBD-.js";
|
|
12
|
+
import "./chart-data-table-BcH_h6kZ.js";
|
|
13
13
|
const u = {
|
|
14
14
|
dropZones: [
|
|
15
15
|
{
|
|
@@ -39,17 +39,17 @@ const u = {
|
|
|
39
39
|
],
|
|
40
40
|
displayOptions: ["showLegend", "showGrid", "showTooltip"]
|
|
41
41
|
}, l = {
|
|
42
|
-
bar: () => import("./chart-config-bar-
|
|
43
|
-
line: () => import("./chart-config-line-
|
|
42
|
+
bar: () => import("./chart-config-bar-soxw6m2o.js"),
|
|
43
|
+
line: () => import("./chart-config-line-D5ME6w0v.js"),
|
|
44
44
|
area: () => import("./chart-config-area-CyyJOO2T.js"),
|
|
45
|
-
pie: () => import("./chart-config-pie-
|
|
45
|
+
pie: () => import("./chart-config-pie-DlHa2jTy.js"),
|
|
46
46
|
scatter: () => import("./chart-config-scatter-CWvN2E-X.js"),
|
|
47
47
|
radar: () => import("./chart-config-radar-BBAVIF0S.js"),
|
|
48
48
|
radialBar: () => import("./chart-config-radial-bar-CTwjDRnB.js"),
|
|
49
|
-
treemap: () => import("./chart-config-tree-map-
|
|
49
|
+
treemap: () => import("./chart-config-tree-map-IRAYf9YM.js"),
|
|
50
50
|
bubble: () => import("./chart-config-bubble-CuSsCHZ4.js"),
|
|
51
51
|
table: () => import("./chart-config-data-table-BhgqwoqT.js"),
|
|
52
|
-
activityGrid: () => import("./chart-config-activity-grid-
|
|
52
|
+
activityGrid: () => import("./chart-config-activity-grid-CAlo1cHA.js"),
|
|
53
53
|
kpiNumber: () => import("./chart-config-kpi-number-nVAwDXzq.js"),
|
|
54
54
|
kpiDelta: () => import("./chart-config-kpi-delta-yTA5ug_l.js"),
|
|
55
55
|
kpiText: () => import("./chart-config-kpi-text-DZjqsx-b.js"),
|
|
@@ -227,4 +227,4 @@ export {
|
|
|
227
227
|
j as u,
|
|
228
228
|
Q as v
|
|
229
229
|
};
|
|
230
|
-
//# sourceMappingURL=charts-
|
|
230
|
+
//# sourceMappingURL=charts-CsEtJy5f.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts-CsEtJy5f.js","sources":["../../../src/client/charts/chartConfigs.ts","../../../src/client/charts/lazyChartConfigRegistry.ts","../../../src/client/utils/index.ts"],"sourcesContent":["import { ComponentType } from 'react'\n\n/**\n * Configuration for a single axis drop zone in the chart configuration UI\n */\nexport interface AxisDropZoneConfig {\n /** The key to store this field in chartConfig (e.g., 'xAxis', 'yAxis', 'sizeField') */\n key: string\n \n /** Display label for the drop zone */\n label: string\n \n /** Optional description/help text shown below the label */\n description?: string\n \n /** Whether at least one field is required in this drop zone */\n mandatory?: boolean\n \n /** Maximum number of items allowed in this drop zone */\n maxItems?: number\n \n /** Which field types this drop zone accepts */\n acceptTypes?: ('dimension' | 'timeDimension' | 'measure')[]\n \n /** Optional icon component to display */\n icon?: ComponentType<{ className?: string }>\n\n /** Placeholder text when drop zone is empty */\n emptyText?: string\n\n /** Enable L/R axis toggle for items in this drop zone (for dual Y-axis support) */\n enableDualAxis?: boolean\n}\n\n/**\n * Configuration for a single display option\n */\nexport interface DisplayOptionConfig {\n /** The key to store this field in displayConfig */\n key: string\n \n /** Display label for the option */\n label: string\n \n /** Type of input control to render */\n type: 'boolean' | 'string' | 'number' | 'select' | 'color' | 'paletteColor' | 'axisFormat' | 'stringArray' | 'buttonGroup'\n \n /** Default value for the option */\n defaultValue?: any\n \n /** Placeholder text for string/number inputs */\n placeholder?: string\n \n /** Options for select type */\n options?: Array<{ value: any; label: string }>\n \n /** Help text shown below the input */\n description?: string\n \n /** Minimum value for number inputs */\n min?: number\n \n /** Maximum value for number inputs */\n max?: number\n \n /** Step value for number inputs */\n step?: number\n}\n\n/**\n * Configuration for which elements in a chart support clicking (for drill-down)\n */\nexport interface ClickableElementsConfig {\n /** Bars in bar charts */\n bar?: boolean\n /** Points/dots in line/scatter charts */\n point?: boolean\n /** Slices in pie/donut charts */\n slice?: boolean\n /** Cells in heatmaps */\n cell?: boolean\n /** Nodes in treemaps, sankey diagrams */\n node?: boolean\n /** Areas in area charts */\n area?: boolean\n /** Rows in data tables */\n row?: boolean\n}\n\n/**\n * Complete configuration for a chart type\n */\nexport interface ChartTypeConfig {\n /** Configuration for each drop zone */\n dropZones: AxisDropZoneConfig[]\n\n /** Simple display options (backward compatibility) - rendered as boolean checkboxes */\n displayOptions?: string[]\n\n /** Structured display options with metadata for different input types */\n displayOptionsConfig?: DisplayOptionConfig[]\n\n /** Optional custom validation function */\n validate?: (config: any) => { isValid: boolean; message?: string }\n\n /** Icon component for the chart type */\n icon?: ComponentType<{ className?: string }>\n\n /** Brief description of the chart */\n description?: string\n\n /** When to use this chart type */\n useCase?: string\n\n /** Whether this chart type skips query requirements (for content-based charts like markdown) */\n skipQuery?: boolean\n\n /** Configuration for which elements support clicking (for drill-down) */\n clickableElements?: ClickableElementsConfig\n}\n\n/**\n * Registry of all chart type configurations\n */\nexport interface ChartConfigRegistry {\n [chartType: string]: ChartTypeConfig\n}\n\n/**\n * Default configuration for charts without specific requirements\n */\nexport const defaultChartConfig: ChartTypeConfig = {\n dropZones: [\n {\n key: 'xAxis',\n label: 'X-Axis (Categories)',\n description: 'Dimensions and time dimensions for grouping',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'Drop dimensions & time dimensions here'\n },\n {\n key: 'yAxis',\n label: 'Y-Axis (Values)',\n description: 'Measures for values or dimensions for series',\n mandatory: false,\n acceptTypes: ['measure', 'dimension'],\n emptyText: 'Drop measures or dimensions here'\n },\n {\n key: 'series',\n label: 'Series (Split into Multiple Series)',\n description: 'Dimensions to create separate data series',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'Drop dimensions here to split data into series'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip']\n}\n\n/**\n * Helper function to get configuration for a chart type\n */\nexport function getChartConfig(chartType: string, registry: ChartConfigRegistry): ChartTypeConfig {\n return registry[chartType] || defaultChartConfig\n}","/**\n * Lazy Chart Config Registry\n *\n * Provides async loading for chart configurations.\n * This enables code splitting - each chart config loads only when needed.\n */\n\nimport { useState, useEffect } from 'react'\nimport type { ChartType } from '../types'\nimport type { ChartTypeConfig, ChartConfigRegistry } from './chartConfigs'\nimport { defaultChartConfig } from './chartConfigs'\n\n// Config import map - lazy imports for each chart config\nconst configImportMap: Record<ChartType, () => Promise<{ [key: string]: ChartTypeConfig }>> = {\n bar: () => import('../components/charts/BarChart.config'),\n line: () => import('../components/charts/LineChart.config'),\n area: () => import('../components/charts/AreaChart.config'),\n pie: () => import('../components/charts/PieChart.config'),\n scatter: () => import('../components/charts/ScatterChart.config'),\n radar: () => import('../components/charts/RadarChart.config'),\n radialBar: () => import('../components/charts/RadialBarChart.config'),\n treemap: () => import('../components/charts/TreeMapChart.config'),\n bubble: () => import('../components/charts/BubbleChart.config'),\n table: () => import('../components/charts/DataTable.config'),\n activityGrid: () => import('../components/charts/ActivityGridChart.config'),\n kpiNumber: () => import('../components/charts/KpiNumber.config'),\n kpiDelta: () => import('../components/charts/KpiDelta.config'),\n kpiText: () => import('../components/charts/KpiText.config'),\n markdown: () => import('../components/charts/MarkdownChart.config'),\n funnel: () => import('../components/charts/FunnelChart.config'),\n sankey: () => import('../components/charts/SankeyChart.config'),\n sunburst: () => import('../components/charts/SunburstChart.config'),\n heatmap: () => import('../components/charts/HeatMapChart.config'),\n retentionHeatmap: () => import('../components/charts/RetentionHeatmap.config'),\n retentionCombined: () => import('../components/charts/RetentionCombinedChart.config'),\n}\n\n// Map from chart type to expected export name\nconst configExportNames: Record<ChartType, string> = {\n bar: 'barChartConfig',\n line: 'lineChartConfig',\n area: 'areaChartConfig',\n pie: 'pieChartConfig',\n scatter: 'scatterChartConfig',\n radar: 'radarChartConfig',\n radialBar: 'radialBarChartConfig',\n treemap: 'treemapChartConfig',\n bubble: 'bubbleChartConfig',\n table: 'dataTableConfig',\n activityGrid: 'activityGridChartConfig',\n kpiNumber: 'kpiNumberConfig',\n kpiDelta: 'kpiDeltaConfig',\n kpiText: 'kpiTextConfig',\n markdown: 'markdownConfig',\n funnel: 'funnelChartConfig',\n sankey: 'sankeyChartConfig',\n sunburst: 'sunburstChartConfig',\n heatmap: 'heatmapChartConfig',\n retentionHeatmap: 'retentionHeatmapConfig',\n retentionCombined: 'retentionCombinedConfig',\n}\n\n// Cache for loaded configs\nconst configCache = new Map<ChartType, ChartTypeConfig>()\n\n/**\n * Get a chart config asynchronously\n *\n * @param chartType The chart type to load config for\n * @returns The chart type config, or null if not found\n *\n * @example\n * ```typescript\n * const config = await getChartConfigAsync('bar')\n * console.log(config?.dropZones)\n * ```\n */\nexport async function getChartConfigAsync(chartType: ChartType): Promise<ChartTypeConfig | null> {\n // Check cache first\n if (configCache.has(chartType)) {\n return configCache.get(chartType)!\n }\n\n const importFn = configImportMap[chartType]\n if (!importFn) {\n return null\n }\n\n try {\n const module = await importFn()\n const exportName = configExportNames[chartType]\n const config = module[exportName]\n\n if (config) {\n configCache.set(chartType, config)\n return config\n }\n return null\n } catch (error) {\n console.error(`Failed to load config for chart type: ${chartType}`, error)\n return null\n }\n}\n\n/**\n * Get a chart config synchronously from cache\n *\n * Returns the cached config if available, otherwise returns the default config.\n * Use this when you need sync access and have already preloaded the config.\n *\n * @param chartType The chart type to get config for\n * @returns The chart type config (from cache or default)\n */\nexport function getChartConfigSync(chartType: ChartType): ChartTypeConfig {\n return configCache.get(chartType) || defaultChartConfig\n}\n\n/**\n * Check if a chart config is already loaded\n */\nexport function isChartConfigLoaded(chartType: ChartType): boolean {\n return configCache.has(chartType)\n}\n\n/**\n * React hook for using chart config\n *\n * Loads the chart config asynchronously and caches it.\n * Returns the default config while loading.\n *\n * @param chartType The chart type to load config for\n * @returns Object with config, loading state, and loaded flag\n *\n * @example\n * ```tsx\n * function ChartSetup({ chartType }) {\n * const { config, loading } = useChartConfig(chartType)\n *\n * if (loading) return <Spinner />\n * return <ConfigForm config={config} />\n * }\n * ```\n */\nexport function useChartConfig(chartType: ChartType | undefined): {\n config: ChartTypeConfig\n loading: boolean\n loaded: boolean\n} {\n const [config, setConfig] = useState<ChartTypeConfig>(\n chartType ? getChartConfigSync(chartType) : defaultChartConfig\n )\n const [loading, setLoading] = useState(false)\n const [loaded, setLoaded] = useState(false)\n\n useEffect(() => {\n if (!chartType) {\n setConfig(defaultChartConfig)\n setLoaded(false)\n return\n }\n\n // Check cache synchronously first\n if (configCache.has(chartType)) {\n setConfig(configCache.get(chartType)!)\n setLoaded(true)\n return\n }\n\n // Load async\n setLoading(true)\n getChartConfigAsync(chartType)\n .then((loadedConfig) => {\n if (loadedConfig) {\n setConfig(loadedConfig)\n setLoaded(true)\n } else {\n setConfig(defaultChartConfig)\n setLoaded(true)\n }\n })\n .finally(() => setLoading(false))\n }, [chartType])\n\n return { config, loading, loaded }\n}\n\n/**\n * Preload a chart config\n *\n * Triggers the async import without needing to use the config immediately.\n * Useful for prefetching configs that will likely be needed.\n *\n * @param chartType The chart type to preload config for\n */\nexport async function preloadChartConfig(chartType: ChartType): Promise<void> {\n if (!configCache.has(chartType)) {\n await getChartConfigAsync(chartType)\n }\n}\n\n/**\n * Preload multiple chart configs\n *\n * @param chartTypes Array of chart types to preload\n */\nexport async function preloadChartConfigs(chartTypes: ChartType[]): Promise<void> {\n await Promise.all(chartTypes.map(preloadChartConfig))\n}\n\n/**\n * Load all chart configs and return as a registry\n *\n * Useful for SSR or when you need all configs upfront.\n * After calling this, all configs are cached and available synchronously.\n *\n * @returns Complete chart config registry\n *\n * @example\n * ```typescript\n * // On server or during initialization\n * const registry = await loadAllChartConfigs()\n * // Now all configs are cached and getChartConfigSync works for all types\n * ```\n */\nexport async function loadAllChartConfigs(): Promise<ChartConfigRegistry> {\n const chartTypes = Object.keys(configImportMap) as ChartType[]\n await Promise.all(chartTypes.map(getChartConfigAsync))\n\n const registry: ChartConfigRegistry = {}\n for (const chartType of chartTypes) {\n const config = configCache.get(chartType)\n if (config) {\n registry[chartType] = config\n }\n }\n return registry\n}\n\n/**\n * Clear the config cache\n *\n * Useful for testing or when configs need to be reloaded.\n */\nexport function clearChartConfigCache(): void {\n configCache.clear()\n}\n","/**\n * Utility functions for drizzle-cube client\n */\n\nimport type { PortletConfig, DashboardConfig } from '../types'\n\n// Re-export chart utilities\nexport * from './chartUtils'\nexport * from './chartConstants'\nexport * from './measureIcons'\nexport * from './periodUtils'\nexport * from './pivotUtils'\nexport * from './syntaxHighlighting'\nexport * from './comparisonUtils'\n\n// Thumbnail utilities (requires html2canvas peer dependency)\nexport { captureThumbnail, isThumbnailCaptureAvailable } from './thumbnail'\n\n/**\n * Create a dashboard layout from portlet configurations\n */\nexport function createDashboardLayout(portlets: PortletConfig[]): DashboardConfig {\n const layouts = generateResponsiveLayouts(portlets)\n \n return {\n portlets,\n layouts\n }\n}\n\n/**\n * Generate responsive layouts for different breakpoints\n */\nexport function generateResponsiveLayouts(portlets: PortletConfig[]) {\n const gridLayout = portlets.map(portlet => ({\n i: portlet.id,\n x: portlet.x,\n y: portlet.y,\n w: portlet.w,\n h: portlet.h,\n minW: 3,\n minH: 3\n }))\n\n return {\n lg: gridLayout,\n md: gridLayout.map(item => ({ ...item, w: Math.min(item.w, 8) })),\n sm: gridLayout.map(item => ({ ...item, w: Math.min(item.w, 6) })),\n xs: gridLayout.map(item => ({ ...item, w: Math.min(item.w, 4) })),\n xxs: gridLayout.map(item => ({ ...item, w: 2 }))\n }\n}\n\n/**\n * Format chart data for display\n */\nexport function formatChartData(data: any[], options: {\n formatNumbers?: boolean\n precision?: number\n} = {}): any[] {\n const { formatNumbers = true, precision = 2 } = options\n\n if (!formatNumbers) return data\n\n return data.map(row => {\n const formattedRow: any = {}\n \n for (const [key, value] of Object.entries(row)) {\n if (typeof value === 'number') {\n formattedRow[key] = Number(value.toFixed(precision))\n } else {\n formattedRow[key] = value\n }\n }\n \n return formattedRow\n })\n}\n\n/**\n * Generate a unique ID for new portlets\n */\nexport function generatePortletId(): string {\n return `portlet-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * Find the next available position in a grid\n */\nexport function findNextPosition(existingPortlets: PortletConfig[], _w: number = 6, _h: number = 4): { x: number; y: number } {\n if (existingPortlets.length === 0) {\n return { x: 0, y: 0 }\n }\n\n // Find the maximum Y position and height\n const maxY = Math.max(...existingPortlets.map(p => p.y + p.h))\n \n return { x: 0, y: maxY }\n}\n\n/**\n * Validate a cube query JSON string\n */\nexport function validateCubeQuery(queryString: string): { valid: boolean; error?: string; query?: any } {\n try {\n const query = JSON.parse(queryString)\n \n // Basic validation\n if (typeof query !== 'object' || query === null) {\n return { valid: false, error: 'Query must be a JSON object' }\n }\n\n // Check for required fields\n if (!query.measures && !query.dimensions) {\n return { valid: false, error: 'Query must have at least measures or dimensions' }\n }\n\n return { valid: true, query }\n } catch {\n return { valid: false, error: 'Invalid JSON format' }\n }\n}\n\n/**\n * Create a sample portlet configuration\n */\nexport function createSamplePortlet(): Omit<PortletConfig, 'id'> {\n return {\n title: 'Sample Chart',\n query: JSON.stringify({\n measures: ['count'],\n dimensions: ['category']\n }, null, 2),\n chartType: 'bar',\n chartConfig: {\n x: 'category',\n y: ['count']\n },\n displayConfig: {\n showLegend: true,\n showGrid: true,\n showTooltip: true\n },\n w: 6,\n h: 4,\n x: 0,\n y: 0\n }\n}"],"names":["defaultChartConfig","configImportMap","configExportNames","configCache","getChartConfigAsync","chartType","importFn","module","exportName","config","error","getChartConfigSync","isChartConfigLoaded","useChartConfig","setConfig","useState","loading","setLoading","loaded","setLoaded","useEffect","loadedConfig","preloadChartConfig","preloadChartConfigs","chartTypes","loadAllChartConfigs","registry","clearChartConfigCache","createDashboardLayout","portlets","layouts","generateResponsiveLayouts","gridLayout","portlet","item","formatChartData","data","options","formatNumbers","precision","row","formattedRow","key","value","generatePortletId","findNextPosition","existingPortlets","_w","_h","p","validateCubeQuery","queryString","query","createSamplePortlet"],"mappings":"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"}
|