drizzle-cube 0.5.0 → 0.5.3
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/README.md +4 -0
- package/dist/adapters/express/index.cjs +2 -2
- package/dist/adapters/express/index.js +106 -102
- package/dist/adapters/fastify/index.cjs +2 -2
- package/dist/adapters/fastify/index.js +109 -105
- package/dist/adapters/{handler-3LGcjLtr.js → handler-BC3nFNxV.js} +2 -2
- package/dist/adapters/{handler-BzzbVpcl.cjs → handler-Cqf-CqAS.cjs} +2 -2
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +41 -45
- package/dist/adapters/locale-BoiA6WiV.cjs +198 -0
- package/dist/adapters/{locale-DTnJrxm1.js → locale-D9VQkLXt.js} +442 -404
- package/dist/adapters/mcp-tools.cjs +1 -1
- package/dist/adapters/mcp-tools.d.ts +7 -3
- package/dist/adapters/mcp-tools.js +28 -28
- package/dist/adapters/mcp-transport-B0mgxRnJ.js +579 -0
- package/dist/adapters/mcp-transport-irsahKmD.cjs +39 -0
- package/dist/adapters/mcp-transport.d.ts +14 -2
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +140 -136
- package/dist/adapters/{openai-C4BD8xnN.cjs → openai-B4N3KfTG.cjs} +1 -1
- package/dist/adapters/{openai-CaSQEduB.js → openai-BWdm0JvG.js} +1 -1
- package/dist/adapters/openai-CoqT_FM5.cjs +16 -0
- package/dist/{server/openai-CqZg6zYL.js → adapters/openai-D0Nsvc9L.js} +824 -720
- package/dist/adapters/{utils-DOg9oGdt.js → utils-CTYvfZ3I.js} +711 -713
- package/dist/adapters/{utils-DNrj-ryp.cjs → utils-XPOzzMdY.cjs} +5 -5
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.d.ts +38 -2
- package/dist/adapters/utils.js +1 -1
- package/dist/cli/index.cjs +2 -2
- package/dist/client/charts.js +10 -10
- package/dist/client/chunks/{DashboardEditModal-cSSIAZGy.js → DashboardEditModal-IU_0dgfC.js} +12 -12
- package/dist/client/chunks/{DashboardEditModal-cSSIAZGy.js.map → DashboardEditModal-IU_0dgfC.js.map} +1 -1
- package/dist/client/chunks/{FieldSearchModal-CZNo4pNK.js → FieldSearchModal-BCWanpPX.js} +3 -3
- package/dist/client/chunks/{FieldSearchModal-CZNo4pNK.js.map → FieldSearchModal-BCWanpPX.js.map} +1 -1
- package/dist/client/chunks/KpiDelta-_igN6cJa.js +2 -0
- package/dist/client/chunks/KpiNumber-t5n8PtRU.js +2 -0
- package/dist/client/chunks/KpiText-BCZJJ6a0.js +2 -0
- package/dist/client/chunks/{RetentionCombinedChart-BD8tGeM_.js → RetentionCombinedChart-CQMBODsK.js} +2 -2
- package/dist/client/chunks/{RetentionCombinedChart-BD8tGeM_.js.map → RetentionCombinedChart-CQMBODsK.js.map} +1 -1
- package/dist/client/chunks/SchemaVisualization-BUUhlOvG.js +2 -0
- package/dist/client/chunks/SchemaVisualizationLazy-CwaPCUL0.js +2 -0
- package/dist/client/chunks/{analysis-builder-BeVZhiQ5.js → analysis-builder-Dm6eD_AX.js} +6 -6
- package/dist/client/chunks/{analysis-builder-BeVZhiQ5.js.map → analysis-builder-Dm6eD_AX.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-BWc7ZZnG.js → analysis-builder-shared-DT5bXwCA.js} +6 -6
- package/dist/client/chunks/{analysis-builder-shared-BWc7ZZnG.js.map → analysis-builder-shared-DT5bXwCA.js.map} +1 -1
- package/dist/client/chunks/{chart-area-D63kG8OT.js → chart-area-DDti9Qtp.js} +2 -2
- package/dist/client/chunks/{chart-area-D63kG8OT.js.map → chart-area-DDti9Qtp.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-BEfsCLjl.js → chart-bar-B3s9qDlh.js} +2 -2
- package/dist/client/chunks/{chart-bar-BEfsCLjl.js.map → chart-bar-B3s9qDlh.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-C3Xh9jwL.js → chart-data-table-Qrt6EAno.js} +17 -17
- package/dist/client/chunks/{chart-data-table-C3Xh9jwL.js.map → chart-data-table-Qrt6EAno.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-CYE0S1x_.js → chart-kpi-delta-CgldZ7zO.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-CYE0S1x_.js.map → chart-kpi-delta-CgldZ7zO.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-BlZ79xHW.js → chart-kpi-number-ByfuX1ki.js} +5 -5
- package/dist/client/chunks/{chart-kpi-number-BlZ79xHW.js.map → chart-kpi-number-ByfuX1ki.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-DY1BnxPe.js → chart-kpi-text-DeNuDraJ.js} +2 -2
- package/dist/client/chunks/{chart-kpi-text-DY1BnxPe.js.map → chart-kpi-text-DeNuDraJ.js.map} +1 -1
- package/dist/client/chunks/{chart-line-CBsTThTv.js → chart-line-RdZwtk27.js} +2 -2
- package/dist/client/chunks/{chart-line-CBsTThTv.js.map → chart-line-RdZwtk27.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-BWaWVkuz.js → chart-markdown-CiGRZdJj.js} +1203 -1139
- package/dist/client/chunks/chart-markdown-CiGRZdJj.js.map +1 -0
- package/dist/client/chunks/{chart-measure-profile-B41qCTBG.js → chart-measure-profile-Ckjw9bX6.js} +2 -2
- package/dist/client/chunks/{chart-measure-profile-B41qCTBG.js.map → chart-measure-profile-Ckjw9bX6.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-Djbu8x2v.js → chart-pie-BvY4FY__.js} +2 -2
- package/dist/client/chunks/{chart-pie-Djbu8x2v.js.map → chart-pie-BvY4FY__.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-BsTcKV0K.js → chart-radar-DjiiEAmc.js} +2 -2
- package/dist/client/chunks/{chart-radar-BsTcKV0K.js.map → chart-radar-DjiiEAmc.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-Du7XNnwE.js → chart-radial-bar-lla_JEYu.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-Du7XNnwE.js.map → chart-radial-bar-lla_JEYu.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-D8krEYsA.js → chart-scatter-DwXnI0rr.js} +2 -2
- package/dist/client/chunks/{chart-scatter-D8krEYsA.js.map → chart-scatter-DwXnI0rr.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-C5C2iaWM.js → chart-tree-map-DJHoA26f.js} +2 -2
- package/dist/client/chunks/{chart-tree-map-C5C2iaWM.js.map → chart-tree-map-DJHoA26f.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-BGdPrJ5Y.js → chart-waterfall-Y7c8csO5.js} +2 -2
- package/dist/client/chunks/{chart-waterfall-BGdPrJ5Y.js.map → chart-waterfall-Y7c8csO5.js.map} +1 -1
- package/dist/client/chunks/{core-DcfMGTVa.js → core-Dk6z6kC0.js} +2 -2
- package/dist/client/chunks/{core-DcfMGTVa.js.map → core-Dk6z6kC0.js.map} +1 -1
- package/dist/client/chunks/{exceljs.min-CcjgM-qg.js → exceljs.min-DaJsLlWM.js} +24 -24
- package/dist/client/chunks/{exceljs.min-CcjgM-qg.js.map → exceljs.min-DaJsLlWM.js.map} +1 -1
- package/dist/client/chunks/{schema-visualization-Xp60Ff2W.js → schema-visualization-DWwJukK7.js} +8 -8
- package/dist/client/chunks/{schema-visualization-Xp60Ff2W.js.map → schema-visualization-DWwJukK7.js.map} +1 -1
- package/dist/client/chunks/{syntaxHighlighting-CnDujqwg.js → syntaxHighlighting-D8J6Yt9j.js} +2 -2
- package/dist/client/chunks/{syntaxHighlighting-CnDujqwg.js.map → syntaxHighlighting-D8J6Yt9j.js.map} +1 -1
- package/dist/client/chunks/{useDebounce-CfmUMFau.js → useDebounce-DyJVREop.js} +2 -2
- package/dist/client/chunks/{useDebounce-CfmUMFau.js.map → useDebounce-DyJVREop.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-BKGmejIj.js → useExplainAI-CxSkjocM.js} +4 -4
- package/dist/client/chunks/{useExplainAI-BKGmejIj.js.map → useExplainAI-CxSkjocM.js.map} +1 -1
- package/dist/client/chunks/{utils-BldkcRHv.js → utils-BHZdKxua.js} +2 -2
- package/dist/client/chunks/{utils-BldkcRHv.js.map → utils-BHZdKxua.js.map} +1 -1
- package/dist/client/chunks/{vendor-ClXpIiea.js → vendor-CBD_Olr0.js} +8 -8
- package/dist/client/chunks/{vendor-ClXpIiea.js.map → vendor-CBD_Olr0.js.map} +1 -1
- package/dist/client/components.js +3 -3
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +11 -11
- package/dist/client/providers.js +1 -1
- package/dist/client/schema.js +1 -1
- package/dist/client/utils.js +5 -5
- package/dist/client-bundle-stats.html +1 -1
- package/dist/mcp-app/mcp-app.html +39 -37
- package/dist/server/index.cjs +42 -42
- package/dist/server/index.js +1009 -971
- package/dist/server/{openai-D9Zjuby1.cjs → openai-BfiZU0rG.cjs} +1 -1
- package/dist/server/openai-BwsBio1K.cjs +16 -0
- package/dist/server/{openai-rwauPzCT.js → openai-CLWSwD-D.js} +1 -1
- package/dist/{adapters/openai-BAnEZgKZ.js → server/openai-zpXlGbbF.js} +824 -720
- package/package.json +2 -2
- package/dist/adapters/locale-DueXjqMh.cjs +0 -198
- package/dist/adapters/mcp-transport-45SiFcCH.cjs +0 -39
- package/dist/adapters/mcp-transport-Bxpc4mRy.js +0 -553
- package/dist/adapters/openai-4JP2B6pB.cjs +0 -16
- package/dist/client/chunks/KpiDelta-Dll_eCV1.js +0 -2
- package/dist/client/chunks/KpiNumber-BPlR92hI.js +0 -2
- package/dist/client/chunks/KpiText-BIxq7Jso.js +0 -2
- package/dist/client/chunks/SchemaVisualization-CCICjhvv.js +0 -2
- package/dist/client/chunks/SchemaVisualizationLazy-DraGsMx6.js +0 -2
- package/dist/client/chunks/chart-markdown-BWaWVkuz.js.map +0 -1
- package/dist/server/openai-DmuEbFd6.cjs +0 -16
|
@@ -183,7 +183,7 @@ function M(e, t) {
|
|
|
183
183
|
if (e.length === 1) return Array(t).fill(e[0]);
|
|
184
184
|
let n = [], r = Math.floor(t / e.length), i = t % e.length, a = 0;
|
|
185
185
|
for (let t = 0; t < e.length; t++) {
|
|
186
|
-
let o = r + (t < i
|
|
186
|
+
let o = r + +(t < i);
|
|
187
187
|
for (let r = 0; r < o; r++) n[a++] = e[t];
|
|
188
188
|
}
|
|
189
189
|
return n;
|
|
@@ -446,4 +446,4 @@ var F = /* @__PURE__ */ e({ default: () => I }), I = c.memo(function({ data: e,
|
|
|
446
446
|
//#endregion
|
|
447
447
|
export { j as a, k as c, P as i, D as l, F as n, M as o, N as r, A as s, I as t, E as u };
|
|
448
448
|
|
|
449
|
-
//# sourceMappingURL=chart-area-
|
|
449
|
+
//# sourceMappingURL=chart-area-DDti9Qtp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-area-D63kG8OT.js","names":[],"sources":["../../../src/client/components/LoadingIndicator.tsx","../../../src/client/components/charts/ChartContainer.tsx","../../../src/client/components/charts/ChartTooltip.tsx","../../../src/client/components/charts/AngledXAxisTick.tsx","../../../src/client/utils/targetUtils.ts","../../../src/client/components/charts/AreaChart.tsx"],"sourcesContent":["/**\n * LoadingIndicator Component\n *\n * A centralized, theme-aware loading spinner that uses CSS variables\n * for consistent styling across all drizzle-cube components.\n *\n * Can be overridden at the Dashboard or Portlet level by passing a\n * custom loadingComponent prop.\n */\n\nexport interface LoadingIndicatorProps {\n /** Size variant: 'xs' (12px), 'sm' (24px), 'md' (32px), 'lg' (48px) */\n size?: 'xs' | 'sm' | 'md' | 'lg'\n /** Additional CSS classes */\n className?: string\n}\n\nconst sizeClasses = {\n xs: 'dc:h-3 dc:w-3',\n sm: 'dc:h-6 dc:w-6',\n md: 'dc:h-8 dc:w-8',\n lg: 'dc:h-12 dc:w-12'\n}\n\nexport default function LoadingIndicator({\n size = 'md',\n className = ''\n}: LoadingIndicatorProps) {\n return (\n <div\n className={`dc:animate-spin dc:rounded-full dc:border-b-2 ${sizeClasses[size]} ${className}`}\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n role=\"status\"\n aria-label=\"Loading\"\n />\n )\n}\n","import { ReactElement, useState, useRef, useLayoutEffect, startTransition } from 'react'\nimport { ResponsiveContainer } from 'recharts'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport LoadingIndicator from '../LoadingIndicator'\n\ninterface ChartContainerProps {\n children: ReactElement\n height?: string | number\n}\n\nexport default function ChartContainer({ children, height = \"100%\" }: ChartContainerProps) {\n const { t } = useTranslation()\n // Track if container is ready to render ResponsiveContainer\n // We need to wait for the container to be in the DOM with valid dimensions\n const containerRef = useRef<HTMLDivElement>(null)\n const [isReady, setIsReady] = useState(false)\n const [containerSize, setContainerSize] = useState({ width: 0, height: 0 })\n const sizeRef = useRef({ width: 0, height: 0 })\n const readyRef = useRef(false)\n const pendingSizeRef = useRef<{ width: number; height: number } | null>(null)\n const frameRef = useRef<number | null>(null)\n\n // Use useLayoutEffect to measure before paint\n useLayoutEffect(() => {\n let mounted = true\n let resizeObserver: ResizeObserver | null = null\n\n const flushPendingSize = () => {\n frameRef.current = null\n if (!mounted) return\n const pending = pendingSizeRef.current\n pendingSizeRef.current = null\n if (!pending) return\n\n const nextWidth = Math.round(pending.width)\n const nextHeight = Math.round(pending.height)\n if (nextWidth <= 0 || nextHeight <= 0) return\n\n const sizeChanged =\n sizeRef.current.width !== nextWidth || sizeRef.current.height !== nextHeight\n const shouldBecomeReady = !readyRef.current\n\n if (!sizeChanged && !shouldBecomeReady) return\n\n sizeRef.current = { width: nextWidth, height: nextHeight }\n readyRef.current = true\n\n // Resize-driven chart updates can come in bursts (one per portlet).\n // Transitioning these avoids blocking urgent input and coalesces visual work.\n startTransition(() => {\n if (sizeChanged) {\n setContainerSize({ width: nextWidth, height: nextHeight })\n }\n if (shouldBecomeReady) {\n setIsReady(true)\n }\n })\n }\n\n const scheduleSizeUpdate = (width: number, height: number) => {\n pendingSizeRef.current = { width, height }\n if (frameRef.current === null) {\n frameRef.current = requestAnimationFrame(flushPendingSize)\n }\n }\n\n const measureAndSetReady = () => {\n if (!mounted || !containerRef.current) return\n\n const rect = containerRef.current.getBoundingClientRect()\n // Check both clientWidth/Height AND getBoundingClientRect for robustness\n const width = Math.max(containerRef.current.clientWidth, rect.width)\n const measuredHeight = Math.max(containerRef.current.clientHeight, rect.height)\n\n if (width > 0 && measuredHeight > 0) {\n scheduleSizeUpdate(width, measuredHeight)\n }\n }\n\n // Set up ResizeObserver to detect when container gets valid dimensions\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: entryHeight } = entry.contentRect\n if (width > 0 && entryHeight > 0) {\n scheduleSizeUpdate(width, entryHeight)\n }\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n // Also try immediate measurement\n measureAndSetReady()\n }\n\n return () => {\n mounted = false\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current)\n frameRef.current = null\n }\n resizeObserver?.disconnect()\n }\n }, [])\n\n try {\n if (height === \"100%\") {\n // For 100% height, make the container fill the available flex space with proper sizing\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:h-full dc:flex-1 dc:flex dc:flex-col dc:relative\"\n style={{ minHeight: '250px', minWidth: '100px', overflow: 'hidden', userSelect: 'none' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n }\n\n // For specific heights, use them directly\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n const containerStyle = {\n height: typeof height === 'number' ? `${height}px` : height,\n width: '100%',\n minHeight: '200px',\n minWidth: '100px',\n userSelect: 'none' as const\n }\n\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:flex dc:flex-col dc:relative\"\n style={{ ...containerStyle, overflow: 'hidden' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n } catch (error) {\n // ChartContainer ResponsiveContainer error\n\n return (\n <div\n className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-4 dc:text-center dc:border dc:border-dashed dc:rounded-lg\"\n style={{ height, borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}\n >\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1 text-dc-text-muted\">{t('chart.runtime.unableToDisplay')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {error instanceof Error ? error.message : 'Failed to create responsive container'}\n </div>\n </div>\n )\n }\n}\n","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, payload?: readonly 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}","import React from 'react'\n\ninterface AngledXAxisTickProps {\n x?: number\n y?: number\n payload?: {\n value: string | number\n }\n tickFormatter?: (value: string | number, index: number) => string\n index?: number\n visibleTicksCount?: number\n // Allow any additional props recharts might pass\n [key: string]: unknown\n}\n\n/**\n * Custom XAxis tick component for properly aligned angled labels.\n * Fixes alignment issues in recharts 3.7+ where angled labels don't\n * center properly under data points.\n */\nconst AngledXAxisTick: React.FC<AngledXAxisTickProps> = ({\n x = 0,\n y = 0,\n payload,\n tickFormatter,\n index = 0\n}) => {\n if (!payload) return null\n\n const displayValue = tickFormatter\n ? tickFormatter(payload.value, index)\n : String(payload.value)\n\n return (\n <g transform={`translate(${x},${y})`}>\n <text\n x={0}\n y={0}\n dy={16}\n textAnchor=\"end\"\n fill=\"currentColor\"\n fontSize={12}\n transform=\"rotate(-45)\"\n >\n {displayValue}\n </text>\n </g>\n )\n}\n\nexport default AngledXAxisTick\n","/**\n * Utility functions for handling target values in charts\n */\n\n/**\n * Parse target values from string format\n * @param targetString - String containing target values (e.g., \"100\" or \"50,75,100\")\n * @returns Array of numeric target values\n */\nexport function parseTargetValues(targetString: string): number[] {\n if (!targetString || typeof targetString !== 'string') {\n return []\n }\n\n const trimmed = targetString.trim()\n if (!trimmed) {\n return []\n }\n\n try {\n // Split by comma and parse each value\n const values = trimmed\n .split(',')\n .map(val => val.trim())\n .filter(val => val !== '')\n .map(val => {\n const num = parseFloat(val)\n if (isNaN(num)) {\n throw new Error(`Invalid numeric value: ${val}`)\n }\n return num\n })\n\n return values.length > 0 ? values : []\n } catch (error) {\n console.warn('Failed to parse target values:', error)\n return []\n }\n}\n\n/**\n * Spread target values across data points\n * @param targets - Array of target values\n * @param dataLength - Number of data points to spread across\n * @returns Array of target values for each data point\n */\nexport function spreadTargetValues(targets: number[], dataLength: number): number[] {\n if (targets.length === 0 || dataLength <= 0) {\n return []\n }\n\n // If only one target value, repeat for all data points\n if (targets.length === 1) {\n return new Array(dataLength).fill(targets[0])\n }\n\n // If we have multiple targets, spread them evenly across data points\n const result: number[] = []\n const baseGroupSize = Math.floor(dataLength / targets.length)\n const remainder = dataLength % targets.length\n\n let currentIndex = 0\n \n for (let i = 0; i < targets.length; i++) {\n // Calculate group size for this target\n // First 'remainder' groups get an extra item\n const groupSize = baseGroupSize + (i < remainder ? 1 : 0)\n \n // Fill this group with the current target value\n for (let j = 0; j < groupSize; j++) {\n result[currentIndex++] = targets[i]\n }\n }\n\n return result\n}\n\n/**\n * Calculate variance between actual and target values\n * @param actual - Actual value\n * @param target - Target value\n * @returns Variance as percentage\n */\nexport function calculateVariance(actual: number, target: number): number {\n if (target === 0) {\n return actual === 0 ? 0 : (actual > 0 ? 100 : -100)\n }\n return ((actual - target) / target) * 100\n}\n\n/**\n * Format variance as percentage string with appropriate sign and color indication\n * @param variance - Variance percentage\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted variance string (e.g., \"+12.5%\" or \"-8.3%\")\n */\nexport function formatVariance(variance: number, decimals: number = 1): string {\n const sign = variance >= 0 ? '+' : ''\n return `${sign}${variance.toFixed(decimals)}%`\n}\n\n/**\n * Get unique target values for reference lines\n * @param targets - Array of target values (may contain duplicates)\n * @returns Array of unique target values\n */\nexport function getUniqueTargets(targets: number[]): number[] {\n return [...new Set(targets)].sort((a, b) => a - b)\n}","import React, { useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport AngledXAxisTick from './AngledXAxisTick'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst AreaChart = React.memo(function AreaChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n \n try {\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.area')}</div>\n </div>\n </div>\n )\n }\n\n // Validate chartConfig - support both legacy and new formats\n let xAxisField: string\n let yAxisFields: string[]\n let seriesFields: string[] = []\n \n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n <div className=\"dc:text-xs\">{t('chart.runtime.configErrorHint.axisInvalid')}</div>\n </div>\n </div>\n )\n }\n\n if (!xAxisField || !yAxisFields || yAxisFields.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n <div className=\"dc:text-xs\">{t('chart.runtime.configErrorHint.axisFields')}</div>\n </div>\n </div>\n )\n }\n\n // Use shared function to transform data and handle series\n const { data: chartData, seriesKeys } = transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig\n const yAxisAssignment = chartConfig?.yAxisAssignment || {}\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n seriesKeyToField[label] = field\n })\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Disable stacking when dual Y-axis is used (areas on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noValidData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No valid data points for area chart after transformation</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n const stackOffset = effectiveIsPercentStack ? ('expand' as const) : undefined\n\n return (\n <ChartContainer height={height}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />}\n <XAxis dataKey=\"name\" type=\"category\" tick={<AngledXAxisTick />} height={60} />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n // When drill is enabled, show persistent dots for better click targets\n const areaColor = (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n\n return (\n <Area\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n stroke={areaColor}\n fill={areaColor}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 0.6 : 0.1) : 0.3}\n strokeWidth={2}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={safeDisplayConfig.connectNulls}\n dot={(props: any) => {\n const { cx, cy, payload, key } = props\n if (!drillEnabled || cx === undefined || cy === undefined) return null\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n event.preventDefault()\n if (onDataPointClick) {\n onDataPointClick({\n dataPoint: payload,\n clickedField: originalField || seriesKey,\n xValue: payload.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n return (\n <g key={key}>\n {/* Background to mask grid lines - uses theme surface color */}\n <circle\n cx={cx}\n cy={cy}\n r={6}\n fill=\"var(--dc-surface)\"\n style={{ pointerEvents: 'none' }}\n />\n {/* Visible dot with click handler */}\n <circle\n cx={cx}\n cy={cy}\n r={4}\n fill=\"var(--dc-surface)\"\n stroke={areaColor}\n strokeWidth={2}\n cursor=\"pointer\"\n onClick={(e: React.MouseEvent<SVGCircleElement>) => {\n handleClick(e as unknown as React.MouseEvent)\n }}\n />\n </g>\n )\n }}\n activeDot={false}\n />\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n )\n } catch (error) {\n // 'AreaChart rendering error\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.chartError', { chartType: 'Area Chart' })}</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : t('chart.runtime.unknownError')}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">{t('chart.runtime.checkConfig')}</div>\n </div>\n </div>\n )\n }\n})\n\nexport default AreaChart"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-area-DDti9Qtp.js","names":[],"sources":["../../../src/client/components/LoadingIndicator.tsx","../../../src/client/components/charts/ChartContainer.tsx","../../../src/client/components/charts/ChartTooltip.tsx","../../../src/client/components/charts/AngledXAxisTick.tsx","../../../src/client/utils/targetUtils.ts","../../../src/client/components/charts/AreaChart.tsx"],"sourcesContent":["/**\n * LoadingIndicator Component\n *\n * A centralized, theme-aware loading spinner that uses CSS variables\n * for consistent styling across all drizzle-cube components.\n *\n * Can be overridden at the Dashboard or Portlet level by passing a\n * custom loadingComponent prop.\n */\n\nexport interface LoadingIndicatorProps {\n /** Size variant: 'xs' (12px), 'sm' (24px), 'md' (32px), 'lg' (48px) */\n size?: 'xs' | 'sm' | 'md' | 'lg'\n /** Additional CSS classes */\n className?: string\n}\n\nconst sizeClasses = {\n xs: 'dc:h-3 dc:w-3',\n sm: 'dc:h-6 dc:w-6',\n md: 'dc:h-8 dc:w-8',\n lg: 'dc:h-12 dc:w-12'\n}\n\nexport default function LoadingIndicator({\n size = 'md',\n className = ''\n}: LoadingIndicatorProps) {\n return (\n <div\n className={`dc:animate-spin dc:rounded-full dc:border-b-2 ${sizeClasses[size]} ${className}`}\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n role=\"status\"\n aria-label=\"Loading\"\n />\n )\n}\n","import { ReactElement, useState, useRef, useLayoutEffect, startTransition } from 'react'\nimport { ResponsiveContainer } from 'recharts'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport LoadingIndicator from '../LoadingIndicator'\n\ninterface ChartContainerProps {\n children: ReactElement\n height?: string | number\n}\n\nexport default function ChartContainer({ children, height = \"100%\" }: ChartContainerProps) {\n const { t } = useTranslation()\n // Track if container is ready to render ResponsiveContainer\n // We need to wait for the container to be in the DOM with valid dimensions\n const containerRef = useRef<HTMLDivElement>(null)\n const [isReady, setIsReady] = useState(false)\n const [containerSize, setContainerSize] = useState({ width: 0, height: 0 })\n const sizeRef = useRef({ width: 0, height: 0 })\n const readyRef = useRef(false)\n const pendingSizeRef = useRef<{ width: number; height: number } | null>(null)\n const frameRef = useRef<number | null>(null)\n\n // Use useLayoutEffect to measure before paint\n useLayoutEffect(() => {\n let mounted = true\n let resizeObserver: ResizeObserver | null = null\n\n const flushPendingSize = () => {\n frameRef.current = null\n if (!mounted) return\n const pending = pendingSizeRef.current\n pendingSizeRef.current = null\n if (!pending) return\n\n const nextWidth = Math.round(pending.width)\n const nextHeight = Math.round(pending.height)\n if (nextWidth <= 0 || nextHeight <= 0) return\n\n const sizeChanged =\n sizeRef.current.width !== nextWidth || sizeRef.current.height !== nextHeight\n const shouldBecomeReady = !readyRef.current\n\n if (!sizeChanged && !shouldBecomeReady) return\n\n sizeRef.current = { width: nextWidth, height: nextHeight }\n readyRef.current = true\n\n // Resize-driven chart updates can come in bursts (one per portlet).\n // Transitioning these avoids blocking urgent input and coalesces visual work.\n startTransition(() => {\n if (sizeChanged) {\n setContainerSize({ width: nextWidth, height: nextHeight })\n }\n if (shouldBecomeReady) {\n setIsReady(true)\n }\n })\n }\n\n const scheduleSizeUpdate = (width: number, height: number) => {\n pendingSizeRef.current = { width, height }\n if (frameRef.current === null) {\n frameRef.current = requestAnimationFrame(flushPendingSize)\n }\n }\n\n const measureAndSetReady = () => {\n if (!mounted || !containerRef.current) return\n\n const rect = containerRef.current.getBoundingClientRect()\n // Check both clientWidth/Height AND getBoundingClientRect for robustness\n const width = Math.max(containerRef.current.clientWidth, rect.width)\n const measuredHeight = Math.max(containerRef.current.clientHeight, rect.height)\n\n if (width > 0 && measuredHeight > 0) {\n scheduleSizeUpdate(width, measuredHeight)\n }\n }\n\n // Set up ResizeObserver to detect when container gets valid dimensions\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: entryHeight } = entry.contentRect\n if (width > 0 && entryHeight > 0) {\n scheduleSizeUpdate(width, entryHeight)\n }\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n // Also try immediate measurement\n measureAndSetReady()\n }\n\n return () => {\n mounted = false\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current)\n frameRef.current = null\n }\n resizeObserver?.disconnect()\n }\n }, [])\n\n try {\n if (height === \"100%\") {\n // For 100% height, make the container fill the available flex space with proper sizing\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:h-full dc:flex-1 dc:flex dc:flex-col dc:relative\"\n style={{ minHeight: '250px', minWidth: '100px', overflow: 'hidden', userSelect: 'none' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n }\n\n // For specific heights, use them directly\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n const containerStyle = {\n height: typeof height === 'number' ? `${height}px` : height,\n width: '100%',\n minHeight: '200px',\n minWidth: '100px',\n userSelect: 'none' as const\n }\n\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:flex dc:flex-col dc:relative\"\n style={{ ...containerStyle, overflow: 'hidden' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n } catch (error) {\n // ChartContainer ResponsiveContainer error\n\n return (\n <div\n className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-4 dc:text-center dc:border dc:border-dashed dc:rounded-lg\"\n style={{ height, borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}\n >\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1 text-dc-text-muted\">{t('chart.runtime.unableToDisplay')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {error instanceof Error ? error.message : 'Failed to create responsive container'}\n </div>\n </div>\n )\n }\n}\n","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, payload?: readonly 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}","import React from 'react'\n\ninterface AngledXAxisTickProps {\n x?: number\n y?: number\n payload?: {\n value: string | number\n }\n tickFormatter?: (value: string | number, index: number) => string\n index?: number\n visibleTicksCount?: number\n // Allow any additional props recharts might pass\n [key: string]: unknown\n}\n\n/**\n * Custom XAxis tick component for properly aligned angled labels.\n * Fixes alignment issues in recharts 3.7+ where angled labels don't\n * center properly under data points.\n */\nconst AngledXAxisTick: React.FC<AngledXAxisTickProps> = ({\n x = 0,\n y = 0,\n payload,\n tickFormatter,\n index = 0\n}) => {\n if (!payload) return null\n\n const displayValue = tickFormatter\n ? tickFormatter(payload.value, index)\n : String(payload.value)\n\n return (\n <g transform={`translate(${x},${y})`}>\n <text\n x={0}\n y={0}\n dy={16}\n textAnchor=\"end\"\n fill=\"currentColor\"\n fontSize={12}\n transform=\"rotate(-45)\"\n >\n {displayValue}\n </text>\n </g>\n )\n}\n\nexport default AngledXAxisTick\n","/**\n * Utility functions for handling target values in charts\n */\n\n/**\n * Parse target values from string format\n * @param targetString - String containing target values (e.g., \"100\" or \"50,75,100\")\n * @returns Array of numeric target values\n */\nexport function parseTargetValues(targetString: string): number[] {\n if (!targetString || typeof targetString !== 'string') {\n return []\n }\n\n const trimmed = targetString.trim()\n if (!trimmed) {\n return []\n }\n\n try {\n // Split by comma and parse each value\n const values = trimmed\n .split(',')\n .map(val => val.trim())\n .filter(val => val !== '')\n .map(val => {\n const num = parseFloat(val)\n if (isNaN(num)) {\n throw new Error(`Invalid numeric value: ${val}`)\n }\n return num\n })\n\n return values.length > 0 ? values : []\n } catch (error) {\n console.warn('Failed to parse target values:', error)\n return []\n }\n}\n\n/**\n * Spread target values across data points\n * @param targets - Array of target values\n * @param dataLength - Number of data points to spread across\n * @returns Array of target values for each data point\n */\nexport function spreadTargetValues(targets: number[], dataLength: number): number[] {\n if (targets.length === 0 || dataLength <= 0) {\n return []\n }\n\n // If only one target value, repeat for all data points\n if (targets.length === 1) {\n return new Array(dataLength).fill(targets[0])\n }\n\n // If we have multiple targets, spread them evenly across data points\n const result: number[] = []\n const baseGroupSize = Math.floor(dataLength / targets.length)\n const remainder = dataLength % targets.length\n\n let currentIndex = 0\n \n for (let i = 0; i < targets.length; i++) {\n // Calculate group size for this target\n // First 'remainder' groups get an extra item\n const groupSize = baseGroupSize + (i < remainder ? 1 : 0)\n \n // Fill this group with the current target value\n for (let j = 0; j < groupSize; j++) {\n result[currentIndex++] = targets[i]\n }\n }\n\n return result\n}\n\n/**\n * Calculate variance between actual and target values\n * @param actual - Actual value\n * @param target - Target value\n * @returns Variance as percentage\n */\nexport function calculateVariance(actual: number, target: number): number {\n if (target === 0) {\n return actual === 0 ? 0 : (actual > 0 ? 100 : -100)\n }\n return ((actual - target) / target) * 100\n}\n\n/**\n * Format variance as percentage string with appropriate sign and color indication\n * @param variance - Variance percentage\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted variance string (e.g., \"+12.5%\" or \"-8.3%\")\n */\nexport function formatVariance(variance: number, decimals: number = 1): string {\n const sign = variance >= 0 ? '+' : ''\n return `${sign}${variance.toFixed(decimals)}%`\n}\n\n/**\n * Get unique target values for reference lines\n * @param targets - Array of target values (may contain duplicates)\n * @returns Array of unique target values\n */\nexport function getUniqueTargets(targets: number[]): number[] {\n return [...new Set(targets)].sort((a, b) => a - b)\n}","import React, { useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport AngledXAxisTick from './AngledXAxisTick'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst AreaChart = React.memo(function AreaChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n \n try {\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.area')}</div>\n </div>\n </div>\n )\n }\n\n // Validate chartConfig - support both legacy and new formats\n let xAxisField: string\n let yAxisFields: string[]\n let seriesFields: string[] = []\n \n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n <div className=\"dc:text-xs\">{t('chart.runtime.configErrorHint.axisInvalid')}</div>\n </div>\n </div>\n )\n }\n\n if (!xAxisField || !yAxisFields || yAxisFields.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n <div className=\"dc:text-xs\">{t('chart.runtime.configErrorHint.axisFields')}</div>\n </div>\n </div>\n )\n }\n\n // Use shared function to transform data and handle series\n const { data: chartData, seriesKeys } = transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig\n const yAxisAssignment = chartConfig?.yAxisAssignment || {}\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n seriesKeyToField[label] = field\n })\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Disable stacking when dual Y-axis is used (areas on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noValidData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No valid data points for area chart after transformation</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n const stackOffset = effectiveIsPercentStack ? ('expand' as const) : undefined\n\n return (\n <ChartContainer height={height}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />}\n <XAxis dataKey=\"name\" type=\"category\" tick={<AngledXAxisTick />} height={60} />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n // When drill is enabled, show persistent dots for better click targets\n const areaColor = (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n\n return (\n <Area\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n stroke={areaColor}\n fill={areaColor}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 0.6 : 0.1) : 0.3}\n strokeWidth={2}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={safeDisplayConfig.connectNulls}\n dot={(props: any) => {\n const { cx, cy, payload, key } = props\n if (!drillEnabled || cx === undefined || cy === undefined) return null\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n event.preventDefault()\n if (onDataPointClick) {\n onDataPointClick({\n dataPoint: payload,\n clickedField: originalField || seriesKey,\n xValue: payload.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n return (\n <g key={key}>\n {/* Background to mask grid lines - uses theme surface color */}\n <circle\n cx={cx}\n cy={cy}\n r={6}\n fill=\"var(--dc-surface)\"\n style={{ pointerEvents: 'none' }}\n />\n {/* Visible dot with click handler */}\n <circle\n cx={cx}\n cy={cy}\n r={4}\n fill=\"var(--dc-surface)\"\n stroke={areaColor}\n strokeWidth={2}\n cursor=\"pointer\"\n onClick={(e: React.MouseEvent<SVGCircleElement>) => {\n handleClick(e as unknown as React.MouseEvent)\n }}\n />\n </g>\n )\n }}\n activeDot={false}\n />\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n )\n } catch (error) {\n // 'AreaChart rendering error\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.chartError', { chartType: 'Area Chart' })}</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : t('chart.runtime.unknownError')}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">{t('chart.runtime.checkConfig')}</div>\n </div>\n </div>\n )\n }\n})\n\nexport default AreaChart"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as e } from "./rolldown-runtime-CCl2IeXn.js";
|
|
2
2
|
import { D as t, _ as n, i as r, k as i, n as a, o as ee, w as o, y as s } from "./chart-activity-grid-CWT0gLv4.js";
|
|
3
|
-
import { a as te, c, l, o as u, s as d } from "./chart-area-
|
|
3
|
+
import { a as te, c, l, o as u, s as d } from "./chart-area-DDti9Qtp.js";
|
|
4
4
|
import f, { useMemo as p, useState as m } from "react";
|
|
5
5
|
import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
6
6
|
import { Bar as v, CartesianGrid as y, Cell as b, ComposedChart as x, Legend as ne, Line as S, XAxis as C, YAxis as w } from "recharts";
|
|
@@ -267,4 +267,4 @@ var T = /* @__PURE__ */ e({ default: () => E }), E = f.memo(function({ data: e,
|
|
|
267
267
|
//#endregion
|
|
268
268
|
export { T as n, E as t };
|
|
269
269
|
|
|
270
|
-
//# sourceMappingURL=chart-bar-
|
|
270
|
+
//# sourceMappingURL=chart-bar-B3s9qDlh.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-bar-BEfsCLjl.js","names":[],"sources":["../../../src/client/components/charts/BarChart.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { ComposedChart, Bar, Line, XAxis, YAxis, CartesianGrid, Cell, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport AngledXAxisTick from './AngledXAxisTick'\nimport { CHART_COLORS, POSITIVE_COLOR, NEGATIVE_COLOR, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, isValidNumericValue, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst BarChart = React.memo(function BarChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n // Validate chartConfig - support both legacy and new formats\n // Do validation but don't early return yet (hooks must come first)\n const { xAxisField, yAxisFields, seriesFields, configError } = useMemo(() => {\n let xAxisField: string | undefined\n let yAxisFields: string[] = []\n let seriesFields: string[] = []\n let configError: string | null = null\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n configError = 'Invalid or missing chart axis configuration'\n }\n\n if (!configError && (!xAxisField || !yAxisFields || yAxisFields.length === 0)) {\n configError = 'Missing required X-axis or Y-axis fields'\n }\n\n return { xAxisField, yAxisFields, seriesFields, configError }\n }, [chartConfig])\n\n // Transform data (will be empty arrays if config is invalid)\n const { data: transformedData, seriesKeys } = useMemo(() => {\n if (configError || !data || data.length === 0 || !xAxisField) {\n return { data: [], seriesKeys: [] }\n }\n return transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n }, [data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel, configError])\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig (memoized to prevent object recreation)\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = useMemo(() => {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n mapping[label] = field\n })\n return mapping\n }, [yAxisFields, getFieldLabel])\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Null handling: Filter out data points where ALL measure values are null\n // This prevents rendering empty bars and makes the chart clearer\n const { chartData, skippedCount } = useMemo(() => {\n if (transformedData.length === 0 || seriesKeys.length === 0) {\n return { chartData: [], skippedCount: 0 }\n }\n const filtered = transformedData.filter(row => {\n // Keep the row if at least one series has a valid numeric value\n return seriesKeys.some(key => isValidNumericValue(row[key]))\n })\n const skipped = transformedData.length - filtered.length\n return { chartData: filtered, skippedCount: skipped }\n }, [transformedData, seriesKeys])\n\n // Now handle early returns AFTER all hooks\n try {\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in bar chart</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n // Disable stacking when dual Y-axis is used (bars on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n const stackOffset = effectiveIsPercentStack ? 'expand' as const : undefined\n\n // Check if we should use positive/negative coloring\n // This is enabled when we have single series data with mixed positive/negative values\n const usePositiveNegativeColoring = seriesKeys.length === 1 && chartData.some(row => {\n const value = row[seriesKeys[0]]\n return typeof value === 'number' && value < 0\n })\n\n // Color each bar by its x-axis category when there's a single measure and no series dimension.\n // This gives each category a distinct color without needing to abuse the series field.\n const useColorByCategory = seriesKeys.length === 1\n && !usePositiveNegativeColoring\n && !seriesFields.length\n && chartData.length > 1\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noValidData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No valid data points for bar chart after transformation</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:relative dc:w-full\" style={{ height }}>\n <ChartContainer height={skippedCount > 0 ? `calc(100% - 20px)` : \"100%\"}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && (\n <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />\n )}\n <XAxis\n dataKey=\"name\"\n type=\"category\"\n tick={<AngledXAxisTick />}\n height={60}\n />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '25px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n return (\n <Bar\n key={seriesKey}\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n fill={\n usePositiveNegativeColoring\n ? POSITIVE_COLOR\n : (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n cursor={drillEnabled ? 'pointer' : undefined}\n onClick={(barData: any, dataIndex: number, event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled && barData) {\n onDataPointClick({\n dataPoint: enhancedChartData[dataIndex] || barData,\n clickedField: originalField || seriesKey,\n xValue: barData.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }}\n >\n {usePositiveNegativeColoring &&\n chartData.map((entry, entryIndex) => {\n const value = entry[seriesKey]\n const fillColor = typeof value === 'number' && value < 0 ? NEGATIVE_COLOR : POSITIVE_COLOR\n return (\n <Cell\n key={`cell-${entryIndex}`}\n fill={fillColor}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n />\n )\n })}\n {useColorByCategory &&\n chartData.map((_entry, entryIndex) => {\n const colors = colorPalette?.colors || CHART_COLORS\n return (\n <Cell\n key={`cat-${entryIndex}`}\n fill={colors[entryIndex % colors.length]}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n />\n )\n })}\n </Bar>\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n {skippedCount > 0 && (\n <div className=\"dc:text-xs text-dc-text-muted dc:text-center dc:mt-1\">\n {skippedCount} data point{skippedCount !== 1 ? 's' : ''} with no values hidden\n </div>\n )}\n </div>\n )\n } catch (error) {\n // 'BarChart rendering error\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.chartError', { chartType: 'Bar Chart' })}</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : t('chart.runtime.unknownError')}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">{t('chart.runtime.checkConfig')}</div>\n </div>\n </div>\n )\n }\n})\n\nexport default BarChart"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-bar-B3s9qDlh.js","names":[],"sources":["../../../src/client/components/charts/BarChart.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { ComposedChart, Bar, Line, XAxis, YAxis, CartesianGrid, Cell, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport AngledXAxisTick from './AngledXAxisTick'\nimport { CHART_COLORS, POSITIVE_COLOR, NEGATIVE_COLOR, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, isValidNumericValue, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst BarChart = React.memo(function BarChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n // Validate chartConfig - support both legacy and new formats\n // Do validation but don't early return yet (hooks must come first)\n const { xAxisField, yAxisFields, seriesFields, configError } = useMemo(() => {\n let xAxisField: string | undefined\n let yAxisFields: string[] = []\n let seriesFields: string[] = []\n let configError: string | null = null\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n configError = 'Invalid or missing chart axis configuration'\n }\n\n if (!configError && (!xAxisField || !yAxisFields || yAxisFields.length === 0)) {\n configError = 'Missing required X-axis or Y-axis fields'\n }\n\n return { xAxisField, yAxisFields, seriesFields, configError }\n }, [chartConfig])\n\n // Transform data (will be empty arrays if config is invalid)\n const { data: transformedData, seriesKeys } = useMemo(() => {\n if (configError || !data || data.length === 0 || !xAxisField) {\n return { data: [], seriesKeys: [] }\n }\n return transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n }, [data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel, configError])\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig (memoized to prevent object recreation)\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = useMemo(() => {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n mapping[label] = field\n })\n return mapping\n }, [yAxisFields, getFieldLabel])\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Null handling: Filter out data points where ALL measure values are null\n // This prevents rendering empty bars and makes the chart clearer\n const { chartData, skippedCount } = useMemo(() => {\n if (transformedData.length === 0 || seriesKeys.length === 0) {\n return { chartData: [], skippedCount: 0 }\n }\n const filtered = transformedData.filter(row => {\n // Keep the row if at least one series has a valid numeric value\n return seriesKeys.some(key => isValidNumericValue(row[key]))\n })\n const skipped = transformedData.length - filtered.length\n return { chartData: filtered, skippedCount: skipped }\n }, [transformedData, seriesKeys])\n\n // Now handle early returns AFTER all hooks\n try {\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in bar chart</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n // Disable stacking when dual Y-axis is used (bars on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n const stackOffset = effectiveIsPercentStack ? 'expand' as const : undefined\n\n // Check if we should use positive/negative coloring\n // This is enabled when we have single series data with mixed positive/negative values\n const usePositiveNegativeColoring = seriesKeys.length === 1 && chartData.some(row => {\n const value = row[seriesKeys[0]]\n return typeof value === 'number' && value < 0\n })\n\n // Color each bar by its x-axis category when there's a single measure and no series dimension.\n // This gives each category a distinct color without needing to abuse the series field.\n const useColorByCategory = seriesKeys.length === 1\n && !usePositiveNegativeColoring\n && !seriesFields.length\n && chartData.length > 1\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.noValidData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No valid data points for bar chart after transformation</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:relative dc:w-full\" style={{ height }}>\n <ChartContainer height={skippedCount > 0 ? `calc(100% - 20px)` : \"100%\"}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && (\n <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />\n )}\n <XAxis\n dataKey=\"name\"\n type=\"category\"\n tick={<AngledXAxisTick />}\n height={60}\n />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '25px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n return (\n <Bar\n key={seriesKey}\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n fill={\n usePositiveNegativeColoring\n ? POSITIVE_COLOR\n : (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n cursor={drillEnabled ? 'pointer' : undefined}\n onClick={(barData: any, dataIndex: number, event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled && barData) {\n onDataPointClick({\n dataPoint: enhancedChartData[dataIndex] || barData,\n clickedField: originalField || seriesKey,\n xValue: barData.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }}\n >\n {usePositiveNegativeColoring &&\n chartData.map((entry, entryIndex) => {\n const value = entry[seriesKey]\n const fillColor = typeof value === 'number' && value < 0 ? NEGATIVE_COLOR : POSITIVE_COLOR\n return (\n <Cell\n key={`cell-${entryIndex}`}\n fill={fillColor}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n />\n )\n })}\n {useColorByCategory &&\n chartData.map((_entry, entryIndex) => {\n const colors = colorPalette?.colors || CHART_COLORS\n return (\n <Cell\n key={`cat-${entryIndex}`}\n fill={colors[entryIndex % colors.length]}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n />\n )\n })}\n </Bar>\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n {skippedCount > 0 && (\n <div className=\"dc:text-xs text-dc-text-muted dc:text-center dc:mt-1\">\n {skippedCount} data point{skippedCount !== 1 ? 's' : ''} with no values hidden\n </div>\n )}\n </div>\n )\n } catch (error) {\n // 'BarChart rendering error\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.chartError', { chartType: 'Bar Chart' })}</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : t('chart.runtime.unknownError')}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">{t('chart.runtime.checkConfig')}</div>\n </div>\n </div>\n )\n }\n})\n\nexport default BarChart"],"mappings":"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"}
|
|
@@ -2122,7 +2122,7 @@ function dn(e, t) {
|
|
|
2122
2122
|
async function fn() {
|
|
2123
2123
|
if (en) return B;
|
|
2124
2124
|
try {
|
|
2125
|
-
return B = await import("./exceljs.min-
|
|
2125
|
+
return B = await import("./exceljs.min-DaJsLlWM.js").then((t) => /* @__PURE__ */ e(t.default, 1)), en = !0, B;
|
|
2126
2126
|
} catch {
|
|
2127
2127
|
return en = !0, B = null, null;
|
|
2128
2128
|
}
|
|
@@ -4134,31 +4134,31 @@ var J = /* @__PURE__ */ new Map(), Y = /* @__PURE__ */ new Set(), Ha = {
|
|
|
4134
4134
|
installCommand: "npm install d3-shape"
|
|
4135
4135
|
}
|
|
4136
4136
|
}, Ua = {
|
|
4137
|
-
bar: () => import("./chart-bar-
|
|
4138
|
-
line: () => import("./chart-line-
|
|
4139
|
-
area: () => import("./chart-area-
|
|
4140
|
-
pie: () => import("./chart-pie-
|
|
4141
|
-
scatter: () => import("./chart-scatter-
|
|
4142
|
-
radar: () => import("./chart-radar-
|
|
4143
|
-
radialBar: () => import("./chart-radial-bar-
|
|
4144
|
-
treemap: () => import("./chart-tree-map-
|
|
4137
|
+
bar: () => import("./chart-bar-B3s9qDlh.js").then((e) => e.n),
|
|
4138
|
+
line: () => import("./chart-line-RdZwtk27.js").then((e) => e.n),
|
|
4139
|
+
area: () => import("./chart-area-DDti9Qtp.js").then((e) => e.n),
|
|
4140
|
+
pie: () => import("./chart-pie-BvY4FY__.js").then((e) => e.n),
|
|
4141
|
+
scatter: () => import("./chart-scatter-DwXnI0rr.js").then((e) => e.n),
|
|
4142
|
+
radar: () => import("./chart-radar-DjiiEAmc.js").then((e) => e.n),
|
|
4143
|
+
radialBar: () => import("./chart-radial-bar-lla_JEYu.js").then((e) => e.n),
|
|
4144
|
+
treemap: () => import("./chart-tree-map-DJHoA26f.js").then((e) => e.n),
|
|
4145
4145
|
bubble: () => import("./chart-bubble-CMDp4Pfm.js").then((e) => e.t),
|
|
4146
4146
|
table: () => Promise.resolve().then(() => Lo),
|
|
4147
4147
|
activityGrid: () => import("./chart-activity-grid-CWT0gLv4.js").then((e) => e.t),
|
|
4148
|
-
kpiNumber: () => import("./KpiNumber-
|
|
4149
|
-
kpiDelta: () => import("./KpiDelta-
|
|
4150
|
-
kpiText: () => import("./KpiText-
|
|
4151
|
-
markdown: () => import("./chart-markdown-
|
|
4148
|
+
kpiNumber: () => import("./KpiNumber-t5n8PtRU.js"),
|
|
4149
|
+
kpiDelta: () => import("./KpiDelta-_igN6cJa.js"),
|
|
4150
|
+
kpiText: () => import("./KpiText-BCZJJ6a0.js"),
|
|
4151
|
+
markdown: () => import("./chart-markdown-CiGRZdJj.js").then((e) => e.n),
|
|
4152
4152
|
funnel: () => import("./chart-funnel-C7pgktN5.js").then((e) => e.n),
|
|
4153
4153
|
sankey: () => import("./chart-sankey-WwkZAhLy.js").then((e) => e.t),
|
|
4154
4154
|
sunburst: () => import("./chart-sunburst-CIDB_pTl.js").then((e) => e.t),
|
|
4155
4155
|
heatmap: () => import("./chart-heat-map-Dw2yjwfO.js").then((e) => e.t),
|
|
4156
4156
|
retentionHeatmap: () => import("./RetentionHeatmap-B_5sewwi.js"),
|
|
4157
|
-
retentionCombined: () => import("./RetentionCombinedChart-
|
|
4157
|
+
retentionCombined: () => import("./RetentionCombinedChart-CQMBODsK.js"),
|
|
4158
4158
|
boxPlot: () => import("./chart-box-plot-o-h9MRX5.js").then((e) => e.t),
|
|
4159
|
-
waterfall: () => import("./chart-waterfall-
|
|
4159
|
+
waterfall: () => import("./chart-waterfall-Y7c8csO5.js").then((e) => e.t),
|
|
4160
4160
|
candlestick: () => import("./chart-candlestick-WyANJ0Ky.js").then((e) => e.t),
|
|
4161
|
-
measureProfile: () => import("./chart-measure-profile-
|
|
4161
|
+
measureProfile: () => import("./chart-measure-profile-Ckjw9bX6.js").then((e) => e.t),
|
|
4162
4162
|
gauge: () => import("./chart-gauge-D2r2B_AR.js").then((e) => e.t)
|
|
4163
4163
|
}, X = /* @__PURE__ */ new Map();
|
|
4164
4164
|
function Wa(e) {
|
|
@@ -4905,4 +4905,4 @@ function Uo(e, t) {
|
|
|
4905
4905
|
//#endregion
|
|
4906
4906
|
export { Lt as $, q as A, ci as B, to as C, Qa as D, Za as E, Fa as F, Jt as G, vn as H, Ia as I, Yt as J, $t as K, Pa as L, Ma as M, La as N, za as O, Ra as P, Ft as Q, ka as R, $a as S, Ja as T, pn as U, Cn as V, mn as W, Wt as X, qt as Y, Vt as Z, mo as _, Ue as _t, Ao as a, Ot as at, uo as b, Oo as c, St as ct, xo as d, rt as dt, Pt as et, yo as f, F as ft, lo as g, Ne as gt, co as h, Me as ht, ko as i, Et as it, Na as j, Ba as k, $ as l, yt as lt, so as m, k as mt, Lo as n, Mt as nt, Fo as o, Dt as ot, ho as p, M as pt, Xt as q, Io as r, jt as rt, Do as s, Tt as st, Ro as t, kt as tt, Q as u, mt as ut, fo as v, D as vt, eo as w, Xa as x, po as y, Oa as z };
|
|
4907
4907
|
|
|
4908
|
-
//# sourceMappingURL=chart-data-table-
|
|
4908
|
+
//# sourceMappingURL=chart-data-table-Qrt6EAno.js.map
|