drizzle-cube 0.2.11 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/adapters/compiler-CMwSRhTS.cjs +22 -0
  2. package/dist/adapters/{compiler-gcKytLwd.js → compiler-DrkCCzf0.js} +16 -11
  3. package/dist/adapters/express/index.cjs +1 -1
  4. package/dist/adapters/express/index.js +8 -8
  5. package/dist/adapters/fastify/index.cjs +1 -1
  6. package/dist/adapters/fastify/index.js +9 -9
  7. package/dist/adapters/hono/index.cjs +1 -1
  8. package/dist/adapters/hono/index.js +11 -11
  9. package/dist/adapters/nextjs/index.cjs +1 -1
  10. package/dist/adapters/nextjs/index.js +59 -59
  11. package/dist/client/charts.js +11 -11
  12. package/dist/client/chunks/{chart-activitygridchart-D17Fxiuf.js → chart-activitygridchart-CUGN9Xq9.js} +3 -2
  13. package/dist/client/chunks/chart-activitygridchart-CUGN9Xq9.js.map +1 -0
  14. package/dist/client/chunks/{chart-areachart-udSbAzl1.js → chart-areachart-B4tknnsY.js} +25 -25
  15. package/dist/client/chunks/{chart-areachart-udSbAzl1.js.map → chart-areachart-B4tknnsY.js.map} +1 -1
  16. package/dist/client/chunks/{chart-axisformatcontrols-DqSa245M.js → chart-axisformatcontrols-Ch_IYF94.js} +18 -18
  17. package/dist/client/chunks/chart-axisformatcontrols-Ch_IYF94.js.map +1 -0
  18. package/dist/client/chunks/{chart-barchart-CDIpqCKS.js → chart-barchart-D_op06r-.js} +6 -6
  19. package/dist/client/chunks/{chart-barchart-CDIpqCKS.js.map → chart-barchart-D_op06r-.js.map} +1 -1
  20. package/dist/client/chunks/{chart-bubblechart-CivK_yfh.js → chart-bubblechart-BsaIXUbS.js} +3 -3
  21. package/dist/client/chunks/chart-bubblechart-BsaIXUbS.js.map +1 -0
  22. package/dist/client/chunks/{chart-charttooltip-BVEdz4Q-.js → chart-charttooltip-Bx3I8jQv.js} +2 -2
  23. package/dist/client/chunks/{chart-charttooltip-BVEdz4Q-.js.map → chart-charttooltip-Bx3I8jQv.js.map} +1 -1
  24. package/dist/client/chunks/{chart-datatable-NHE7BTMr.js → chart-datatable-C7MS9q4Y.js} +2 -2
  25. package/dist/client/chunks/{chart-datatable-NHE7BTMr.js.map → chart-datatable-C7MS9q4Y.js.map} +1 -1
  26. package/dist/client/chunks/{chart-kpidelta-D-FR2o4V.js → chart-kpidelta-7-KOmb3w.js} +62 -60
  27. package/dist/client/chunks/chart-kpidelta-7-KOmb3w.js.map +1 -0
  28. package/dist/client/chunks/{chart-kpinumber-DSH8RJxb.js → chart-kpinumber-HOPfcK2N.js} +4 -4
  29. package/dist/client/chunks/{chart-kpinumber-DSH8RJxb.js.map → chart-kpinumber-HOPfcK2N.js.map} +1 -1
  30. package/dist/client/chunks/{chart-kpitext-Z9oh0bJq.js → chart-kpitext-BZkC9u3A.js} +24 -24
  31. package/dist/client/chunks/{chart-kpitext-Z9oh0bJq.js.map → chart-kpitext-BZkC9u3A.js.map} +1 -1
  32. package/dist/client/chunks/{chart-linechart-D4r0uD1j.js → chart-linechart-DqFmLbRe.js} +7 -7
  33. package/dist/client/chunks/{chart-linechart-D4r0uD1j.js.map → chart-linechart-DqFmLbRe.js.map} +1 -1
  34. package/dist/client/chunks/chart-markdownchart-9n_TemoB.js +256 -0
  35. package/dist/client/chunks/chart-markdownchart-9n_TemoB.js.map +1 -0
  36. package/dist/client/chunks/{chart-piechart-BhttUWuH.js → chart-piechart-CrXFd9pE.js} +6 -6
  37. package/dist/client/chunks/{chart-piechart-BhttUWuH.js.map → chart-piechart-CrXFd9pE.js.map} +1 -1
  38. package/dist/client/chunks/{chart-radarchart-DnqlfoGr.js → chart-radarchart-tar2GBkO.js} +5 -5
  39. package/dist/client/chunks/{chart-radarchart-DnqlfoGr.js.map → chart-radarchart-tar2GBkO.js.map} +1 -1
  40. package/dist/client/chunks/{chart-radialbarchart-BFxxiqLw.js → chart-radialbarchart-ab8Swtal.js} +5 -5
  41. package/dist/client/chunks/{chart-radialbarchart-BFxxiqLw.js.map → chart-radialbarchart-ab8Swtal.js.map} +1 -1
  42. package/dist/client/chunks/{chart-scatterchart-MN4SM-w7.js → chart-scatterchart-BP06BeU5.js} +5 -5
  43. package/dist/client/chunks/{chart-scatterchart-MN4SM-w7.js.map → chart-scatterchart-BP06BeU5.js.map} +1 -1
  44. package/dist/client/chunks/{chart-treemapchart-Nozh2m26.js → chart-treemapchart-DAiixITm.js} +31 -31
  45. package/dist/client/chunks/{chart-treemapchart-Nozh2m26.js.map → chart-treemapchart-DAiixITm.js.map} +1 -1
  46. package/dist/client/chunks/{charts-BSDHSv4l.js → charts-CHzWeaY1.js} +26 -26
  47. package/dist/client/chunks/charts-CHzWeaY1.js.map +1 -0
  48. package/dist/client/chunks/{components-CbDovlG-.js → components-DnM9CCUS.js} +2453 -2445
  49. package/dist/client/chunks/components-DnM9CCUS.js.map +1 -0
  50. package/dist/client/chunks/{index-th92_8oL.js → index-DlsvcKXf.js} +135 -135
  51. package/dist/client/chunks/index-DlsvcKXf.js.map +1 -0
  52. package/dist/client/components/AnalysisBuilder/AnalysisAxisDropZone.d.ts +5 -5
  53. package/dist/client/components/AnalysisBuilder/SectionHeading.d.ts +2 -7
  54. package/dist/client/components/AnalysisBuilder/types.d.ts +8 -8
  55. package/dist/client/components.js +2 -2
  56. package/dist/client/hooks/useResponsiveDashboard.d.ts +2 -8
  57. package/dist/client/hooks.js +2 -2
  58. package/dist/client/hooks.js.map +1 -1
  59. package/dist/client/icons/types.d.ts +2 -2
  60. package/dist/client/index.js +3 -3
  61. package/dist/client/providers.js +1 -1
  62. package/dist/client/styles.css +1 -1
  63. package/dist/client-bundle-stats.html +1 -1
  64. package/dist/server/index.cjs +2 -2
  65. package/dist/server/index.js +16 -11
  66. package/package.json +3 -3
  67. package/dist/adapters/compiler-DP1pPIcg.cjs +0 -22
  68. package/dist/client/chunks/chart-activitygridchart-D17Fxiuf.js.map +0 -1
  69. package/dist/client/chunks/chart-axisformatcontrols-DqSa245M.js.map +0 -1
  70. package/dist/client/chunks/chart-bubblechart-CivK_yfh.js.map +0 -1
  71. package/dist/client/chunks/chart-kpidelta-D-FR2o4V.js.map +0 -1
  72. package/dist/client/chunks/chart-markdownchart-C3FAQFuO.js +0 -254
  73. package/dist/client/chunks/chart-markdownchart-C3FAQFuO.js.map +0 -1
  74. package/dist/client/chunks/charts-BSDHSv4l.js.map +0 -1
  75. package/dist/client/chunks/components-CbDovlG-.js.map +0 -1
  76. package/dist/client/chunks/index-th92_8oL.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-axisformatcontrols-DqSa245M.js","sources":["../../../src/client/components/AnalysisBuilder/SectionHeading.tsx","../../../src/client/components/charts/AxisFormatControls.tsx"],"sourcesContent":["/**\n * SectionHeading Component\n *\n * A reusable section heading for the Analysis Builder panels.\n * Provides consistent styling that can be easily adjusted in one place.\n */\n\ninterface SectionHeadingProps {\n children: React.ReactNode\n /** Optional className to add additional styles */\n className?: string\n}\n\n/**\n * Consistent section heading style for Analysis Builder panels.\n * Change the styles here to update all section headings at once.\n */\nexport default function SectionHeading({ children, className = '' }: SectionHeadingProps) {\n return (\n <h3 className={`text-sm font-semibold text-dc-primary uppercase tracking-wide ${className}`}>\n {children}\n </h3>\n )\n}\n","/**\n * AxisFormatControls Component\n *\n * A reusable component for configuring axis number formatting.\n * Provides controls for unit type, abbreviation, decimal places, and custom labels.\n */\n\nimport { useMemo } from 'react'\nimport SectionHeading from '../AnalysisBuilder/SectionHeading'\nimport type { AxisFormatConfig } from '../../types'\nimport { formatAxisValue } from '../../utils/chartUtils'\n\ninterface AxisFormatControlsProps {\n value: AxisFormatConfig\n onChange: (config: AxisFormatConfig) => void\n axisLabel: string // \"X-Axis\", \"Left Y-Axis\", \"Right Y-Axis\"\n /** Sample value for preview (default: 1250000) */\n previewValue?: number\n}\n\n/**\n * Get the currency symbol for the user's locale\n */\nfunction getLocaleCurrencySymbol(): string {\n const locale = typeof navigator !== 'undefined' ? navigator.language : 'en-US'\n // Format a number as currency and extract just the symbol\n const formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: getCurrencyCodeForLocale(locale),\n currencyDisplay: 'narrowSymbol'\n }).format(0)\n // Extract the currency symbol (remove digits, spaces, and common separators)\n return formatted.replace(/[\\d.,\\s]/g, '').trim() || '$'\n}\n\n/**\n * Get the currency code for a given locale (duplicated from chartUtils for component isolation)\n */\nfunction getCurrencyCodeForLocale(locale: string): string {\n const parts = locale.split('-')\n const region = parts[1]?.toUpperCase()\n const currencyMap: Record<string, string> = {\n 'US': 'USD', 'CA': 'CAD', 'GB': 'GBP', 'UK': 'GBP', 'AU': 'AUD', 'NZ': 'NZD',\n 'EU': 'EUR', 'DE': 'EUR', 'FR': 'EUR', 'IT': 'EUR', 'ES': 'EUR', 'NL': 'EUR',\n 'BE': 'EUR', 'AT': 'EUR', 'IE': 'EUR', 'PT': 'EUR', 'FI': 'EUR',\n 'JP': 'JPY', 'CN': 'CNY', 'KR': 'KRW', 'IN': 'INR', 'BR': 'BRL', 'MX': 'MXN',\n 'CH': 'CHF', 'SE': 'SEK', 'NO': 'NOK', 'DK': 'DKK', 'PL': 'PLN', 'RU': 'RUB',\n 'ZA': 'ZAR', 'SG': 'SGD', 'HK': 'HKD', 'TW': 'TWD', 'TH': 'THB', 'MY': 'MYR',\n 'PH': 'PHP', 'ID': 'IDR', 'VN': 'VND', 'AE': 'AED', 'SA': 'SAR', 'IL': 'ILS', 'TR': 'TRY',\n }\n return currencyMap[region] || 'USD'\n}\n\n/**\n * Single axis format control section\n */\nexport function AxisFormatControls({\n value,\n onChange,\n axisLabel,\n previewValue = 1250000\n}: AxisFormatControlsProps) {\n const config = value || {}\n\n // Get locale-aware currency symbol for the button\n const currencySymbol = useMemo(() => getLocaleCurrencySymbol(), [])\n\n // Generate preview of formatted value\n const preview = useMemo(() => {\n return formatAxisValue(previewValue, config)\n }, [previewValue, config])\n\n const handleChange = (updates: Partial<AxisFormatConfig>) => {\n onChange({ ...config, ...updates })\n }\n\n const unitButtons: Array<{ value: AxisFormatConfig['unit']; label: string }> = [\n { value: 'currency', label: currencySymbol },\n { value: 'percent', label: '%' },\n { value: 'number', label: '#' },\n { value: 'custom', label: 'Custom' }\n ]\n\n return (\n <div className=\"space-y-3 pb-4\">\n {/* Axis Header */}\n <SectionHeading>{axisLabel}</SectionHeading>\n\n {/* Label Input */}\n <div className=\"space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Label</label>\n <input\n type=\"text\"\n value={config.label || ''}\n onChange={(e) => handleChange({ label: e.target.value || undefined })}\n placeholder=\"Auto-generated label\"\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n />\n </div>\n\n {/* Unit Type */}\n <div className=\"space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Unit</label>\n <div className=\"flex border border-dc-border rounded-sm overflow-hidden\">\n {unitButtons.map((btn) => (\n <button\n key={btn.value}\n type=\"button\"\n onClick={() => handleChange({ unit: btn.value })}\n className={`flex-1 px-2 py-1.5 text-sm font-medium transition-colors ${\n config.unit === btn.value\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n {btn.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Custom Prefix/Suffix (only when Custom is selected) */}\n {config.unit === 'custom' && (\n <div className=\"flex gap-2\">\n <div className=\"flex-1 space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Prefix</label>\n <input\n type=\"text\"\n value={config.customPrefix || ''}\n onChange={(e) => handleChange({ customPrefix: e.target.value || undefined })}\n placeholder=\"e.g., $\"\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n />\n </div>\n <div className=\"flex-1 space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Suffix</label>\n <input\n type=\"text\"\n value={config.customSuffix || ''}\n onChange={(e) => handleChange({ customSuffix: e.target.value || undefined })}\n placeholder=\"e.g., units\"\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n />\n </div>\n </div>\n )}\n\n {/* Abbreviation Toggle */}\n <div className=\"space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Abbreviation</label>\n <div className=\"flex border border-dc-border rounded-sm overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => handleChange({ abbreviate: true })}\n className={`flex-1 px-3 py-1.5 text-sm font-medium transition-colors ${\n config.abbreviate !== false\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n Yes\n </button>\n <button\n type=\"button\"\n onClick={() => handleChange({ abbreviate: false })}\n className={`flex-1 px-3 py-1.5 text-sm font-medium transition-colors ${\n config.abbreviate === false\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n No\n </button>\n </div>\n </div>\n\n {/* Decimals */}\n <div className=\"space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Decimals</label>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n const current = config.decimals ?? 2\n if (current > 0) handleChange({ decimals: current - 1 })\n }}\n disabled={(config.decimals ?? 2) <= 0}\n className=\"flex-1 px-3 py-2 text-sm border border-dc-border rounded-sm bg-dc-surface text-dc-text hover:bg-dc-border disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n >\n ← .0\n </button>\n <button\n type=\"button\"\n onClick={() => {\n const current = config.decimals ?? 2\n if (current < 4) handleChange({ decimals: current + 1 })\n }}\n disabled={(config.decimals ?? 2) >= 4}\n className=\"flex-1 px-3 py-2 text-sm border border-dc-border rounded-sm bg-dc-surface text-dc-text hover:bg-dc-border disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n >\n .00 →\n </button>\n </div>\n </div>\n\n {/* Preview */}\n <div className=\"space-y-1\">\n <label className=\"text-xs text-dc-text-secondary\">Preview</label>\n <div className=\"text-sm font-mono text-dc-text\">\n {preview}\n </div>\n </div>\n </div>\n )\n}\n\ninterface MultiAxisFormatControlsProps {\n displayConfig: {\n xAxisFormat?: AxisFormatConfig\n leftYAxisFormat?: AxisFormatConfig\n rightYAxisFormat?: AxisFormatConfig\n }\n onChange: (updates: {\n xAxisFormat?: AxisFormatConfig\n leftYAxisFormat?: AxisFormatConfig\n rightYAxisFormat?: AxisFormatConfig\n }) => void\n /** Which axes to show controls for */\n showAxes?: {\n xAxis?: boolean\n leftYAxis?: boolean\n rightYAxis?: boolean\n }\n}\n\n/**\n * Container component for multiple axis format controls\n */\nexport function MultiAxisFormatControls({\n displayConfig,\n onChange,\n showAxes = { leftYAxis: true, rightYAxis: true }\n}: MultiAxisFormatControlsProps) {\n return (\n <div className=\"space-y-4\">\n {showAxes.leftYAxis && (\n <AxisFormatControls\n axisLabel=\"Left Y-Axis\"\n value={displayConfig.leftYAxisFormat || {}}\n onChange={(config) =>\n onChange({\n ...displayConfig,\n leftYAxisFormat: Object.keys(config).length > 0 ? config : undefined\n })\n }\n />\n )}\n\n {showAxes.rightYAxis && (\n <AxisFormatControls\n axisLabel=\"Right Y-Axis\"\n value={displayConfig.rightYAxisFormat || {}}\n onChange={(config) =>\n onChange({\n ...displayConfig,\n rightYAxisFormat: Object.keys(config).length > 0 ? config : undefined\n })\n }\n />\n )}\n\n {showAxes.xAxis && (\n <AxisFormatControls\n axisLabel=\"X-Axis\"\n value={displayConfig.xAxisFormat || {}}\n onChange={(config) =>\n onChange({\n ...displayConfig,\n xAxisFormat: Object.keys(config).length > 0 ? config : undefined\n })\n }\n previewValue={2024} // Use a year-like number for X-axis preview\n />\n )}\n </div>\n )\n}\n\nexport default AxisFormatControls\n"],"names":["SectionHeading","children","className","getLocaleCurrencySymbol","locale","getCurrencyCodeForLocale","region","AxisFormatControls","value","onChange","axisLabel","previewValue","config","currencySymbol","useMemo","preview","formatAxisValue","handleChange","updates","unitButtons","jsxs","jsx","e","btn","current"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-bubblechart-CivK_yfh.js","sources":["../../../src/client/components/charts/BubbleChart.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { select, scaleLinear, scaleSqrt, scaleOrdinal, scaleQuantize, extent, max, axisBottom, axisLeft, type ScaleOrdinal, type ScaleQuantize } from 'd3'\nimport { CHART_COLORS, CHART_COLORS_GRADIENT, CHART_MARGINS } from '../../utils/chartConstants'\nimport { formatTimeValue, getFieldGranularity, parseNumericValue, isValidNumericValue, formatAxisValue } from '../../utils/chartUtils'\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { getTheme, watchThemeChanges, type Theme } from '../../theme'\nimport type { ChartProps } from '../../types'\n\ninterface BubbleData {\n x: number\n xLabel?: string // Formatted label for time dimensions\n y: number\n size: number\n color?: string | number\n label: string\n series?: string\n}\n\nexport default function BubbleChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const svgRef = useRef<SVGSVGElement | null>(null)\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [, setHoveredBubble] = useState<string | null>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n const [dimensionsReady, setDimensionsReady] = useState(false)\n const [currentTheme, setCurrentTheme] = useState<Theme>('light')\n const { getFieldLabel } = useCubeContext()\n\n // Watch for theme changes\n useEffect(() => {\n setCurrentTheme(getTheme())\n const unwatch = watchThemeChanges((theme) => {\n setCurrentTheme(theme)\n })\n return unwatch\n }, [])\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n minBubbleSize: displayConfig?.minBubbleSize ?? 5,\n maxBubbleSize: displayConfig?.maxBubbleSize ?? 50,\n bubbleOpacity: displayConfig?.bubbleOpacity ?? 0.7,\n xAxisFormat: displayConfig?.xAxisFormat,\n leftYAxisFormat: displayConfig?.leftYAxisFormat\n }\n\n // Enhanced dimension measurement with retry mechanism\n useLayoutEffect(() => {\n let retryCount = 0\n const maxRetries = 10\n let rafId: number\n let timeoutId: NodeJS.Timeout\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n \n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n setDimensionsReady(true)\n return true\n }\n }\n return false\n }\n \n // Immediate measurement\n const success = updateDimensions()\n \n if (!success && retryCount < maxRetries) {\n // Retry with requestAnimationFrame\n const retryWithRaf = () => {\n const rafSuccess = updateDimensions()\n \n if (!rafSuccess && retryCount < maxRetries) {\n retryCount++\n // Use setTimeout for additional retries with increasing delays\n timeoutId = setTimeout(() => {\n rafId = requestAnimationFrame(retryWithRaf)\n }, 50 * retryCount) // Increasing delay: 50ms, 100ms, 150ms, etc.\n }\n }\n \n rafId = requestAnimationFrame(retryWithRaf)\n }\n \n return () => {\n if (rafId) cancelAnimationFrame(rafId)\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [])\n\n // Enhanced ResizeObserver for dynamic resizing with immediate initialization\n useEffect(() => {\n let resizeObserver: ResizeObserver | null = null\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n if (!dimensionsReady) {\n setDimensionsReady(true)\n }\n }\n }\n }\n \n // Initialize ResizeObserver immediately\n if (containerRef.current) {\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect\n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n if (!dimensionsReady) {\n setDimensionsReady(true)\n }\n }\n }\n })\n \n resizeObserver.observe(containerRef.current)\n \n // Also try immediate measurement as fallback\n updateDimensions()\n }\n\n // Window resize as additional fallback\n window.addEventListener('resize', updateDimensions)\n \n return () => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n window.removeEventListener('resize', updateDimensions)\n }\n }, [dimensionsReady])\n\n useEffect(() => {\n if (!data || data.length === 0 || !svgRef.current || !dimensionsReady || dimensions.width === 0) {\n return\n }\n\n // Clear previous chart\n select(svgRef.current).selectAll('*').remove()\n\n\n // Validate chartConfig - only new format supported\n if (!chartConfig?.xAxis || !chartConfig?.yAxis || !chartConfig?.series) {\n return\n }\n\n const xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n const yAxisField = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis[0] : chartConfig.yAxis\n const seriesField = Array.isArray(chartConfig.series) ? chartConfig.series[0] : chartConfig.series\n const sizeFieldName = Array.isArray(chartConfig.sizeField) ? chartConfig.sizeField[0] : chartConfig.sizeField || yAxisField\n const colorFieldName = Array.isArray(chartConfig.colorField) ? chartConfig.colorField[0] : chartConfig.colorField\n\n\n if (!xAxisField || !yAxisField || !seriesField || !sizeFieldName) {\n return\n }\n\n // Transform data for bubble chart\n // Null handling: Filter out bubbles where x, y, or size are null\n const xGranularity = getFieldGranularity(queryObject, xAxisField)\n\n // Check if x-axis field is a time dimension\n const isTimeDimension = queryObject?.timeDimensions?.some(\n (td: { dimension: string }) => td.dimension === xAxisField\n ) || false\n\n const bubbleData: BubbleData[] = data\n .map(item => {\n const rawXValue = item[xAxisField]\n let xNum: number\n let xLabel: string\n\n if (isTimeDimension && rawXValue) {\n // For time dimensions, convert to timestamp for proper numeric positioning\n const dateStr = String(rawXValue)\n // Try to parse as date - handle ISO format and PostgreSQL format\n let date: Date\n if (dateStr.match(/^\\d{4}-\\d{2}-\\d{2}[T ]/)) {\n // Full timestamp format\n let isoStr = dateStr\n if (dateStr.includes(' ')) {\n isoStr = dateStr.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n date = new Date(isoStr)\n } else {\n date = new Date(dateStr)\n }\n\n xNum = isNaN(date.getTime()) ? parseFloat(dateStr) : date.getTime()\n xLabel = formatTimeValue(rawXValue, xGranularity)\n } else {\n // Non-time value - use as-is\n const formattedValue = formatTimeValue(rawXValue, xGranularity) || rawXValue\n xNum = typeof formattedValue === 'string' ? parseFloat(formattedValue) : formattedValue\n xLabel = String(formattedValue)\n }\n\n const yValue = parseNumericValue(item[yAxisField])\n const sizeValue = parseNumericValue(item[sizeFieldName])\n const seriesValue = item[seriesField]\n\n return {\n x: xNum,\n xLabel, // Store formatted label for tooltip display\n y: yValue as number, // Type assertion: filter below ensures this is never null\n size: sizeValue !== null ? Math.abs(sizeValue) : 0, // Ensure positive size\n color: colorFieldName ? item[colorFieldName] : seriesValue,\n series: seriesValue,\n label: `${seriesValue || 'Unknown'}`,\n isValid: isValidNumericValue(xNum) && yValue !== null && sizeValue !== null && sizeValue > 0\n }\n })\n .filter(d => d.isValid && d.size > 0) // Filter out bubbles with invalid coordinates or no size\n\n if (bubbleData.length === 0) return\n\n const margin = { \n ...CHART_MARGINS, \n left: CHART_MARGINS.left + 30, // Add extra 30px left margin for Y-axis label\n bottom: (safeDisplayConfig.showLegend && colorFieldName) ? 100 : 40 // Add extra space for legend\n }\n const width = dimensions.width - margin.left - margin.right\n const chartHeight = dimensions.height - margin.top - margin.bottom\n\n const svg = select(svgRef.current)\n .attr('width', dimensions.width)\n .attr('height', dimensions.height)\n\n const g = svg.append('g')\n .attr('transform', `translate(${margin.left},${margin.top})`)\n\n // Set up scales\n const xScale = scaleLinear()\n .domain(extent(bubbleData, d => d.x) as [number, number])\n .range([0, width])\n .nice()\n\n const yScale = scaleLinear()\n .domain(extent(bubbleData, d => d.y) as [number, number])\n .range([chartHeight, 0])\n .nice()\n\n const sizeScale = scaleSqrt()\n .domain([0, max(bubbleData, d => d.size) as number])\n .range([safeDisplayConfig.minBubbleSize, safeDisplayConfig.maxBubbleSize])\n\n // Set up color scale\n let colorScale: ScaleOrdinal<string, string> | ScaleQuantize<string>\n let isNumericColorField = false\n let uniqueColors: string[] = []\n \n if (colorFieldName && bubbleData.length > 0) {\n // Check if color field is numeric for color scaling (same logic as TreeMapChart)\n const colorValues = bubbleData.map(item => {\n const value = item.color\n return typeof value === 'string' ? parseFloat(value) : value\n }).filter((val): val is number => !isNaN(val as number))\n \n isNumericColorField = colorValues.length === bubbleData.length && colorValues.every(val => typeof val === 'number')\n \n if (isNumericColorField) {\n // Use D3 quantize scale for better color distribution with small ranges\n const minValue = Math.min(...colorValues)\n const maxValue = Math.max(...colorValues)\n \n // Create D3 quantize color scale - maps continuous data to discrete color bands\n colorScale = scaleQuantize<string>()\n .domain([minValue, maxValue])\n .range(colorPalette?.gradient || CHART_COLORS_GRADIENT)\n } else {\n // Categorical color field - use series colors\n uniqueColors = [...new Set(bubbleData.map(d => String(d.color)))]\n colorScale = scaleOrdinal<string>()\n .domain(uniqueColors)\n .range(colorPalette?.colors || CHART_COLORS)\n }\n } else {\n // Single color for all bubbles\n colorScale = scaleOrdinal<string>()\n .domain(['default'])\n .range([CHART_COLORS[0]])\n }\n\n // Get theme colors from CSS variables\n const getThemeColor = (varName: string, fallback: string) => {\n const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return value || fallback\n }\n\n const isDark = currentTheme !== 'light'\n const textColor = isDark\n ? getThemeColor('--dc-text-muted', '#cbd5e1') // Lighter text for dark mode\n : getThemeColor('--dc-text-secondary', '#374151') // Darker text for light mode\n const gridColor = isDark\n ? getThemeColor('--dc-border', '#475569') // Lighter grid for dark mode\n : '#9ca3af' // Much darker gray for light mode visibility\n\n // Add grid\n if (safeDisplayConfig.showGrid) {\n // X-axis grid\n const xGrid = g.append('g')\n .attr('class', 'grid')\n .attr('transform', `translate(0,${chartHeight})`)\n .call(axisBottom(xScale)\n .tickSize(-chartHeight)\n .tickFormat(() => '')\n )\n\n xGrid.selectAll('line')\n .style('stroke', gridColor)\n .style('stroke-dasharray', '3,3')\n .style('opacity', 0.3)\n\n xGrid.select('.domain')\n .style('stroke', 'none')\n\n // Y-axis grid\n const yGrid = g.append('g')\n .attr('class', 'grid')\n .call(axisLeft(yScale)\n .tickSize(-width)\n .tickFormat(() => '')\n )\n\n yGrid.selectAll('line')\n .style('stroke', gridColor)\n .style('stroke-dasharray', '3,3')\n .style('opacity', 0.3)\n\n yGrid.select('.domain')\n .style('stroke', 'none')\n }\n\n // Add X axis with proper time formatting if needed\n const xAxisGenerator = axisBottom(xScale)\n\n // If it's a time dimension, format the tick labels\n if (isTimeDimension) {\n xAxisGenerator.tickFormat((d) => {\n const date = new Date(d as number)\n if (isNaN(date.getTime())) return String(d)\n\n // Format based on granularity\n switch (xGranularity?.toLowerCase()) {\n case 'year':\n return String(date.getUTCFullYear())\n case 'quarter': {\n const q = Math.floor(date.getUTCMonth() / 3) + 1\n return `${date.getUTCFullYear()}-Q${q}`\n }\n case 'month':\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`\n case 'week':\n case 'day':\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}`\n case 'hour':\n return `${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')} ${String(date.getUTCHours()).padStart(2, '0')}:00`\n default:\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`\n }\n })\n } else if (safeDisplayConfig.xAxisFormat) {\n // Apply custom formatting for non-time X-axis\n xAxisGenerator.tickFormat((d) => formatAxisValue(d as number, safeDisplayConfig.xAxisFormat))\n }\n\n const xAxis = g.append('g')\n .attr('transform', `translate(0,${chartHeight})`)\n .call(xAxisGenerator)\n\n xAxis.selectAll('text')\n .style('fill', textColor)\n\n xAxis.selectAll('line, path')\n .style('stroke', gridColor)\n\n xAxis.append('text')\n .attr('x', width / 2)\n .attr('y', 35)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(safeDisplayConfig.xAxisFormat?.label || getFieldLabel(xAxisField))\n\n // Add Y axis with optional formatting\n const yAxisGenerator = axisLeft(yScale)\n if (safeDisplayConfig.leftYAxisFormat) {\n yAxisGenerator.tickFormat((d) => formatAxisValue(d as number, safeDisplayConfig.leftYAxisFormat))\n }\n const yAxis = g.append('g')\n .call(yAxisGenerator)\n\n yAxis.selectAll('text')\n .style('fill', textColor)\n\n yAxis.selectAll('line, path')\n .style('stroke', gridColor)\n\n yAxis.append('text')\n .attr('transform', 'rotate(-90)')\n .attr('y', -35)\n .attr('x', -chartHeight / 2)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(safeDisplayConfig.leftYAxisFormat?.label || getFieldLabel(yAxisField))\n\n // Create tooltip\n const tooltip = select('body').append('div')\n .attr('class', 'bubble-chart-tooltip')\n .style('position', 'absolute')\n .style('padding', '8px')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none')\n .style('opacity', 0)\n .style('z-index', 1000)\n\n // Add bubbles\n const bubbles = g.selectAll('.bubble')\n .data(bubbleData)\n .enter().append('circle')\n .attr('class', 'bubble')\n .attr('cx', d => xScale(d.x))\n .attr('cy', d => yScale(d.y))\n .attr('r', d => sizeScale(d.size))\n .style('fill', d => {\n if (colorFieldName && d.color !== undefined) {\n return isNumericColorField\n ? (colorScale as ScaleQuantize<string>)(d.color as number)\n : (colorScale as ScaleOrdinal<string, string>)(String(d.color))\n }\n return CHART_COLORS[0]\n })\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n .style('stroke', '#fff')\n .style('stroke-width', 1)\n .style('cursor', 'pointer')\n\n // Add hover effects\n if (safeDisplayConfig.showTooltip) {\n bubbles\n .on('mouseover', function(event, d) {\n select(this)\n .transition()\n .duration(200)\n .style('opacity', 1)\n .attr('r', sizeScale(d.size) * 1.1)\n\n const tooltipContent = [\n `<strong>${d.series || 'Unknown'}</strong>`,\n `${getFieldLabel(xAxisField)}: ${d.xLabel || (safeDisplayConfig.xAxisFormat ? formatAxisValue(d.x, safeDisplayConfig.xAxisFormat) : d.x)}`,\n `${getFieldLabel(yAxisField)}: ${safeDisplayConfig.leftYAxisFormat ? formatAxisValue(d.y, safeDisplayConfig.leftYAxisFormat) : d.y}`,\n `${getFieldLabel(sizeFieldName)}: ${safeDisplayConfig.leftYAxisFormat ? formatAxisValue(d.size, safeDisplayConfig.leftYAxisFormat) : d.size}`,\n colorFieldName && d.color ? `${getFieldLabel(colorFieldName)}: ${d.color}` : ''\n ].filter(Boolean).join('<br>')\n\n tooltip\n .html(tooltipContent)\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n .transition()\n .duration(200)\n .style('opacity', 1)\n\n setHoveredBubble(d.label)\n })\n .on('mousemove', function(event) {\n tooltip\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n })\n .on('mouseout', function(_event, d) {\n select(this)\n .transition()\n .duration(200)\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n .attr('r', sizeScale(d.size))\n\n tooltip\n .transition()\n .duration(200)\n .style('opacity', 0)\n\n setHoveredBubble(null)\n })\n }\n\n // Add legend if needed\n if (safeDisplayConfig.showLegend && colorFieldName) {\n if (isNumericColorField) {\n // Create gradient legend for numeric color field\n const legendWidth = 200\n const legendHeight = 20\n const minValue = Math.min(...bubbleData.map(d => d.color as number))\n const maxValue = Math.max(...bubbleData.map(d => d.color as number))\n \n const legend = g.append('g')\n .attr('class', 'color-legend')\n .attr('transform', `translate(${width / 2 - legendWidth / 2}, ${chartHeight + 60})`)\n\n // Create gradient definition\n const defs = svg.append('defs')\n const gradient = defs.append('linearGradient')\n .attr('id', 'color-scale-gradient')\n .attr('x1', '0%')\n .attr('y1', '0%')\n .attr('x2', '100%')\n .attr('y2', '0%')\n\n // Add color stops for the gradient\n const gradientColors = colorPalette?.gradient || CHART_COLORS_GRADIENT\n gradientColors.forEach((color, i) => {\n gradient.append('stop')\n .attr('offset', `${(i / (gradientColors.length - 1)) * 100}%`)\n .attr('stop-color', color)\n })\n\n // Add the gradient rectangle\n legend.append('rect')\n .attr('width', legendWidth)\n .attr('height', legendHeight)\n .style('fill', 'url(#color-scale-gradient)')\n .style('stroke', '#ccc')\n .style('stroke-width', 1)\n\n // Add min value label\n legend.append('text')\n .attr('x', 0)\n .attr('y', legendHeight + 15)\n .attr('text-anchor', 'start')\n .style('font-size', '11px')\n .style('fill', textColor)\n .text(safeDisplayConfig.leftYAxisFormat ? formatAxisValue(minValue, safeDisplayConfig.leftYAxisFormat) : minValue.toFixed(2))\n\n // Add max value label\n legend.append('text')\n .attr('x', legendWidth)\n .attr('y', legendHeight + 15)\n .attr('text-anchor', 'end')\n .style('font-size', '11px')\n .style('fill', textColor)\n .text(safeDisplayConfig.leftYAxisFormat ? formatAxisValue(maxValue, safeDisplayConfig.leftYAxisFormat) : maxValue.toFixed(2))\n\n // Add field name label\n legend.append('text')\n .attr('x', legendWidth / 2)\n .attr('y', -5)\n .attr('text-anchor', 'middle')\n .style('font-size', '12px')\n .style('font-weight', 'bold')\n .style('fill', textColor)\n .text(getFieldLabel(colorFieldName))\n\n } else {\n // Original categorical legend\n const legendItems = uniqueColors\n\n if (legendItems.length > 0) {\n const legend = g.append('g')\n .attr('class', 'legend')\n .attr('transform', `translate(${width / 2 - (legendItems.length * 80) / 2}, ${chartHeight + 60})`)\n\n const legendItem = legend.selectAll('.legend-item')\n .data(legendItems)\n .enter().append('g')\n .attr('class', 'legend-item')\n .attr('transform', (_d, i) => `translate(${i * 80}, 0)`)\n .style('cursor', 'pointer')\n\n legendItem.append('circle')\n .attr('cx', 5)\n .attr('cy', 5)\n .attr('r', 5)\n .style('fill', d => (colorScale as ScaleOrdinal<string, string>)(d as string))\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n\n legendItem.append('text')\n .attr('x', 15)\n .attr('y', 5)\n .attr('dy', '.35em')\n .style('font-size', '11px')\n .style('fill', textColor)\n .text(d => String(d))\n\n // Legend hover effects\n legendItem\n .on('mouseover', function(_event, legendKey) {\n // Highlight matching bubbles\n bubbles\n .transition()\n .duration(200)\n .style('opacity', d => {\n const matches = colorFieldName && String(d.color) === legendKey\n return matches ? 1 : 0.2\n })\n })\n .on('mouseout', function() {\n // Reset all bubbles\n bubbles\n .transition()\n .duration(200)\n .style('opacity', safeDisplayConfig.bubbleOpacity)\n })\n }\n }\n }\n\n // Cleanup function\n return () => {\n tooltip.remove()\n }\n }, [data, chartConfig, displayConfig, queryObject, dimensions, dimensionsReady, safeDisplayConfig.showLegend, safeDisplayConfig.showGrid, safeDisplayConfig.showTooltip, safeDisplayConfig.minBubbleSize, safeDisplayConfig.maxBubbleSize, safeDisplayConfig.bubbleOpacity, colorPalette, currentTheme])\n\n if (!data || data.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data points to display in bubble chart</div>\n </div>\n </div>\n )\n }\n\n // Validate that we have required fields\n const hasValidConfig = chartConfig?.xAxis && chartConfig?.yAxis && chartConfig?.series\n if (!hasValidConfig) {\n return (\n <div className=\"flex items-center justify-center w-full text-yellow-600\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Required</div>\n <div className=\"text-xs\">Bubble chart requires xAxis, yAxis, series, and sizeField dimensions</div>\n <div className=\"text-xs mt-1\">Optional: colorField for bubble coloring</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full flex-1 flex flex-col relative\" style={{ height, minHeight: '250px', overflow: 'hidden' }}>\n <div ref={containerRef} className=\"w-full h-full relative\">\n <svg ref={svgRef} className=\"w-full h-full\" />\n {!dimensionsReady && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"text-dc-text-muted text-sm\">Measuring chart dimensions...</div>\n </div>\n )}\n </div>\n </div>\n )\n}"],"names":["BubbleChart","data","chartConfig","displayConfig","queryObject","height","colorPalette","svgRef","useRef","containerRef","setHoveredBubble","useState","dimensions","setDimensions","dimensionsReady","setDimensionsReady","currentTheme","setCurrentTheme","getFieldLabel","useCubeContext","useEffect","getTheme","watchThemeChanges","theme","safeDisplayConfig","useLayoutEffect","retryCount","maxRetries","rafId","timeoutId","updateDimensions","width","retryWithRaf","resizeObserver","entries","entry","select","xAxisField","yAxisField","seriesField","sizeFieldName","colorFieldName","xGranularity","getFieldGranularity","isTimeDimension","td","bubbleData","item","rawXValue","xNum","xLabel","dateStr","date","isoStr","formatTimeValue","formattedValue","yValue","parseNumericValue","sizeValue","seriesValue","isValidNumericValue","d","margin","CHART_MARGINS","chartHeight","svg","g","xScale","scaleLinear","extent","yScale","sizeScale","scaleSqrt","max","colorScale","isNumericColorField","uniqueColors","colorValues","value","val","minValue","maxValue","scaleQuantize","CHART_COLORS_GRADIENT","scaleOrdinal","CHART_COLORS","getThemeColor","varName","fallback","isDark","textColor","gridColor","xGrid","axisBottom","yGrid","axisLeft","xAxisGenerator","q","formatAxisValue","xAxis","yAxisGenerator","yAxis","tooltip","bubbles","event","tooltipContent","_event","legend","gradient","gradientColors","color","i","legendItems","legendItem","_d","legendKey","jsx","jsxs"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-kpidelta-D-FR2o4V.js","sources":["../../../src/client/utils/periodUtils.ts","../../../src/client/components/charts/KpiDelta.tsx"],"sourcesContent":["/**\n * Utility functions for detecting incomplete time periods in KPI charts\n */\n\n/**\n * Get the end date of a period based on granularity\n * @param date - The date within the period\n * @param granularity - The time granularity (day, week, month, quarter, year)\n * @returns The end date of the period (end of day)\n */\nexport function getPeriodEndDate(date: Date, granularity: string): Date {\n const endDate = new Date(date)\n\n switch (granularity.toLowerCase()) {\n case 'day':\n // End of the same day\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'week':\n // End of the week (Saturday, assuming week starts Sunday)\n const dayOfWeek = endDate.getDay()\n const daysUntilSaturday = 6 - dayOfWeek\n endDate.setDate(endDate.getDate() + daysUntilSaturday)\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'month':\n // Last day of the month\n endDate.setMonth(endDate.getMonth() + 1, 0) // Set to day 0 of next month = last day of current month\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'quarter':\n // Last day of the quarter\n const currentMonth = endDate.getMonth()\n const quarterEndMonth = Math.floor(currentMonth / 3) * 3 + 2 // 0->2, 3->5, 6->8, 9->11\n endDate.setMonth(quarterEndMonth + 1, 0) // Last day of quarter end month\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'year':\n // December 31st\n endDate.setMonth(11, 31) // December 31\n endDate.setHours(23, 59, 59, 999)\n break\n\n default:\n // Unknown granularity - treat as complete\n endDate.setHours(23, 59, 59, 999)\n }\n\n return endDate\n}\n\n/**\n * Check if the last period in the data is complete based on granularity\n * @param lastDataPoint - The last data point in the sorted dataset\n * @param timeDimensionField - The field name containing the time value\n * @param granularity - The time granularity\n * @returns true if the period is complete, false if it's incomplete\n */\nexport function isLastPeriodComplete(\n lastDataPoint: any,\n timeDimensionField: string,\n granularity: string\n): boolean {\n if (!lastDataPoint || !timeDimensionField || !granularity) {\n return true // Assume complete if we can't determine\n }\n\n const timeValue = lastDataPoint[timeDimensionField]\n if (!timeValue) {\n return true // Assume complete if no time value\n }\n\n // Parse the time value\n const date = new Date(timeValue)\n if (isNaN(date.getTime())) {\n return true // Assume complete if invalid date\n }\n\n // Get the end of this period\n const periodEnd = getPeriodEndDate(date, granularity)\n\n // Compare with current time\n const now = new Date()\n\n // If the period end is in the future, the period is incomplete\n return periodEnd <= now\n}\n\n/**\n * Extract granularity from a query object\n * @param queryObject - The CubeQuery object\n * @param dimensionField - Optional specific dimension field to match\n * @returns The granularity string or null if not found\n */\nexport function getQueryGranularity(\n queryObject: any,\n dimensionField?: string\n): string | null {\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return null\n }\n\n // If a specific dimension field is provided, try to find its granularity\n if (dimensionField) {\n const matchingDim = queryObject.timeDimensions.find((td: any) =>\n td.dimension === dimensionField ||\n td.dimension?.includes(dimensionField) ||\n dimensionField?.includes(td.dimension)\n )\n if (matchingDim?.granularity) {\n return matchingDim.granularity\n }\n }\n\n // Fallback to first time dimension's granularity\n const firstTimeDim = queryObject.timeDimensions[0]\n return firstTimeDim?.granularity || null\n}\n\n/**\n * Filter data to exclude incomplete or last period\n * @param data - The data array sorted by time\n * @param timeDimensionField - The field containing time values\n * @param queryObject - The query object containing timeDimensions\n * @param useLastCompletePeriod - Whether to check for incomplete periods\n * @param skipLastPeriod - Whether to always skip the last period (overrides useLastCompletePeriod)\n * @returns Object with filtered data and whether filtering was applied\n */\nexport function filterIncompletePeriod(\n data: any[],\n timeDimensionField: string | undefined,\n queryObject: any,\n useLastCompletePeriod: boolean,\n skipLastPeriod: boolean = false\n): { filteredData: any[]; excludedIncompletePeriod: boolean; skippedLastPeriod: boolean; granularity: string | null } {\n // Default return - no filtering\n const noFilter = {\n filteredData: data,\n excludedIncompletePeriod: false,\n skippedLastPeriod: false,\n granularity: null\n }\n\n // Need at least 2 data points to filter\n if (data.length < 2) {\n return noFilter\n }\n\n const granularity = getQueryGranularity(queryObject, timeDimensionField)\n\n // If skipLastPeriod is enabled, always skip the last period\n if (skipLastPeriod) {\n return {\n filteredData: data.slice(0, -1),\n excludedIncompletePeriod: false,\n skippedLastPeriod: true,\n granularity\n }\n }\n\n // Skip incomplete period check if feature is disabled\n if (!useLastCompletePeriod) {\n return { ...noFilter, granularity }\n }\n\n // Skip if no time dimension field\n if (!timeDimensionField) {\n return { ...noFilter, granularity }\n }\n\n // Skip if no time dimensions in query\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return { ...noFilter, granularity }\n }\n\n if (!granularity) {\n return noFilter\n }\n\n // Check if last period is incomplete\n const lastRow = data[data.length - 1]\n if (!isLastPeriodComplete(lastRow, timeDimensionField, granularity)) {\n return {\n filteredData: data.slice(0, -1),\n excludedIncompletePeriod: true,\n skippedLastPeriod: false,\n granularity\n }\n }\n\n return { ...noFilter, granularity }\n}\n","import { useState, useRef, useEffect } from \"react\";\nimport { Icon } from \"@iconify/react\";\nimport infoCircleIcon from \"@iconify-icons/tabler/info-circle\";\nimport { useCubeContext } from \"../../providers/CubeProvider\";\nimport { filterIncompletePeriod } from \"../../utils/periodUtils\";\nimport type { ChartProps } from \"../../types\";\n\ninterface VarianceHistogramProps {\n values: number[];\n lastValue: number;\n positiveColor: string;\n negativeColor: string;\n formatValue: (value: number) => string;\n width: number;\n height: number;\n}\n\nfunction VarianceHistogram({\n values,\n lastValue,\n positiveColor,\n negativeColor,\n formatValue,\n width,\n height,\n}: VarianceHistogramProps) {\n // Limit to most recent N values to fit in the histogram\n // Calculate max bars based on width (minimum 8px per bar including gap)\n const maxBars = Math.max(10, Math.floor(width / 10));\n const limitedValues =\n values.length > maxBars\n ? values.slice(-maxBars) // Take the most recent values\n : values;\n\n // Calculate variance (difference) from current/last value for each point\n const variances = limitedValues.map((value) => value - lastValue);\n\n // Find min/max variance for scaling (include 0 as baseline)\n const minVariance = Math.min(...variances, 0);\n const maxVariance = Math.max(...variances, 0);\n const range = Math.max(Math.abs(minVariance), Math.abs(maxVariance));\n\n if (range === 0 || variances.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center bg-gray-50 rounded-sm border\"\n style={{ width: `${width}px`, height: `${height}px` }}\n >\n <span className=\"text-xs text-gray-500\">No variance data</span>\n </div>\n );\n }\n\n // Calculate bar dimensions\n const barGap = 2;\n const availableWidth = width - (limitedValues.length - 1) * barGap;\n const barWidth = Math.max(4, availableWidth / limitedValues.length);\n\n // Calculate where zero line should be positioned (as percentage from top)\n // If maxVariance = 67 and minVariance = -24, total range = 91\n // Zero should be at 67/91 = 73.6% from top\n const totalRange = maxVariance - minVariance;\n const zeroLinePercent =\n totalRange > 0 ? (maxVariance / totalRange) * 100 : 50;\n\n return (\n <div className=\"flex items-center space-x-2\">\n {/* Histogram bars */}\n <div\n className=\"relative\"\n style={{\n width: `${width}px`,\n height: `${height}px`,\n }}\n >\n {/* Zero line (represents current value) */}\n <div\n className=\"absolute left-0 right-0\"\n style={{\n height: \"1px\",\n top: `${zeroLinePercent}%`,\n backgroundColor: \"var(--dc-border)\",\n zIndex: 1,\n }}\n />\n\n {/* Variance bars - oldest to newest (left to right) */}\n {variances.map((variance, index) => {\n // Calculate bar height as proportion of total range\n const normalizedHeight = Math.abs(variance) / totalRange;\n const barHeight = Math.max(2, normalizedHeight * (height - 4));\n const isPositive = variance >= 0;\n const isLastValue = index === limitedValues.length - 1;\n const color = isPositive ? positiveColor : negativeColor;\n const xPosition = index * (barWidth + barGap);\n\n return (\n <div\n key={index}\n className=\"absolute rounded-xs\"\n style={{\n left: `${xPosition}px`,\n width: `${barWidth}px`,\n height: `${barHeight}px`,\n backgroundColor: color,\n opacity: isLastValue ? 1 : 0.6,\n // Position bar relative to zero line\n ...(isPositive\n ? { bottom: `${100 - zeroLinePercent}%` }\n : { top: `${zeroLinePercent}%` }),\n zIndex: 2,\n }}\n title={`${formatValue(limitedValues[index])}: ${variance >= 0 ? \"+\" : \"\"}${formatValue(variance)} vs current`}\n />\n );\n })}\n </div>\n\n {/* Variance labels on the right - show actual value difference */}\n <div\n className=\"flex flex-col justify-between text-xs text-dc-text-muted\"\n style={{ height: `${height}px` }}\n >\n <span>+{formatValue(maxVariance)}</span>\n <span>\n {minVariance < 0 ? \"\" : \"\"}\n {formatValue(minVariance)}\n </span>\n </div>\n </div>\n );\n}\n\nexport default function KpiDelta({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n}: ChartProps) {\n const [fontSize, setFontSize] = useState(32);\n const [textWidth, setTextWidth] = useState(250);\n const containerRef = useRef<HTMLDivElement>(null);\n const valueRef = useRef<HTMLDivElement>(null);\n const { getFieldLabel } = useCubeContext();\n\n // Calculate font size and text width based on container dimensions\n useEffect(() => {\n const updateDimensions = () => {\n if (containerRef.current) {\n const container = containerRef.current;\n const rect = container.getBoundingClientRect();\n const containerWidth = rect.width;\n const containerHeight = rect.height;\n\n if (containerWidth > 0 && containerHeight > 0) {\n const widthBasedSize = containerWidth / 4;\n const heightBasedSize = containerHeight / 4;\n const baseFontSize = Math.min(widthBasedSize, heightBasedSize);\n const clampedFontSize = Math.max(28, Math.min(baseFontSize, 140));\n setFontSize(clampedFontSize);\n\n setTimeout(() => {\n if (valueRef.current) {\n const textRect = valueRef.current.getBoundingClientRect();\n const measuredWidth = textRect.width;\n // Scale histogram width with container, accounting for labels on the right (~60px)\n const maxHistogramWidth = containerWidth - 100; // Leave room for padding and labels\n const effectiveWidth = Math.max(\n measuredWidth,\n Math.min(maxHistogramWidth, containerWidth * 0.7),\n );\n setTextWidth(Math.max(100, effectiveWidth)); // Minimum 100px\n }\n }, 10);\n }\n }\n };\n\n const timer = setTimeout(updateDimensions, 50);\n\n const resizeObserver = new ResizeObserver(() => {\n setTimeout(updateDimensions, 10);\n });\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current);\n }\n\n return () => {\n clearTimeout(timer);\n resizeObserver.disconnect();\n };\n }, [data, chartConfig]);\n\n if (!data || data.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">\n No data points to display\n </div>\n </div>\n </div>\n );\n }\n\n // Extract value and dimension fields from chart config\n let valueFields: string[] = [];\n let dimensionFields: string[] = [];\n\n if (chartConfig?.yAxis) {\n valueFields = Array.isArray(chartConfig.yAxis)\n ? chartConfig.yAxis\n : [chartConfig.yAxis];\n }\n\n if (chartConfig?.xAxis) {\n dimensionFields = Array.isArray(chartConfig.xAxis)\n ? chartConfig.xAxis\n : [chartConfig.xAxis];\n }\n\n if (valueFields.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n backgroundColor: \"var(--dc-danger-bg)\",\n color: \"var(--dc-danger)\",\n borderColor: \"var(--dc-danger-border)\",\n }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">No measure field configured</div>\n </div>\n </div>\n );\n }\n\n const valueField = valueFields[0];\n const dimensionField = dimensionFields[0]; // Optional\n\n // Sort data by dimension if available (for time series)\n let sortedData = [...data];\n if (dimensionField) {\n sortedData = sortedData.sort((a, b) => {\n const aVal = a[dimensionField];\n const bVal = b[dimensionField];\n if (aVal < bVal) return -1;\n if (aVal > bVal) return 1;\n return 0;\n });\n }\n\n // Filter out incomplete or last period if enabled\n const { useLastCompletePeriod = true, skipLastPeriod = false } =\n displayConfig;\n const {\n filteredData,\n excludedIncompletePeriod,\n skippedLastPeriod,\n granularity,\n } = filterIncompletePeriod(\n sortedData,\n dimensionField,\n queryObject,\n useLastCompletePeriod,\n skipLastPeriod,\n );\n\n // Use filtered data for calculations\n const dataToUse = filteredData;\n\n // Extract values from filtered data\n const values = dataToUse\n .map((row) => row[valueField])\n .filter((val) => val !== null && val !== undefined && !isNaN(Number(val)))\n .map((val) => Number(val));\n\n if (values.length < 2) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n backgroundColor: \"var(--dc-warning-bg)\",\n color: \"var(--dc-warning)\",\n borderColor: \"var(--dc-warning-border)\",\n }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Insufficient Data</div>\n <div className=\"text-xs\">\n Delta calculation requires at least 2 data points\n </div>\n <div className=\"text-xs\">Current data points: {values.length}</div>\n </div>\n </div>\n );\n }\n\n // Calculate delta between last and second-last values\n const lastValue = values[values.length - 1];\n const secondLastValue = values[values.length - 2];\n const absoluteChange = lastValue - secondLastValue;\n const percentageChange =\n secondLastValue !== 0\n ? (absoluteChange / Math.abs(secondLastValue)) * 100\n : 0;\n\n const isPositiveChange = absoluteChange >= 0;\n\n // Format number with appropriate units and decimals\n const formatNumber = (value: number | null | undefined): string => {\n // If custom formatValue is provided, use it exclusively\n if (displayConfig.formatValue) {\n return displayConfig.formatValue(value);\n }\n\n // Null handling: Show placeholder for missing data\n if (value === null || value === undefined) {\n return \"—\";\n }\n\n const decimals = displayConfig.decimals ?? 0;\n const prefix = displayConfig.prefix ?? \"\";\n\n let formattedValue: string;\n\n if (Math.abs(value) >= 1e9) {\n formattedValue = (value / 1e9).toFixed(decimals) + \"B\";\n } else if (Math.abs(value) >= 1e6) {\n formattedValue = (value / 1e6).toFixed(decimals) + \"M\";\n } else if (Math.abs(value) >= 1e3) {\n formattedValue = (value / 1e3).toFixed(decimals) + \"K\";\n } else {\n formattedValue = value.toFixed(decimals);\n }\n\n return prefix + formattedValue;\n };\n\n // Get colors from palette\n const getPositiveColor = (): string => {\n if (\n displayConfig.positiveColorIndex !== undefined &&\n colorPalette?.colors\n ) {\n const colorIndex = displayConfig.positiveColorIndex;\n if (colorIndex >= 0 && colorIndex < colorPalette.colors.length) {\n return colorPalette.colors[colorIndex];\n }\n }\n return \"#10b981\"; // Default green\n };\n\n const getNegativeColor = (): string => {\n if (\n displayConfig.negativeColorIndex !== undefined &&\n colorPalette?.colors\n ) {\n const colorIndex = displayConfig.negativeColorIndex;\n if (colorIndex >= 0 && colorIndex < colorPalette.colors.length) {\n return colorPalette.colors[colorIndex];\n }\n }\n return \"#ef4444\"; // Default red\n };\n\n const positiveColor = getPositiveColor();\n const negativeColor = getNegativeColor();\n const currentColor = isPositiveChange ? positiveColor : negativeColor;\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col items-center justify-center w-full h-full p-4\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n }}\n >\n {/* Field Label */}\n <div\n className=\"text-dc-text-secondary font-bold text-center mb-2 flex items-center justify-center gap-1\"\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.2\",\n }}\n >\n <span>\n {(() => {\n const label = getFieldLabel(valueField);\n return label && label.length > 1 ? label : valueField;\n })()}\n </span>\n {(excludedIncompletePeriod || skippedLastPeriod) && (\n <span\n title={\n skippedLastPeriod\n ? `Excludes last ${granularity || \"period\"}`\n : `Excludes current incomplete ${granularity}`\n }\n className=\"cursor-help\"\n >\n <Icon\n icon={infoCircleIcon}\n className=\"w-4 h-4 text-dc-text-muted opacity-70\"\n />\n </span>\n )}\n </div>\n\n {/* Main KPI Value and Delta */}\n <div className=\"flex items-center justify-center space-x-4 mb-2\">\n {/* Main KPI Value */}\n <div\n ref={valueRef}\n className=\"font-bold leading-none\"\n style={{\n fontSize: `${fontSize}px`,\n color: \"var(--dc-text)\", // Keep main value neutral\n }}\n >\n {formatNumber(lastValue)}\n </div>\n\n {/* Delta Information */}\n <div className=\"flex items-center space-x-1\">\n {/* Arrow */}\n <div\n className=\"font-bold\"\n style={{\n color: currentColor,\n fontSize: `${fontSize * 0.35}px`,\n }}\n >\n {isPositiveChange ? \"▲\" : \"▼\"}\n </div>\n\n {/* Delta Values */}\n <div className=\"text-left\">\n <div\n className=\"font-bold leading-tight\"\n style={{\n fontSize: `${fontSize * 0.35}px`,\n color: currentColor,\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {formatNumber(absoluteChange)}\n </div>\n <div\n className=\"font-semibold leading-tight\"\n style={{\n fontSize: `${fontSize * 0.28}px`,\n color: currentColor,\n opacity: 0.8,\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {percentageChange.toFixed(1)}%\n </div>\n </div>\n </div>\n </div>\n\n {/* Unit/Suffix (hidden when formatValue is provided) */}\n {displayConfig.suffix && !displayConfig.formatValue && (\n <div\n className=\"text-dc-text-muted text-center mb-3\"\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.2\",\n opacity: 0.8,\n }}\n >\n {displayConfig.suffix}\n </div>\n )}\n\n {/* Variance Histogram */}\n {displayConfig.showHistogram !== false && values.length > 2 && (\n <div className=\"mt-2 w-full flex justify-center overflow-hidden\">\n <VarianceHistogram\n values={values}\n lastValue={lastValue}\n positiveColor={positiveColor}\n negativeColor={negativeColor}\n formatValue={formatNumber}\n width={textWidth}\n height={64}\n />\n </div>\n )}\n </div>\n );\n}\n"],"names":["getPeriodEndDate","date","granularity","endDate","daysUntilSaturday","currentMonth","quarterEndMonth","isLastPeriodComplete","lastDataPoint","timeDimensionField","timeValue","getQueryGranularity","queryObject","dimensionField","matchingDim","td","filterIncompletePeriod","data","useLastCompletePeriod","skipLastPeriod","noFilter","lastRow","VarianceHistogram","values","lastValue","positiveColor","negativeColor","formatValue","width","height","maxBars","limitedValues","variances","value","minVariance","maxVariance","jsx","barGap","availableWidth","barWidth","totalRange","zeroLinePercent","jsxs","variance","index","normalizedHeight","barHeight","isPositive","isLastValue","color","xPosition","KpiDelta","chartConfig","displayConfig","colorPalette","fontSize","setFontSize","useState","textWidth","setTextWidth","containerRef","useRef","valueRef","getFieldLabel","useCubeContext","useEffect","updateDimensions","rect","containerWidth","containerHeight","widthBasedSize","heightBasedSize","baseFontSize","clampedFontSize","measuredWidth","maxHistogramWidth","effectiveWidth","timer","resizeObserver","valueFields","dimensionFields","valueField","sortedData","a","b","aVal","bVal","filteredData","excludedIncompletePeriod","skippedLastPeriod","row","val","secondLastValue","absoluteChange","percentageChange","isPositiveChange","formatNumber","decimals","prefix","formattedValue","getPositiveColor","colorIndex","getNegativeColor","currentColor","label","Icon","infoCircleIcon"],"mappings":"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"}
@@ -1,254 +0,0 @@
1
- import { jsx as c, jsxs as m } from "react/jsx-runtime";
2
- function H({
3
- displayConfig: p = {},
4
- height: x = "100%",
5
- colorPalette: g
6
- }) {
7
- const k = p.content || "", w = p.accentColorIndex ?? 0, N = p.fontSize || "medium", u = p.alignment || "left", h = g?.colors && w < g.colors.length ? g.colors[w] : "#8884d8", y = {
8
- small: "text-sm",
9
- medium: "text-lg",
10
- large: "text-xl"
11
- }, v = {
12
- left: "text-left",
13
- center: "text-center",
14
- right: "text-right"
15
- }, M = (n) => {
16
- const e = n.split(`
17
- `), l = [];
18
- let t = null;
19
- for (let o = 0; o < e.length; o++) {
20
- const i = e[o].trim();
21
- if (!i) {
22
- t && (l.push(t), t = null), l.push({ type: "break" });
23
- continue;
24
- }
25
- const a = i.match(/^(#{1,3})\s+(.*)$/);
26
- if (a) {
27
- t && (l.push(t), t = null), l.push({
28
- type: "header",
29
- level: a[1].length,
30
- content: a[2]
31
- });
32
- continue;
33
- }
34
- const s = i.match(/^[-*+]\s+(.*)$/);
35
- if (s) {
36
- (!t || t.ordered) && (t && l.push(t), t = { type: "list", ordered: !1, children: [] }), t.children.push({
37
- type: "listItem",
38
- children: $(s[1]),
39
- parentOrdered: !1
40
- });
41
- continue;
42
- }
43
- const r = i.match(/^\d+\.\s+(.*)$/);
44
- if (r) {
45
- (!t || !t.ordered) && (t && l.push(t), t = { type: "list", ordered: !0, children: [] }), t.children.push({
46
- type: "listItem",
47
- children: $(r[1]),
48
- parentOrdered: !0
49
- });
50
- continue;
51
- }
52
- t && (l.push(t), t = null), l.push({
53
- type: "paragraph",
54
- children: $(i)
55
- });
56
- }
57
- return t && l.push(t), l;
58
- }, $ = (n) => {
59
- const e = [];
60
- let l = n;
61
- for (; l; ) {
62
- const t = l.match(/^(.*?)\[([^\]]+)\]\(([^)]+)\)(.*)$/);
63
- if (t) {
64
- const [, o, i, a, s] = t;
65
- o && e.push(...C(o)), e.push({
66
- type: "link",
67
- content: i,
68
- url: a
69
- }), l = s;
70
- continue;
71
- }
72
- e.push(...C(l));
73
- break;
74
- }
75
- return e;
76
- }, C = (n) => {
77
- const e = [];
78
- let l = n;
79
- for (; l; ) {
80
- const t = l.match(/^(.*?)\*\*([^*]+)\*\*(.*)$/);
81
- if (t) {
82
- const [, i, a, s] = t;
83
- i && e.push({ type: "text", content: i }), e.push({ type: "bold", content: a }), l = s;
84
- continue;
85
- }
86
- const o = l.match(/^(.*?)\*([^*]+)\*(.*)$/);
87
- if (o) {
88
- const [, i, a, s] = o;
89
- i && e.push({ type: "text", content: i }), e.push({ type: "italic", content: a }), l = s;
90
- continue;
91
- }
92
- e.push({ type: "text", content: l });
93
- break;
94
- }
95
- return e;
96
- }, d = (n, e, l) => {
97
- switch (n.type) {
98
- case "text":
99
- return /* @__PURE__ */ c("span", { className: "text-dc-text", children: n.content }, e);
100
- case "bold":
101
- return /* @__PURE__ */ c("strong", { className: "font-bold text-dc-text", children: n.content }, e);
102
- case "italic":
103
- return /* @__PURE__ */ c("em", { className: "italic text-dc-text", children: n.content }, e);
104
- case "link":
105
- return /* @__PURE__ */ c(
106
- "a",
107
- {
108
- href: n.url,
109
- target: "_blank",
110
- rel: "nofollow noopener noreferrer",
111
- className: "hover:underline transition-colors",
112
- style: { color: h },
113
- children: n.content
114
- },
115
- e
116
- );
117
- case "header":
118
- const t = (s, r) => {
119
- const f = "font-bold", I = {
120
- 1: "mb-4",
121
- 2: "mb-3",
122
- 3: "mb-2"
123
- };
124
- let b = "";
125
- return r === "small" ? b = { 1: "text-lg", 2: "text-base", 3: "text-sm" }[s] || "text-sm" : r === "large" ? b = { 1: "text-5xl", 2: "text-4xl", 3: "text-3xl" }[s] || "text-3xl" : b = { 1: "text-3xl", 2: "text-2xl", 3: "text-xl" }[s] || "text-xl", `${f} ${b} ${I[s]}`;
126
- }, o = `h${n.level}`;
127
- return /* @__PURE__ */ c(
128
- o,
129
- {
130
- className: t(n.level, N),
131
- style: { color: h },
132
- children: n.content
133
- },
134
- e
135
- );
136
- case "paragraph":
137
- return /* @__PURE__ */ c("p", { className: "mb-3 leading-relaxed", children: n.children?.map((s, r) => d(s, r)) }, e);
138
- case "list":
139
- const i = n.ordered ? "ol" : "ul";
140
- let a = "mb-3";
141
- return u === "center" ? a += " list-none flex flex-col items-center" : u === "right" ? a += " list-none ml-auto max-w-max" : a += " list-none ml-6", /* @__PURE__ */ c(i, { className: a, children: n.children?.map((s, r) => d(s, r, n.ordered ? r + 1 : void 0)) }, e);
142
- case "listItem":
143
- if (n.children) {
144
- if (n.parentOrdered && l !== void 0) {
145
- const s = y[N];
146
- return u === "center" ? /* @__PURE__ */ m("li", { className: "mb-1 flex items-center justify-center", children: [
147
- /* @__PURE__ */ m(
148
- "span",
149
- {
150
- className: `inline-block mr-2 shrink-0 ${s} font-medium`,
151
- style: { color: h },
152
- children: [
153
- l,
154
- "."
155
- ]
156
- }
157
- ),
158
- /* @__PURE__ */ c("span", { className: "text-center", children: n.children.map((r, f) => d(r, f)) })
159
- ] }, e) : u === "right" ? /* @__PURE__ */ m("li", { className: "mb-1 flex items-start justify-end", children: [
160
- /* @__PURE__ */ c("span", { className: "text-right", children: n.children.map((r, f) => d(r, f)) }),
161
- /* @__PURE__ */ m(
162
- "span",
163
- {
164
- className: `inline-block ml-2 shrink-0 ${s} font-medium`,
165
- style: { color: h },
166
- children: [
167
- l,
168
- "."
169
- ]
170
- }
171
- )
172
- ] }, e) : /* @__PURE__ */ m("li", { className: "mb-1 flex items-start", children: [
173
- /* @__PURE__ */ m(
174
- "span",
175
- {
176
- className: `inline-block mr-3 shrink-0 ${s} font-medium`,
177
- style: { color: h },
178
- children: [
179
- l,
180
- "."
181
- ]
182
- }
183
- ),
184
- /* @__PURE__ */ c("span", { className: "flex-1", children: n.children.map((r, f) => d(r, f)) })
185
- ] }, e);
186
- }
187
- return u === "center" ? /* @__PURE__ */ m("li", { className: "mb-1 flex items-center justify-center", children: [
188
- /* @__PURE__ */ c(
189
- "span",
190
- {
191
- className: "inline-block w-2 h-2 rounded-full mr-2 shrink-0",
192
- style: { backgroundColor: h }
193
- }
194
- ),
195
- /* @__PURE__ */ c("span", { className: "text-center", children: n.children.map((s, r) => d(s, r)) })
196
- ] }, e) : u === "right" ? /* @__PURE__ */ m("li", { className: "mb-1 flex items-start justify-end", children: [
197
- /* @__PURE__ */ c("span", { className: "text-right", children: n.children.map((s, r) => d(s, r)) }),
198
- /* @__PURE__ */ c(
199
- "span",
200
- {
201
- className: "inline-block w-2 h-2 rounded-full ml-2 mt-2 shrink-0",
202
- style: { backgroundColor: h }
203
- }
204
- )
205
- ] }, e) : /* @__PURE__ */ m("li", { className: "mb-1 flex items-start", children: [
206
- /* @__PURE__ */ c(
207
- "span",
208
- {
209
- className: "inline-block w-2 h-2 rounded-full mr-3 mt-2 shrink-0",
210
- style: { backgroundColor: h }
211
- }
212
- ),
213
- /* @__PURE__ */ c("span", { className: "flex-1", children: n.children.map((s, r) => d(s, r)) })
214
- ] }, e);
215
- }
216
- return null;
217
- case "break":
218
- return /* @__PURE__ */ c("br", {}, e);
219
- default:
220
- return null;
221
- }
222
- };
223
- if (!k.trim())
224
- return /* @__PURE__ */ c(
225
- "div",
226
- {
227
- className: "flex items-center justify-center w-full h-full",
228
- style: {
229
- height: x === "100%" ? "100%" : x,
230
- minHeight: x === "100%" ? "200px" : void 0
231
- },
232
- children: /* @__PURE__ */ m("div", { className: "text-center text-dc-text-muted", children: [
233
- /* @__PURE__ */ c("div", { className: "text-sm font-semibold mb-1", children: "No content" }),
234
- /* @__PURE__ */ c("div", { className: "text-xs text-dc-text-secondary", children: "Add markdown content in the chart configuration" })
235
- ] })
236
- }
237
- );
238
- const j = M(k);
239
- return /* @__PURE__ */ c(
240
- "div",
241
- {
242
- className: `p-4 w-full h-full overflow-auto ${y[N]} ${v[u]}`,
243
- style: {
244
- height: x === "100%" ? "100%" : x,
245
- minHeight: x === "100%" ? "200px" : void 0
246
- },
247
- children: j.map((n, e) => d(n, e))
248
- }
249
- );
250
- }
251
- export {
252
- H as default
253
- };
254
- //# sourceMappingURL=chart-markdownchart-C3FAQFuO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-markdownchart-C3FAQFuO.js","sources":["../../../src/client/components/charts/MarkdownChart.tsx"],"sourcesContent":["import React from 'react'\nimport type { ChartProps } from '../../types'\n\ninterface MarkdownNode {\n type: 'text' | 'bold' | 'italic' | 'link' | 'header' | 'list' | 'listItem' | 'paragraph' | 'break'\n content?: string\n url?: string\n level?: number\n ordered?: boolean\n children?: MarkdownNode[]\n parentOrdered?: boolean // For list items to know if parent list is ordered\n}\n\nexport default function MarkdownChart({ \n displayConfig = {},\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const content = displayConfig.content || ''\n const accentColorIndex = displayConfig.accentColorIndex ?? 0\n const fontSize = displayConfig.fontSize || 'medium'\n const alignment = displayConfig.alignment || 'left'\n\n // Get accent color from palette\n const getAccentColor = (): string => {\n if (colorPalette?.colors && accentColorIndex < colorPalette.colors.length) {\n return colorPalette.colors[accentColorIndex]\n }\n return '#8884d8' // Default color\n }\n\n const accentColor = getAccentColor()\n\n // Font size mapping\n const fontSizeClasses = {\n small: 'text-sm',\n medium: 'text-lg', \n large: 'text-xl'\n }\n\n // Alignment mapping\n const alignmentClasses = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right'\n }\n\n // Simple markdown parser\n const parseMarkdown = (text: string): MarkdownNode[] => {\n const lines = text.split('\\n')\n const nodes: MarkdownNode[] = []\n let currentList: MarkdownNode | null = null\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim()\n \n if (!line) {\n // Empty line - end current list and add line break\n if (currentList) {\n nodes.push(currentList)\n currentList = null\n }\n nodes.push({ type: 'break' })\n continue\n }\n\n // Headers\n const headerMatch = line.match(/^(#{1,3})\\s+(.*)$/)\n if (headerMatch) {\n if (currentList) {\n nodes.push(currentList)\n currentList = null\n }\n nodes.push({\n type: 'header',\n level: headerMatch[1].length,\n content: headerMatch[2]\n })\n continue\n }\n\n // Unordered list\n const unorderedMatch = line.match(/^[-*+]\\s+(.*)$/)\n if (unorderedMatch) {\n if (!currentList || currentList.ordered) {\n if (currentList) nodes.push(currentList)\n currentList = { type: 'list', ordered: false, children: [] }\n }\n currentList.children!.push({\n type: 'listItem',\n children: parseInline(unorderedMatch[1]),\n parentOrdered: false\n })\n continue\n }\n\n // Ordered list\n const orderedMatch = line.match(/^\\d+\\.\\s+(.*)$/)\n if (orderedMatch) {\n if (!currentList || !currentList.ordered) {\n if (currentList) nodes.push(currentList)\n currentList = { type: 'list', ordered: true, children: [] }\n }\n currentList.children!.push({\n type: 'listItem',\n children: parseInline(orderedMatch[1]),\n parentOrdered: true\n })\n continue\n }\n\n // Regular paragraph\n if (currentList) {\n nodes.push(currentList)\n currentList = null\n }\n \n nodes.push({\n type: 'paragraph',\n children: parseInline(line)\n })\n }\n\n // Add any remaining list\n if (currentList) {\n nodes.push(currentList)\n }\n\n return nodes\n }\n\n // Parse inline elements (bold, italic, links)\n const parseInline = (text: string): MarkdownNode[] => {\n const nodes: MarkdownNode[] = []\n let remaining = text\n \n while (remaining) {\n // Try to match link first [text](url)\n const linkMatch = remaining.match(/^(.*?)\\[([^\\]]+)\\]\\(([^)]+)\\)(.*)$/)\n if (linkMatch) {\n const [, before, linkText, url, after] = linkMatch\n if (before) {\n nodes.push(...parseSimpleInline(before))\n }\n nodes.push({\n type: 'link',\n content: linkText,\n url: url\n })\n remaining = after\n continue\n }\n\n // No more special formatting, parse remaining as simple inline\n nodes.push(...parseSimpleInline(remaining))\n break\n }\n\n return nodes\n }\n\n // Parse bold and italic\n const parseSimpleInline = (text: string): MarkdownNode[] => {\n const nodes: MarkdownNode[] = []\n let remaining = text\n\n while (remaining) {\n // Try bold first **text**\n const boldMatch = remaining.match(/^(.*?)\\*\\*([^*]+)\\*\\*(.*)$/)\n if (boldMatch) {\n const [, before, boldText, after] = boldMatch\n if (before) nodes.push({ type: 'text', content: before })\n nodes.push({ type: 'bold', content: boldText })\n remaining = after\n continue\n }\n\n // Try italic *text*\n const italicMatch = remaining.match(/^(.*?)\\*([^*]+)\\*(.*)$/)\n if (italicMatch) {\n const [, before, italicText, after] = italicMatch\n if (before) nodes.push({ type: 'text', content: before })\n nodes.push({ type: 'italic', content: italicText })\n remaining = after\n continue\n }\n\n // No more formatting, add as text\n nodes.push({ type: 'text', content: remaining })\n break\n }\n\n return nodes\n }\n\n // Render markdown nodes to React elements\n const renderNode = (node: MarkdownNode, key: number, listNumber?: number): React.ReactNode => {\n switch (node.type) {\n case 'text':\n return <span key={key} className=\"text-dc-text\">{node.content}</span>\n\n case 'bold':\n return <strong key={key} className=\"font-bold text-dc-text\">{node.content}</strong>\n\n case 'italic':\n return <em key={key} className=\"italic text-dc-text\">{node.content}</em>\n\n case 'link':\n return (\n <a \n key={key}\n href={node.url}\n target=\"_blank\"\n rel=\"nofollow noopener noreferrer\"\n className=\"hover:underline transition-colors\"\n style={{ color: accentColor }}\n >\n {node.content}\n </a>\n )\n\n case 'header':\n // Header classes that scale with fontSize setting\n const getHeaderClasses = (level: number, fontSize: string) => {\n const baseClasses = 'font-bold'\n const marginClasses = {\n 1: 'mb-4',\n 2: 'mb-3', \n 3: 'mb-2'\n }\n \n let sizeClasses = ''\n if (fontSize === 'small') {\n sizeClasses = { 1: 'text-lg', 2: 'text-base', 3: 'text-sm' }[level] || 'text-sm'\n } else if (fontSize === 'large') {\n sizeClasses = { 1: 'text-5xl', 2: 'text-4xl', 3: 'text-3xl' }[level] || 'text-3xl'\n } else { // medium (default)\n sizeClasses = { 1: 'text-3xl', 2: 'text-2xl', 3: 'text-xl' }[level] || 'text-xl'\n }\n \n return `${baseClasses} ${sizeClasses} ${marginClasses[level as keyof typeof marginClasses]}`\n }\n \n const HeaderTag = `h${node.level}` as keyof JSX.IntrinsicElements\n return (\n <HeaderTag \n key={key} \n className={getHeaderClasses(node.level as number, fontSize)}\n style={{ color: accentColor }}\n >\n {node.content}\n </HeaderTag>\n )\n\n case 'paragraph':\n return (\n <p key={key} className=\"mb-3 leading-relaxed\">\n {node.children?.map((child, i) => renderNode(child, i))}\n </p>\n )\n\n case 'list':\n const ListTag = node.ordered ? 'ol' : 'ul'\n let listClasses = 'mb-3'\n \n if (alignment === 'center') {\n listClasses += ' list-none flex flex-col items-center'\n } else if (alignment === 'right') {\n listClasses += ' list-none ml-auto max-w-max'\n } else {\n listClasses += ' list-none ml-6'\n }\n \n return (\n <ListTag key={key} className={listClasses}>\n {node.children?.map((child, i) => renderNode(child, i, node.ordered ? i + 1 : undefined))}\n </ListTag>\n )\n\n case 'listItem':\n if (node.children) {\n // For ordered lists, use custom colored numbers\n if (node.parentOrdered && listNumber !== undefined) {\n const numberSizeClass = fontSizeClasses[fontSize as keyof typeof fontSizeClasses]\n \n if (alignment === 'center') {\n return (\n <li key={key} className=\"mb-1 flex items-center justify-center\">\n <span \n className={`inline-block mr-2 shrink-0 ${numberSizeClass} font-medium`}\n style={{ color: accentColor }}\n >\n {listNumber}.\n </span>\n <span className=\"text-center\">\n {node.children.map((child, i) => renderNode(child, i))}\n </span>\n </li>\n )\n } else if (alignment === 'right') {\n return (\n <li key={key} className=\"mb-1 flex items-start justify-end\">\n <span className=\"text-right\">\n {node.children.map((child, i) => renderNode(child, i))}\n </span>\n <span \n className={`inline-block ml-2 shrink-0 ${numberSizeClass} font-medium`}\n style={{ color: accentColor }}\n >\n {listNumber}.\n </span>\n </li>\n )\n } else {\n return (\n <li key={key} className=\"mb-1 flex items-start\">\n <span \n className={`inline-block mr-3 shrink-0 ${numberSizeClass} font-medium`}\n style={{ color: accentColor }}\n >\n {listNumber}.\n </span>\n <span className=\"flex-1\">\n {node.children.map((child, i) => renderNode(child, i))}\n </span>\n </li>\n )\n }\n }\n \n // For unordered lists, use custom bullets with alignment\n if (alignment === 'center') {\n return (\n <li key={key} className=\"mb-1 flex items-center justify-center\">\n <span \n className=\"inline-block w-2 h-2 rounded-full mr-2 shrink-0\"\n style={{ backgroundColor: accentColor }}\n />\n <span className=\"text-center\">\n {node.children.map((child, i) => renderNode(child, i))}\n </span>\n </li>\n )\n } else if (alignment === 'right') {\n return (\n <li key={key} className=\"mb-1 flex items-start justify-end\">\n <span className=\"text-right\">\n {node.children.map((child, i) => renderNode(child, i))}\n </span>\n <span \n className=\"inline-block w-2 h-2 rounded-full ml-2 mt-2 shrink-0\"\n style={{ backgroundColor: accentColor }}\n />\n </li>\n )\n } else {\n return (\n <li key={key} className=\"mb-1 flex items-start\">\n <span \n className=\"inline-block w-2 h-2 rounded-full mr-3 mt-2 shrink-0\"\n style={{ backgroundColor: accentColor }}\n />\n <span className=\"flex-1\">\n {node.children.map((child, i) => renderNode(child, i))}\n </span>\n </li>\n )\n }\n }\n return null\n\n case 'break':\n return <br key={key} />\n\n default:\n return null\n }\n }\n\n if (!content.trim()) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? '200px' : undefined\n }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No content</div>\n <div className=\"text-xs text-dc-text-secondary\">Add markdown content in the chart configuration</div>\n </div>\n </div>\n )\n }\n\n const parsedNodes = parseMarkdown(content)\n\n return (\n <div \n className={`p-4 w-full h-full overflow-auto ${fontSizeClasses[fontSize as keyof typeof fontSizeClasses]} ${alignmentClasses[alignment as keyof typeof alignmentClasses]}`}\n style={{ \n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? '200px' : undefined\n }}\n >\n {parsedNodes.map((node, index) => renderNode(node, index))}\n </div>\n )\n}"],"names":["MarkdownChart","displayConfig","height","colorPalette","content","accentColorIndex","fontSize","alignment","accentColor","fontSizeClasses","alignmentClasses","parseMarkdown","text","lines","nodes","currentList","i","line","headerMatch","unorderedMatch","parseInline","orderedMatch","remaining","linkMatch","before","linkText","url","after","parseSimpleInline","boldMatch","boldText","italicMatch","italicText","renderNode","node","key","listNumber","jsx","getHeaderClasses","level","baseClasses","marginClasses","sizeClasses","HeaderTag","child","ListTag","listClasses","numberSizeClass","jsxs","parsedNodes","index"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"charts-BSDHSv4l.js","sources":["../../../src/client/charts/ChartLoader.tsx","../../../src/client/charts/chartConfigs.ts","../../../src/client/charts/lazyChartConfigRegistry.ts","../../../src/client/utils/index.ts"],"sourcesContent":["/**\n * Lazy Chart Loader\n *\n * Provides React.lazy-based dynamic loading for chart components.\n * This enables code splitting - each chart type loads only when needed.\n */\n\nimport { lazy, Suspense, ComponentType, ReactNode } from 'react'\nimport type { ChartType, ChartProps } from '../types'\n\n// Type for lazy-loaded chart components\ntype LazyChartComponent = ComponentType<ChartProps>\n\n// Chart loader cache to prevent re-creating lazy components\nconst chartLoaderCache = new Map<ChartType, React.LazyExoticComponent<LazyChartComponent>>()\n\n// Dynamic import functions for each chart type\nconst chartImportMap: Record<ChartType, () => Promise<{ default: LazyChartComponent }>> = {\n bar: () => import('../components/charts/BarChart'),\n line: () => import('../components/charts/LineChart'),\n area: () => import('../components/charts/AreaChart'),\n pie: () => import('../components/charts/PieChart'),\n scatter: () => import('../components/charts/ScatterChart'),\n radar: () => import('../components/charts/RadarChart'),\n radialBar: () => import('../components/charts/RadialBarChart'),\n treemap: () => import('../components/charts/TreeMapChart'),\n bubble: () => import('../components/charts/BubbleChart'),\n table: () => import('../components/charts/DataTable'),\n activityGrid: () => import('../components/charts/ActivityGridChart'),\n kpiNumber: () => import('../components/charts/KpiNumber'),\n kpiDelta: () => import('../components/charts/KpiDelta'),\n kpiText: () => import('../components/charts/KpiText'),\n markdown: () => import('../components/charts/MarkdownChart'),\n}\n\n/**\n * Get or create a lazy component for a chart type\n */\nfunction getLazyChart(chartType: ChartType): React.LazyExoticComponent<LazyChartComponent> {\n if (!chartLoaderCache.has(chartType)) {\n const importFn = chartImportMap[chartType]\n if (!importFn) {\n throw new Error(`Unknown chart type: ${chartType}`)\n }\n chartLoaderCache.set(chartType, lazy(importFn))\n }\n return chartLoaderCache.get(chartType)!\n}\n\n/**\n * Check if a chart type is supported\n */\nexport function isValidChartType(chartType: string): chartType is ChartType {\n return chartType in chartImportMap\n}\n\n// Props for the LazyChart wrapper\nexport interface LazyChartProps extends ChartProps {\n chartType: ChartType\n fallback?: ReactNode\n}\n\n/**\n * Default loading placeholder for charts\n */\nfunction DefaultChartFallback({ height }: { height?: string | number }) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height: typeof height === 'number' ? `${height}px` : height || '200px' }}\n >\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full min-h-[100px]\" />\n </div>\n )\n}\n\n/**\n * Lazy Chart Component\n *\n * Renders a chart component with React.lazy dynamic loading.\n * The chart type determines which chart component is loaded.\n *\n * @example\n * ```tsx\n * <LazyChart\n * chartType=\"bar\"\n * data={chartData}\n * chartConfig={{ yAxis: ['value'] }}\n * height={300}\n * />\n * ```\n */\nexport function LazyChart({\n chartType,\n fallback,\n height,\n ...chartProps\n}: LazyChartProps) {\n const ChartComponent = getLazyChart(chartType)\n\n return (\n <Suspense fallback={fallback ?? <DefaultChartFallback height={height} />}>\n <ChartComponent height={height} {...chartProps} />\n </Suspense>\n )\n}\n\n/**\n * Preload a chart type\n *\n * Triggers the dynamic import without rendering.\n * Useful for prefetching charts that will likely be needed.\n *\n * @example\n * ```tsx\n * // Preload bar chart on hover\n * onMouseEnter={() => preloadChart('bar')}\n * ```\n */\nexport function preloadChart(chartType: ChartType): void {\n const importFn = chartImportMap[chartType]\n if (importFn) {\n importFn()\n }\n}\n\n/**\n * Preload multiple chart types\n *\n * @example\n * ```tsx\n * // Preload common charts on app init\n * useEffect(() => {\n * preloadCharts(['bar', 'line', 'pie'])\n * }, [])\n * ```\n */\nexport function preloadCharts(chartTypes: ChartType[]): void {\n chartTypes.forEach(preloadChart)\n}\n\n/**\n * Get all available chart types\n */\nexport function getAvailableChartTypes(): ChartType[] {\n return Object.keys(chartImportMap) as ChartType[]\n}\n","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'\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 * 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\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}\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}\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'\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 (error) {\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":["chartLoaderCache","chartImportMap","n","getLazyChart","chartType","importFn","lazy","isValidChartType","DefaultChartFallback","height","jsx","LazyChart","fallback","chartProps","ChartComponent","Suspense","preloadChart","preloadCharts","chartTypes","getAvailableChartTypes","defaultChartConfig","getChartConfig","registry","configImportMap","configExportNames","configCache","getChartConfigAsync","module","exportName","config","error","getChartConfigSync","isChartConfigLoaded","useChartConfig","setConfig","useState","loading","setLoading","loaded","setLoaded","useEffect","loadedConfig","preloadChartConfig","preloadChartConfigs","loadAllChartConfigs","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":";;;;;;;;;;;;AAcA,MAAMA,wBAAuB,IAAA,GAGvBC,IAAoF;AAAA,EACxF,KAAK,MAAM,OAAO,8BAA+B;AAAA,EACjD,MAAM,MAAM,OAAO,+BAAgC;AAAA,EACnD,MAAM,MAAM,OAAO,+BAAgC,EAAA,KAAA,CAAAC,MAAAA,EAAA,CAAA;AAAA,EACnD,KAAK,MAAM,OAAO,8BAA+B;AAAA,EACjD,SAAS,MAAM,OAAO,kCAAmC;AAAA,EACzD,OAAO,MAAM,OAAO,gCAAiC;AAAA,EACrD,WAAW,MAAM,OAAO,oCAAqC;AAAA,EAC7D,SAAS,MAAM,OAAO,kCAAmC;AAAA,EACzD,QAAQ,MAAM,OAAO,iCAAkC;AAAA,EACvD,OAAO,MAAM,OAAO,+BAAgC;AAAA,EACpD,cAAc,MAAM,OAAO,uCAAwC,EAAA,KAAA,CAAAA,MAAAA,EAAA,CAAA;AAAA,EACnE,WAAW,MAAM,OAAO,+BAAgC,EAAA,KAAA,CAAAA,MAAAA,EAAA,CAAA;AAAA,EACxD,UAAU,MAAM,OAAO,8BAA+B,EAAA,KAAA,CAAAA,MAAAA,EAAA,CAAA;AAAA,EACtD,SAAS,MAAM,OAAO,6BAA8B;AAAA,EACpD,UAAU,MAAM,OAAO,mCAAoC;AAC7D;AAKA,SAASC,EAAaC,GAAqE;AACzF,MAAI,CAACJ,EAAiB,IAAII,CAAS,GAAG;AACpC,UAAMC,IAAWJ,EAAeG,CAAS;AACzC,QAAI,CAACC;AACH,YAAM,IAAI,MAAM,uBAAuBD,CAAS,EAAE;AAEpD,IAAAJ,EAAiB,IAAII,GAAWE,EAAKD,CAAQ,CAAC;AAAA,EAChD;AACA,SAAOL,EAAiB,IAAII,CAAS;AACvC;AAKO,SAASG,EAAiBH,GAA2C;AAC1E,SAAOA,KAAaH;AACtB;AAWA,SAASO,EAAqB,EAAE,QAAAC,KAAwC;AACtE,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,QAAQ,OAAOD,KAAW,WAAW,GAAGA,CAAM,OAAOA,KAAU,QAAA;AAAA,MAExE,UAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,4EAAA,CAA4E;AAAA,IAAA;AAAA,EAAA;AAGjG;AAkBO,SAASC,EAAU;AAAA,EACxB,WAAAP;AAAA,EACA,UAAAQ;AAAA,EACA,QAAAH;AAAA,EACA,GAAGI;AACL,GAAmB;AACjB,QAAMC,IAAiBX,EAAaC,CAAS;AAE7C,SACE,gBAAAM,EAACK,GAAA,EAAS,UAAUH,KAAY,gBAAAF,EAACF,GAAA,EAAqB,QAAAC,EAAA,CAAgB,GACpE,UAAA,gBAAAC,EAACI,GAAA,EAAe,QAAAL,GAAiB,GAAGI,GAAY,GAClD;AAEJ;AAcO,SAASG,EAAaZ,GAA4B;AACvD,QAAMC,IAAWJ,EAAeG,CAAS;AACzC,EAAIC,KACFA,EAAA;AAEJ;AAaO,SAASY,EAAcC,GAA+B;AAC3D,EAAAA,EAAW,QAAQF,CAAY;AACjC;AAKO,SAASG,IAAsC;AACpD,SAAO,OAAO,KAAKlB,CAAc;AACnC;ACtCO,MAAMmB,IAAsC;AAAA,EACjD,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,aAAa,CAAC,aAAa,eAAe;AAAA,MAC1C,WAAW;AAAA,IAAA;AAAA,IAEb;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,aAAa,CAAC,WAAW,WAAW;AAAA,MACpC,WAAW;AAAA,IAAA;AAAA,IAEb;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,aAAa,CAAC,WAAW;AAAA,MACzB,WAAW;AAAA,IAAA;AAAA,EACb;AAAA,EAEF,gBAAgB,CAAC,cAAc,YAAY,aAAa;AAC1D;AAKO,SAASC,EAAejB,GAAmBkB,GAAgD;AAChG,SAAOA,EAASlB,CAAS,KAAKgB;AAChC;AClIA,MAAMG,IAAwF;AAAA,EAC5F,KAAK,MAAM,OAAO,qCAAsC;AAAA,EACxD,MAAM,MAAM,OAAO,sCAAuC;AAAA,EAC1D,MAAM,MAAM,OAAO,sCAAuC;AAAA,EAC1D,KAAK,MAAM,OAAO,qCAAsC;AAAA,EACxD,SAAS,MAAM,OAAO,yCAA0C;AAAA,EAChE,OAAO,MAAM,OAAO,uCAAwC;AAAA,EAC5D,WAAW,MAAM,OAAO,2CAA4C;AAAA,EACpE,SAAS,MAAM,OAAO,yCAA0C;AAAA,EAChE,QAAQ,MAAM,OAAO,wCAAyC;AAAA,EAC9D,OAAO,MAAM,OAAO,sCAAuC;AAAA,EAC3D,cAAc,MAAM,OAAO,8CAA+C,EAAA,KAAA,CAAArB,MAAAA,EAAA,CAAA;AAAA,EAC1E,WAAW,MAAM,OAAO,sCAAuC;AAAA,EAC/D,UAAU,MAAM,OAAO,qCAAsC;AAAA,EAC7D,SAAS,MAAM,OAAO,oCAAqC;AAAA,EAC3D,UAAU,MAAM,OAAO,0CAA2C;AACpE,GAGMsB,IAA+C;AAAA,EACnD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AACZ,GAGMC,wBAAkB,IAAA;AAcxB,eAAsBC,EAAoBtB,GAAuD;AAE/F,MAAIqB,EAAY,IAAIrB,CAAS;AAC3B,WAAOqB,EAAY,IAAIrB,CAAS;AAGlC,QAAMC,IAAWkB,EAAgBnB,CAAS;AAC1C,MAAI,CAACC;AACH,WAAO;AAGT,MAAI;AACF,UAAMsB,IAAS,MAAMtB,EAAA,GACfuB,IAAaJ,EAAkBpB,CAAS,GACxCyB,IAASF,EAAOC,CAAU;AAEhC,WAAIC,KACFJ,EAAY,IAAIrB,GAAWyB,CAAM,GAC1BA,KAEF;AAAA,EACT,SAASC,GAAO;AACd,mBAAQ,MAAM,yCAAyC1B,CAAS,IAAI0B,CAAK,GAClE;AAAA,EACT;AACF;AAWO,SAASC,EAAmB3B,GAAuC;AACxE,SAAOqB,EAAY,IAAIrB,CAAS,KAAKgB;AACvC;AAKO,SAASY,EAAoB5B,GAA+B;AACjE,SAAOqB,EAAY,IAAIrB,CAAS;AAClC;AAqBO,SAAS6B,EAAe7B,GAI7B;AACA,QAAM,CAACyB,GAAQK,CAAS,IAAIC;AAAA,IAC1B/B,IAAY2B,EAAmB3B,CAAS,IAAIgB;AAAA,EAAA,GAExC,CAACgB,GAASC,CAAU,IAAIF,EAAS,EAAK,GACtC,CAACG,GAAQC,CAAS,IAAIJ,EAAS,EAAK;AAE1C,SAAAK,EAAU,MAAM;AACd,QAAI,CAACpC,GAAW;AACd,MAAA8B,EAAUd,CAAkB,GAC5BmB,EAAU,EAAK;AACf;AAAA,IACF;AAGA,QAAId,EAAY,IAAIrB,CAAS,GAAG;AAC9B,MAAA8B,EAAUT,EAAY,IAAIrB,CAAS,CAAE,GACrCmC,EAAU,EAAI;AACd;AAAA,IACF;AAGA,IAAAF,EAAW,EAAI,GACfX,EAAoBtB,CAAS,EAC1B,KAAK,CAACqC,MAAiB;AACtB,MAAIA,KACFP,EAAUO,CAAY,GACtBF,EAAU,EAAI,MAEdL,EAAUd,CAAkB,GAC5BmB,EAAU,EAAI;AAAA,IAElB,CAAC,EACA,QAAQ,MAAMF,EAAW,EAAK,CAAC;AAAA,EACpC,GAAG,CAACjC,CAAS,CAAC,GAEP,EAAE,QAAAyB,GAAQ,SAAAO,GAAS,QAAAE,EAAA;AAC5B;AAUA,eAAsBI,EAAmBtC,GAAqC;AAC5E,EAAKqB,EAAY,IAAIrB,CAAS,KAC5B,MAAMsB,EAAoBtB,CAAS;AAEvC;AAOA,eAAsBuC,EAAoBzB,GAAwC;AAChF,QAAM,QAAQ,IAAIA,EAAW,IAAIwB,CAAkB,CAAC;AACtD;AAiBA,eAAsBE,IAAoD;AACxE,QAAM1B,IAAa,OAAO,KAAKK,CAAe;AAC9C,QAAM,QAAQ,IAAIL,EAAW,IAAIQ,CAAmB,CAAC;AAErD,QAAMJ,IAAgC,CAAA;AACtC,aAAWlB,KAAac,GAAY;AAClC,UAAMW,IAASJ,EAAY,IAAIrB,CAAS;AACxC,IAAIyB,MACFP,EAASlB,CAAS,IAAIyB;AAAA,EAE1B;AACA,SAAOP;AACT;AAOO,SAASuB,IAA8B;AAC5C,EAAApB,EAAY,MAAA;AACd;ACzNO,SAASqB,EAAsBC,GAA4C;AAChF,QAAMC,IAAUC,EAA0BF,CAAQ;AAElD,SAAO;AAAA,IACL,UAAAA;AAAA,IACA,SAAAC;AAAA,EAAA;AAEJ;AAKO,SAASC,EAA0BF,GAA2B;AACnE,QAAMG,IAAaH,EAAS,IAAI,CAAAI,OAAY;AAAA,IAC1C,GAAGA,EAAQ;AAAA,IACX,GAAGA,EAAQ;AAAA,IACX,GAAGA,EAAQ;AAAA,IACX,GAAGA,EAAQ;AAAA,IACX,GAAGA,EAAQ;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,EAAA,EACN;AAEF,SAAO;AAAA,IACL,IAAID;AAAA,IACJ,IAAIA,EAAW,IAAI,CAAAE,OAAS,EAAE,GAAGA,GAAM,GAAG,KAAK,IAAIA,EAAK,GAAG,CAAC,IAAI;AAAA,IAChE,IAAIF,EAAW,IAAI,CAAAE,OAAS,EAAE,GAAGA,GAAM,GAAG,KAAK,IAAIA,EAAK,GAAG,CAAC,IAAI;AAAA,IAChE,IAAIF,EAAW,IAAI,CAAAE,OAAS,EAAE,GAAGA,GAAM,GAAG,KAAK,IAAIA,EAAK,GAAG,CAAC,IAAI;AAAA,IAChE,KAAKF,EAAW,IAAI,CAAAE,OAAS,EAAE,GAAGA,GAAM,GAAG,IAAI;AAAA,EAAA;AAEnD;AAKO,SAASC,EAAgBC,GAAaC,IAGzC,IAAW;AACb,QAAM,EAAE,eAAAC,IAAgB,IAAM,WAAAC,IAAY,MAAMF;AAEhD,SAAKC,IAEEF,EAAK,IAAI,CAAAI,MAAO;AACrB,UAAMC,IAAoB,CAAA;AAE1B,eAAW,CAACC,GAAKC,CAAK,KAAK,OAAO,QAAQH,CAAG;AAC3C,MAAI,OAAOG,KAAU,WACnBF,EAAaC,CAAG,IAAI,OAAOC,EAAM,QAAQJ,CAAS,CAAC,IAEnDE,EAAaC,CAAG,IAAIC;AAIxB,WAAOF;AAAA,EACT,CAAC,IAd0BL;AAe7B;AAKO,SAASQ,IAA4B;AAC1C,SAAO,WAAW,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AACzE;AAKO,SAASC,EAAiBC,GAAmCC,IAAa,GAAGC,IAAa,GAA6B;AAC5H,SAAIF,EAAiB,WAAW,IACvB,EAAE,GAAG,GAAG,GAAG,EAAA,IAMb,EAAE,GAAG,GAAG,GAFF,KAAK,IAAI,GAAGA,EAAiB,IAAI,CAAAG,MAAKA,EAAE,IAAIA,EAAE,CAAC,CAAC,EAE3C;AACpB;AAKO,SAASC,EAAkBC,GAAsE;AACtG,MAAI;AACF,UAAMC,IAAQ,KAAK,MAAMD,CAAW;AAGpC,WAAI,OAAOC,KAAU,YAAYA,MAAU,OAClC,EAAE,OAAO,IAAO,OAAO,8BAAA,IAI5B,CAACA,EAAM,YAAY,CAACA,EAAM,aACrB,EAAE,OAAO,IAAO,OAAO,kDAAA,IAGzB,EAAE,OAAO,IAAM,OAAAA,EAAA;AAAA,EACxB,QAAgB;AACd,WAAO,EAAE,OAAO,IAAO,OAAO,sBAAA;AAAA,EAChC;AACF;AAKO,SAASC,IAAiD;AAC/D,SAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO,KAAK,UAAU;AAAA,MACpB,UAAU,CAAC,OAAO;AAAA,MAClB,YAAY,CAAC,UAAU;AAAA,IAAA,GACtB,MAAM,CAAC;AAAA,IACV,WAAW;AAAA,IACX,aAAa;AAAA,MACX,GAAG;AAAA,MACH,GAAG,CAAC,OAAO;AAAA,IAAA;AAAA,IAEb,eAAe;AAAA,MACb,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,aAAa;AAAA,IAAA;AAAA,IAEf,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EAAA;AAEP;"}