drizzle-cube 0.2.27 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/charts/chartConfigs.d.ts +1 -1
- package/dist/client/charts.js +2 -2
- package/dist/client/chunks/{charts-BfXEKIrq.js → charts-Cr9ec7VQ.js} +66 -63
- package/dist/client/chunks/charts-Cr9ec7VQ.js.map +1 -0
- package/dist/client/chunks/{charts-DQuOI5HA.js → charts-nP6WCxHG.js} +2725 -2488
- package/dist/client/chunks/charts-nP6WCxHG.js.map +1 -0
- package/dist/client/chunks/{components-CWMeA5e-.js → components-CCRoi0sB.js} +5347 -4700
- package/dist/client/chunks/components-CCRoi0sB.js.map +1 -0
- package/dist/client/chunks/core-DcL8wSpZ.js +6 -0
- package/dist/client/chunks/core-DcL8wSpZ.js.map +1 -0
- package/dist/client/chunks/{hooks-CAKGR-w0.js → hooks-CM78mXuP.js} +20 -19
- package/dist/client/chunks/{hooks-CAKGR-w0.js.map → hooks-CM78mXuP.js.map} +1 -1
- package/dist/client/chunks/{icons-DI4Xack3.js → icons-D7ek1iXF.js} +39 -39
- package/dist/client/chunks/{icons-DI4Xack3.js.map → icons-D7ek1iXF.js.map} +1 -1
- package/dist/client/components/AnalysisBuilder/FunnelBindingKeySelector.d.ts +21 -0
- package/dist/client/components/AnalysisBuilder/types.d.ts +15 -4
- package/dist/client/components/charts/FunnelChart.config.d.ts +9 -0
- package/dist/client/components/charts/FunnelChart.d.ts +11 -0
- package/dist/client/components.js +2 -2
- package/dist/client/hooks/queries/index.d.ts +2 -1
- package/dist/client/hooks/queries/useFunnelQuery.d.ts +25 -0
- package/dist/client/hooks/useAnalysisBuilderHook.d.ts +7 -3
- package/dist/client/hooks/useAnalysisQueryExecution.d.ts +12 -1
- package/dist/client/hooks.d.ts +1 -1
- package/dist/client/hooks.js +12 -11
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +1 -1
- package/dist/client/index.d.ts +5 -3
- package/dist/client/index.js +115 -98
- package/dist/client/providers.js +1 -1
- package/dist/client/stores/analysisBuilderStore.d.ts +21 -1
- package/dist/client/styles.css +1 -1
- package/dist/client/types/funnel.d.ts +231 -0
- package/dist/client/types.d.ts +11 -2
- package/dist/client/utils/funnelExecution.d.ts +111 -0
- package/dist/client/utils/funnelValidation.d.ts +46 -0
- package/dist/client/utils/multiQueryValidation.d.ts +3 -3
- package/dist/client-bundle-stats.html +1 -1
- package/package.json +2 -2
- package/dist/client/chunks/charts-BfXEKIrq.js.map +0 -1
- package/dist/client/chunks/charts-DQuOI5HA.js.map +0 -1
- package/dist/client/chunks/components-CWMeA5e-.js.map +0 -1
- package/dist/client/chunks/core-DrhYtHHa.js +0 -6
- package/dist/client/chunks/core-DrhYtHHa.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components-CCRoi0sB.js","sources":["../../../node_modules/react-intersection-observer/dist/index.mjs","../../../src/client/utils/funnelExecution.ts","../../../src/client/hooks/queries/useFunnelQuery.ts","../../../src/client/components/ChartErrorBoundary.tsx","../../../src/client/types.ts","../../../src/client/utils/filterUtils.ts","../../../src/client/components/AnalyticsPortlet.tsx","../../../src/client/hooks/useScrollDetection.ts","../../../src/client/hooks/useElementVisibility.ts","../../../src/client/utils/syntaxHighlighting.ts","../../../src/client/components/DebugModal.tsx","../../../node_modules/zustand/esm/vanilla.mjs","../../../node_modules/zustand/esm/react.mjs","../../../node_modules/zustand/esm/middleware.mjs","../../../src/client/stores/dashboardStore.tsx","../../../src/client/components/DashboardPortletCard.tsx","../../../src/client/components/RowManagedLayout.tsx","../../../src/client/utils/colorPalettes.ts","../../../src/client/components/FloatingEditToolbar.tsx","../../../src/client/components/Modal.tsx","../../../src/client/components/AnalysisBuilder/utils/idUtils.ts","../../../src/shared/date-utils.ts","../../../src/client/components/AnalysisBuilder/utils/filterUtils.ts","../../../src/client/components/AnalysisBuilder/utils/queryUtils.ts","../../../src/client/components/AnalysisBuilder/utils/storageUtils.ts","../../../src/client/components/AnalysisBuilder/utils/fieldUtils.ts","../../../src/client/components/AnalysisBuilder/utils/recentFieldsUtils.ts","../../../src/client/shared/chartDefaults.ts","../../../src/client/stores/analysisBuilderStore.tsx","../../../src/client/utils/multiQueryValidation.ts","../../../src/client/hooks/useAnalysisQueryBuilder.ts","../../../src/client/hooks/useAnalysisCombinedFields.ts","../../../src/client/hooks/useAnalysisQueryExecution.ts","../../../src/client/hooks/useAnalysisChartDefaults.ts","../../../src/client/hooks/useAnalysisUIState.ts","../../../node_modules/lz-string/libs/lz-string.js","../../../src/client/utils/shareUtils.ts","../../../src/client/hooks/useAnalysisInitialization.ts","../../../src/client/hooks/useAnalysisBuilderHook.ts","../../../src/client/components/AIAssistant/utils.ts","../../../src/client/hooks/useAnalysisAI.ts","../../../src/client/hooks/useAnalysisShare.ts","../../../src/client/components/AnalysisBuilder/FieldSearchItem.tsx","../../../src/client/components/AnalysisBuilder/FieldDetailPanel.tsx","../../../src/client/components/AnalysisBuilder/FieldSearchModal.tsx","../../../src/client/shared/components/QueryAnalysisPanel.tsx","../../../node_modules/highlight.js/lib/core.js","../../../node_modules/highlight.js/es/languages/json.js","../../../node_modules/highlight.js/es/languages/sql.js","../../../src/client/shared/components/CodeBlock.tsx","../../../src/client/components/ColorPaletteSelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisResultsPanel.tsx","../../../src/client/components/AnalysisBuilder/MetricItemCard.tsx","../../../src/client/components/AnalysisBuilder/MetricsSection.tsx","../../../src/client/components/AnalysisBuilder/types.ts","../../../src/client/components/AnalysisBuilder/BreakdownItemCard.tsx","../../../src/client/components/AnalysisBuilder/BreakdownSection.tsx","../../../src/client/components/AnalysisBuilder/FilterConfigModal.tsx","../../../src/client/components/AnalysisBuilder/AnalysisFilterItem.tsx","../../../src/client/components/AnalysisBuilder/AnalysisFilterGroup.tsx","../../../src/client/components/AnalysisBuilder/AnalysisFilterSection.tsx","../../../src/client/components/AnalysisBuilder/AnalysisAxisDropZone.tsx","../../../src/client/charts/chartConfigRegistry.ts","../../../src/client/components/ChartTypeSelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisChartConfigPanel.tsx","../../../src/client/components/AnalysisBuilder/AnalysisDisplayConfigPanel.tsx","../../../src/client/utils/funnelValidation.ts","../../../src/client/components/AnalysisBuilder/FunnelBindingKeySelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisQueryPanel.tsx","../../../src/client/components/AnalysisBuilder/AnalysisAIPanel.tsx","../../../src/client/components/AnalysisBuilder/index.tsx","../../../src/client/components/PortletAnalysisModal.tsx","../../../src/client/components/PortletFilterConfigModal.tsx","../../../src/client/components/ConfirmModal.tsx","../../../src/client/components/DashboardFilters/DashboardFilterConfigModal.tsx","../../../src/client/components/DashboardFilters/FilterEditModal.tsx","../../../src/client/components/DashboardFilters/EditModeFilterList.tsx","../../../src/client/components/shared/utils.ts","../../../src/client/components/DashboardFilters/DatePresetChips.tsx","../../../src/client/components/DashboardFilters/CustomDateDropdown.tsx","../../../src/client/components/DashboardFilters/XTDDropdown.tsx","../../../src/client/components/shared/FilterValueSelector.tsx","../../../src/client/components/DashboardFilters/FilterValuePopover.tsx","../../../src/client/components/DashboardFilters/FilterChip.tsx","../../../src/client/components/DashboardFilters/CompactFilterBar.tsx","../../../src/client/components/DashboardFilterPanel.tsx","../../../src/client/components/ScaledGridWrapper.tsx","../../../src/client/components/MobileStackedLayout.tsx","../../../node_modules/zustand/esm/vanilla/shallow.mjs","../../../node_modules/zustand/esm/react/shallow.mjs","../../../src/client/hooks/useDashboardHook.ts","../../../src/client/components/DashboardGrid.tsx","../../../src/client/components/AnalyticsDashboard.tsx","../../../src/client/components/PortletContainer.tsx","../../../src/client/components/DashboardEditModal.tsx","../../../src/client/components/QueryBuilderShim.tsx"],"sourcesContent":["\"use client\";\nvar __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n\n// src/InView.tsx\nimport * as React from \"react\";\n\n// src/observe.ts\nvar observerMap = /* @__PURE__ */ new Map();\nvar RootIds = /* @__PURE__ */ new WeakMap();\nvar rootId = 0;\nvar unsupportedValue;\nfunction defaultFallbackInView(inView) {\n unsupportedValue = inView;\n}\nfunction getRootId(root) {\n if (!root) return \"0\";\n if (RootIds.has(root)) return RootIds.get(root);\n rootId += 1;\n RootIds.set(root, rootId.toString());\n return RootIds.get(root);\n}\nfunction optionsToId(options) {\n return Object.keys(options).sort().filter(\n (key) => options[key] !== void 0\n ).map((key) => {\n return `${key}_${key === \"root\" ? getRootId(options.root) : options[key]}`;\n }).toString();\n}\nfunction createObserver(options) {\n const id = optionsToId(options);\n let instance = observerMap.get(id);\n if (!instance) {\n const elements = /* @__PURE__ */ new Map();\n let thresholds;\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n var _a2;\n const inView = entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold);\n if (options.trackVisibility && typeof entry.isVisible === \"undefined\") {\n entry.isVisible = inView;\n }\n (_a2 = elements.get(entry.target)) == null ? void 0 : _a2.forEach((callback) => {\n callback(inView, entry);\n });\n });\n }, options);\n thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]);\n instance = {\n id,\n observer,\n elements\n };\n observerMap.set(id, instance);\n }\n return instance;\n}\nfunction observe(element, callback, options = {}, fallbackInView = unsupportedValue) {\n if (typeof window.IntersectionObserver === \"undefined\" && fallbackInView !== void 0) {\n const bounds = element.getBoundingClientRect();\n callback(fallbackInView, {\n isIntersecting: fallbackInView,\n target: element,\n intersectionRatio: typeof options.threshold === \"number\" ? options.threshold : 0,\n time: 0,\n boundingClientRect: bounds,\n intersectionRect: bounds,\n rootBounds: bounds\n });\n return () => {\n };\n }\n const { id, observer, elements } = createObserver(options);\n const callbacks = elements.get(element) || [];\n if (!elements.has(element)) {\n elements.set(element, callbacks);\n }\n callbacks.push(callback);\n observer.observe(element);\n return function unobserve() {\n callbacks.splice(callbacks.indexOf(callback), 1);\n if (callbacks.length === 0) {\n elements.delete(element);\n observer.unobserve(element);\n }\n if (elements.size === 0) {\n observer.disconnect();\n observerMap.delete(id);\n }\n };\n}\n\n// src/InView.tsx\nfunction isPlainChildren(props) {\n return typeof props.children !== \"function\";\n}\nvar InView = class extends React.Component {\n constructor(props) {\n super(props);\n __publicField(this, \"node\", null);\n __publicField(this, \"_unobserveCb\", null);\n __publicField(this, \"lastInView\");\n __publicField(this, \"handleNode\", (node) => {\n if (this.node) {\n this.unobserve();\n if (!node && !this.props.triggerOnce && !this.props.skip) {\n this.setState({ inView: !!this.props.initialInView, entry: void 0 });\n this.lastInView = this.props.initialInView;\n }\n }\n this.node = node ? node : null;\n this.observeNode();\n });\n __publicField(this, \"handleChange\", (inView, entry) => {\n const previousInView = this.lastInView;\n this.lastInView = inView;\n if (previousInView === void 0 && !inView) {\n return;\n }\n if (inView && this.props.triggerOnce) {\n this.unobserve();\n }\n if (!isPlainChildren(this.props)) {\n this.setState({ inView, entry });\n }\n if (this.props.onChange) {\n this.props.onChange(inView, entry);\n }\n });\n this.state = {\n inView: !!props.initialInView,\n entry: void 0\n };\n this.lastInView = props.initialInView;\n }\n componentDidMount() {\n this.unobserve();\n this.observeNode();\n }\n componentDidUpdate(prevProps) {\n if (prevProps.rootMargin !== this.props.rootMargin || prevProps.root !== this.props.root || prevProps.threshold !== this.props.threshold || prevProps.skip !== this.props.skip || prevProps.trackVisibility !== this.props.trackVisibility || prevProps.delay !== this.props.delay) {\n this.unobserve();\n this.observeNode();\n }\n }\n componentWillUnmount() {\n this.unobserve();\n }\n observeNode() {\n if (!this.node || this.props.skip) return;\n const {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n fallbackInView\n } = this.props;\n if (this.lastInView === void 0) {\n this.lastInView = this.props.initialInView;\n }\n this._unobserveCb = observe(\n this.node,\n this.handleChange,\n {\n threshold,\n root,\n rootMargin,\n // @ts-expect-error\n trackVisibility,\n delay\n },\n fallbackInView\n );\n }\n unobserve() {\n if (this._unobserveCb) {\n this._unobserveCb();\n this._unobserveCb = null;\n }\n }\n render() {\n const { children } = this.props;\n if (typeof children === \"function\") {\n const { inView, entry } = this.state;\n return children({ inView, entry, ref: this.handleNode });\n }\n const {\n as,\n triggerOnce,\n threshold,\n root,\n rootMargin,\n onChange,\n skip,\n trackVisibility,\n delay,\n initialInView,\n fallbackInView,\n ...props\n } = this.props;\n return React.createElement(\n as || \"div\",\n { ref: this.handleNode, ...props },\n children\n );\n }\n};\n\n// src/useInView.tsx\nimport * as React2 from \"react\";\nfunction useInView({\n threshold,\n delay,\n trackVisibility,\n rootMargin,\n root,\n triggerOnce,\n skip,\n initialInView,\n fallbackInView,\n onChange\n} = {}) {\n var _a2;\n const [ref, setRef] = React2.useState(null);\n const callback = React2.useRef(onChange);\n const lastInViewRef = React2.useRef(initialInView);\n const [state, setState] = React2.useState({\n inView: !!initialInView,\n entry: void 0\n });\n callback.current = onChange;\n React2.useEffect(\n () => {\n if (lastInViewRef.current === void 0) {\n lastInViewRef.current = initialInView;\n }\n if (skip || !ref) return;\n let unobserve;\n unobserve = observe(\n ref,\n (inView, entry) => {\n const previousInView = lastInViewRef.current;\n lastInViewRef.current = inView;\n if (previousInView === void 0 && !inView) {\n return;\n }\n setState({\n inView,\n entry\n });\n if (callback.current) callback.current(inView, entry);\n if (entry.isIntersecting && triggerOnce && unobserve) {\n unobserve();\n unobserve = void 0;\n }\n },\n {\n root,\n rootMargin,\n threshold,\n // @ts-expect-error\n trackVisibility,\n delay\n },\n fallbackInView\n );\n return () => {\n if (unobserve) {\n unobserve();\n }\n };\n },\n // We break the rule here, because we aren't including the actual `threshold` variable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n // If the threshold is an array, convert it to a string, so it won't change between renders.\n Array.isArray(threshold) ? threshold.toString() : threshold,\n ref,\n root,\n rootMargin,\n triggerOnce,\n skip,\n trackVisibility,\n fallbackInView,\n delay\n ]\n );\n const entryTarget = (_a2 = state.entry) == null ? void 0 : _a2.target;\n const previousEntryTarget = React2.useRef(void 0);\n if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) {\n previousEntryTarget.current = entryTarget;\n setState({\n inView: !!initialInView,\n entry: void 0\n });\n lastInViewRef.current = initialInView;\n }\n const result = [setRef, state.inView, state.entry];\n result.ref = result[0];\n result.inView = result[1];\n result.entry = result[2];\n return result;\n}\n\n// src/useOnInView.tsx\nimport * as React3 from \"react\";\nvar _a, _b;\nvar useSyncEffect = (_b = (_a = React3.useInsertionEffect) != null ? _a : React3.useLayoutEffect) != null ? _b : React3.useEffect;\nvar useOnInView = (onIntersectionChange, {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n triggerOnce,\n skip\n} = {}) => {\n const onIntersectionChangeRef = React3.useRef(onIntersectionChange);\n const observedElementRef = React3.useRef(null);\n const observerCleanupRef = React3.useRef(void 0);\n const lastInViewRef = React3.useRef(void 0);\n useSyncEffect(() => {\n onIntersectionChangeRef.current = onIntersectionChange;\n }, [onIntersectionChange]);\n return React3.useCallback(\n (element) => {\n const cleanupExisting = () => {\n if (observerCleanupRef.current) {\n const cleanup = observerCleanupRef.current;\n observerCleanupRef.current = void 0;\n cleanup();\n }\n };\n if (element === observedElementRef.current) {\n return observerCleanupRef.current;\n }\n if (!element || skip) {\n cleanupExisting();\n observedElementRef.current = null;\n lastInViewRef.current = void 0;\n return;\n }\n cleanupExisting();\n observedElementRef.current = element;\n let destroyed = false;\n const destroyObserver = observe(\n element,\n (inView, entry) => {\n const previousInView = lastInViewRef.current;\n lastInViewRef.current = inView;\n if (previousInView === void 0 && !inView) {\n return;\n }\n onIntersectionChangeRef.current(\n inView,\n entry\n );\n if (triggerOnce && inView) {\n stopObserving();\n }\n },\n {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay\n }\n );\n function stopObserving() {\n if (destroyed) return;\n destroyed = true;\n destroyObserver();\n observedElementRef.current = null;\n observerCleanupRef.current = void 0;\n lastInViewRef.current = void 0;\n }\n observerCleanupRef.current = stopObserving;\n return observerCleanupRef.current;\n },\n [\n Array.isArray(threshold) ? threshold.toString() : threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n triggerOnce,\n skip\n ]\n );\n};\nexport {\n InView,\n defaultFallbackInView,\n observe,\n useInView,\n useOnInView\n};\n//# sourceMappingURL=index.mjs.map","/**\n * Funnel Query Execution Utilities\n *\n * Handles sequential execution of funnel queries where each step\n * filters based on binding key values from the previous step.\n */\n\nimport type { CubeQuery, SimpleFilter } from '../types'\n\n/**\n * Default maximum number of binding key values to pass between funnel steps.\n * Limits the size of the IN clause to prevent performance issues.\n */\nexport const DEFAULT_BINDING_KEY_LIMIT = 500\nimport type {\n FunnelBindingKey,\n FunnelBindingKeyMapping,\n FunnelConfig,\n FunnelStep,\n FunnelStepResult,\n FunnelExecutionResult,\n FunnelChartData,\n} from '../types/funnel'\n\n/**\n * Extract the binding key field name for a specific query/cube.\n *\n * For simple binding keys (string), returns the dimension directly.\n * For cross-cube mappings, finds the mapping for the cube used in the query.\n *\n * @param bindingKey - The funnel binding key configuration\n * @param query - The cube query (used to determine which cube is being queried)\n * @returns The binding key field name (e.g., \"Users.userId\")\n */\nexport function getBindingKeyField(\n bindingKey: FunnelBindingKey,\n query: CubeQuery\n): string {\n // Simple case: single dimension name\n if (typeof bindingKey.dimension === 'string') {\n return bindingKey.dimension\n }\n\n // Cross-cube case: find the mapping for this query's cube\n const mappings = bindingKey.dimension as FunnelBindingKeyMapping[]\n\n // Extract cube name from query fields\n const cubeName = getCubeNameFromQuery(query)\n if (!cubeName) {\n // If we can't determine the cube, use the first mapping\n return mappings[0]?.dimension || ''\n }\n\n // Find matching mapping\n const mapping = mappings.find(m => m.cube === cubeName)\n if (mapping) {\n return mapping.dimension\n }\n\n // Fallback to first mapping if no match found\n return mappings[0]?.dimension || ''\n}\n\n/**\n * Extract the cube name from a query by looking at measures/dimensions\n */\nexport function getCubeNameFromQuery(query: CubeQuery): string | null {\n // Check measures first\n if (query.measures && query.measures.length > 0) {\n const parts = query.measures[0].split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n // Then check dimensions\n if (query.dimensions && query.dimensions.length > 0) {\n const parts = query.dimensions[0].split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n // Then check time dimensions\n if (query.timeDimensions && query.timeDimensions.length > 0) {\n const parts = query.timeDimensions[0].dimension.split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n return null\n}\n\n/**\n * Result from extracting binding key values\n */\nexport interface ExtractedBindingKeyValues {\n /** Binding key values (limited to max if specified) */\n values: (string | number)[]\n /** Total count of unique values before limiting */\n totalCount: number\n /** Whether values were truncated due to limit */\n wasTruncated: boolean\n}\n\n/**\n * Extract unique values for the binding key from query result data\n *\n * @param data - Raw data from query result\n * @param bindingKeyField - The field name to extract values from\n * @param limit - Maximum number of values to return (default: DEFAULT_BINDING_KEY_LIMIT)\n * @returns Object with values array, total count, and truncation flag\n */\nexport function extractBindingKeyValues(\n data: unknown[],\n bindingKeyField: string,\n limit: number = DEFAULT_BINDING_KEY_LIMIT\n): ExtractedBindingKeyValues {\n const values = new Set<string | number>()\n\n for (const row of data) {\n if (typeof row === 'object' && row !== null) {\n const value = (row as Record<string, unknown>)[bindingKeyField]\n if (value !== null && value !== undefined) {\n // Convert to string or number\n if (typeof value === 'number') {\n values.add(value)\n } else {\n values.add(String(value))\n }\n }\n }\n }\n\n const allValues = Array.from(values)\n const totalCount = allValues.length\n\n // Sort values for consistent ordering (enables query cache hits)\n // Numbers sort numerically, strings sort alphabetically\n allValues.sort((a, b) => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n return String(a).localeCompare(String(b))\n })\n\n const limitedValues = limit > 0 ? allValues.slice(0, limit) : allValues\n\n return {\n values: limitedValues,\n totalCount,\n wasTruncated: limitedValues.length < totalCount,\n }\n}\n\n/**\n * Build a step query with binding key filter applied.\n *\n * For the first step (no previous values), returns the original query\n * with the binding key dimension ensured.\n *\n * For subsequent steps, adds an IN filter for the previous step's\n * binding key values.\n *\n * @param step - The funnel step configuration\n * @param bindingKey - The funnel binding key configuration\n * @param previousBindingKeyValues - Binding key values from previous step (null for first step)\n * @returns Modified CubeQuery with binding key filter\n */\nexport function buildStepQuery(\n step: FunnelStep,\n bindingKey: FunnelBindingKey,\n previousBindingKeyValues: (string | number)[] | null\n): CubeQuery {\n const query: CubeQuery = { ...step.query }\n\n // Get binding key field for this query\n const bindingKeyField = getBindingKeyField(bindingKey, query)\n\n // Ensure binding key dimension is in the query (needed to extract values for next step)\n if (!query.dimensions?.includes(bindingKeyField)) {\n query.dimensions = [...(query.dimensions || []), bindingKeyField]\n }\n\n // Add IN filter for previous step's binding key values (except for first step)\n if (previousBindingKeyValues && previousBindingKeyValues.length > 0) {\n const inFilter: SimpleFilter = {\n member: bindingKeyField,\n operator: 'in',\n values: previousBindingKeyValues,\n }\n query.filters = [...(query.filters || []), inFilter]\n }\n\n return query\n}\n\n/**\n * Calculate conversion metrics for a step\n */\nexport function calculateStepMetrics(\n currentCount: number,\n previousCount: number | null,\n firstStepCount: number\n): {\n conversionRate: number | null\n cumulativeConversionRate: number\n} {\n const conversionRate =\n previousCount !== null && previousCount > 0\n ? currentCount / previousCount\n : null\n\n const cumulativeConversionRate =\n firstStepCount > 0 ? currentCount / firstStepCount : 1.0\n\n return { conversionRate, cumulativeConversionRate }\n}\n\n/**\n * Build a funnel step result from query execution\n */\nexport function buildStepResult(\n step: FunnelStep,\n stepIndex: number,\n data: unknown[],\n bindingKeyField: string,\n countUnique: boolean,\n previousCount: number | null,\n firstStepCount: number,\n executionTime: number,\n error: Error | null = null,\n bindingKeyLimit: number = DEFAULT_BINDING_KEY_LIMIT\n): FunnelStepResult {\n // Extract binding key values (with limit applied)\n const extracted = error\n ? { values: [], totalCount: 0, wasTruncated: false }\n : extractBindingKeyValues(data, bindingKeyField, bindingKeyLimit)\n\n // Calculate count based on total unique values (before truncation)\n const count = error\n ? 0\n : countUnique\n ? extracted.totalCount\n : data.length\n\n // Calculate conversion metrics\n const { conversionRate, cumulativeConversionRate } = calculateStepMetrics(\n count,\n previousCount,\n firstStepCount || count // Use current count as first step count if this is step 0\n )\n\n return {\n stepIndex,\n stepName: step.name,\n stepId: step.id,\n data,\n bindingKeyValues: extracted.values,\n bindingKeyTotalCount: extracted.totalCount,\n count,\n conversionRate,\n cumulativeConversionRate,\n executionTime,\n error,\n }\n}\n\n/**\n * Convert step results to chart-ready data format\n */\nexport function buildFunnelChartData(\n stepResults: FunnelStepResult[]\n): FunnelChartData[] {\n if (stepResults.length === 0) return []\n\n const firstStepCount = stepResults[0]?.count || 0\n\n return stepResults.map((result, index) => ({\n name: result.stepName,\n value: result.count,\n percentage: firstStepCount > 0 ? (result.count / firstStepCount) * 100 : 0,\n conversionRate: result.conversionRate,\n stepIndex: index,\n }))\n}\n\n/**\n * Build the complete funnel execution result\n */\nexport function buildFunnelResult(\n config: FunnelConfig,\n stepResults: FunnelStepResult[],\n status: FunnelExecutionResult['status'],\n error: Error | null = null,\n currentStepIndex: number | null = null\n): FunnelExecutionResult {\n const firstStepCount = stepResults[0]?.count || 0\n const lastStepCount = stepResults[stepResults.length - 1]?.count || 0\n const totalExecutionTime = stepResults.reduce((sum, r) => sum + r.executionTime, 0)\n\n return {\n config,\n steps: stepResults,\n summary: {\n totalEntries: firstStepCount,\n totalCompletions: lastStepCount,\n overallConversionRate: firstStepCount > 0 ? lastStepCount / firstStepCount : 0,\n totalExecutionTime,\n },\n chartData: buildFunnelChartData(stepResults),\n status,\n error,\n currentStepIndex,\n }\n}\n\n/**\n * Create an empty/initial funnel result\n */\nexport function createEmptyFunnelResult(\n config: FunnelConfig\n): FunnelExecutionResult {\n return {\n config,\n steps: [],\n summary: {\n totalEntries: 0,\n totalCompletions: 0,\n overallConversionRate: 0,\n totalExecutionTime: 0,\n },\n chartData: [],\n status: 'idle',\n error: null,\n currentStepIndex: null,\n }\n}\n\n/**\n * Build a FunnelConfig from multi-query config state.\n * Used to convert AnalysisBuilder state to funnel configuration.\n *\n * @param queries - Array of CubeQuery objects (one per step)\n * @param bindingKey - The binding key configuration\n * @param stepLabels - Optional labels for each step\n * @param stepTimeToConvert - Optional time window for each step\n * @returns FunnelConfig ready for execution\n */\nexport function buildFunnelConfigFromQueries(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey,\n stepLabels?: string[],\n stepTimeToConvert?: (string | null)[]\n): FunnelConfig {\n const steps: FunnelStep[] = queries.map((query, index) => ({\n id: `step-${index}`,\n name: stepLabels?.[index] || `Step ${index + 1}`,\n query,\n timeToConvert: stepTimeToConvert?.[index] || undefined,\n }))\n\n return {\n id: `funnel-${Date.now()}`,\n name: 'Funnel Analysis',\n bindingKey,\n steps,\n countUnique: true,\n }\n}\n\n/**\n * Check if funnel execution should stop early\n * (e.g., when no binding key values remain)\n */\nexport function shouldStopFunnelExecution(\n stepResult: FunnelStepResult\n): boolean {\n return stepResult.bindingKeyValues.length === 0 || stepResult.error !== null\n}\n\n/**\n * Metadata fields injected into funnel result data\n * (for compatibility with existing chart/table components)\n */\nexport interface FunnelMetadata {\n __stepIndex: number\n __stepName: string\n __stepId: string\n __conversionRate: number | null\n __cumulativeRate: number\n}\n\n/**\n * Check if data contains funnel metadata\n */\nexport function isFunnelData(data: unknown[]): boolean {\n return (\n data.length > 0 &&\n typeof data[0] === 'object' &&\n data[0] !== null &&\n '__stepIndex' in data[0]\n )\n}\n","/**\n * useFunnelQuery - Hook for sequential funnel query execution\n *\n * Unlike useMultiCubeLoadQuery which executes queries in parallel,\n * this hook executes queries sequentially where each step filters\n * based on binding key values from the previous step's results.\n *\n * Features:\n * - Sequential execution with binding key propagation\n * - Progressive loading (shows results as each step completes)\n * - Built-in debouncing\n * - Per-step error tracking\n * - Conversion rate calculation\n */\n\nimport { useState, useCallback, useRef, useEffect, useMemo } from 'react'\nimport { useCubeApi } from '../../providers/CubeApiProvider'\nimport { cleanQueryForServer } from '../../shared/utils'\nimport { useDebounceQuery } from '../useDebounceQuery'\nimport type { CubeQuery, CubeResultSet } from '../../types'\nimport type {\n FunnelConfig,\n FunnelStepResult,\n FunnelExecutionResult,\n FunnelChartData,\n UseFunnelQueryOptions,\n UseFunnelQueryResult,\n} from '../../types/funnel'\nimport {\n getBindingKeyField,\n extractBindingKeyValues,\n buildStepQuery,\n buildStepResult,\n buildFunnelResult,\n buildFunnelChartData,\n shouldStopFunnelExecution,\n DEFAULT_BINDING_KEY_LIMIT,\n} from '../../utils/funnelExecution'\n\n// Default debounce delay in milliseconds\nconst DEFAULT_DEBOUNCE_MS = 300\n\n/**\n * Check if a FunnelConfig is valid for execution\n */\nfunction isValidFunnelConfig(config: FunnelConfig | null): boolean {\n if (!config) return false\n if (!config.bindingKey) return false\n if (!config.steps || config.steps.length < 2) return false\n\n // Check that binding key dimension is defined\n if (typeof config.bindingKey.dimension === 'string') {\n if (!config.bindingKey.dimension) return false\n } else if (Array.isArray(config.bindingKey.dimension)) {\n if (config.bindingKey.dimension.length === 0) return false\n }\n\n // Check that each step has a valid query\n for (const step of config.steps) {\n const query = step.query\n const hasFields =\n (query.measures && query.measures.length > 0) ||\n (query.dimensions && query.dimensions.length > 0) ||\n (query.timeDimensions && query.timeDimensions.length > 0)\n if (!hasFields) return false\n }\n\n return true\n}\n\n/**\n * Hook for sequential funnel query execution\n *\n * Usage:\n * ```tsx\n * const { result, isExecuting, execute, stepResults, chartData } = useFunnelQuery(config, {\n * debounceMs: 300,\n * skip: !hasBindingKey\n * })\n *\n * // Results show progressively as each step completes\n * {stepResults.map((step, i) => (\n * <div key={i}>\n * {step.stepName}: {step.count} ({step.conversionRate}% from previous)\n * </div>\n * ))}\n * ```\n */\nexport function useFunnelQuery(\n config: FunnelConfig | null,\n options: UseFunnelQueryOptions = {}\n): UseFunnelQueryResult {\n const {\n skip = false,\n debounceMs = DEFAULT_DEBOUNCE_MS,\n onStepComplete,\n onComplete,\n onError,\n } = options\n\n const { cubeApi } = useCubeApi()\n\n // Validate config\n const isValidConfig = isValidFunnelConfig(config)\n\n // Use shared debounce hook\n const { debouncedValue: debouncedConfig, isDebouncing } = useDebounceQuery(config, {\n isValid: isValidConfig,\n skip,\n debounceMs,\n })\n\n // State\n const [result, setResult] = useState<FunnelExecutionResult | null>(null)\n const [stepResults, setStepResults] = useState<FunnelStepResult[]>([])\n const [status, setStatus] = useState<FunnelExecutionResult['status']>('idle')\n const [currentStepIndex, setCurrentStepIndex] = useState<number | null>(null)\n const [error, setError] = useState<Error | null>(null)\n // Track the actually executed queries (with binding key dimension and IN filters)\n const [executedQueries, setExecutedQueries] = useState<CubeQuery[]>([])\n\n // Ref to track execution cancellation\n const executionIdRef = useRef<number>(0)\n const abortControllerRef = useRef<AbortController | null>(null)\n\n // Reset state when config changes significantly\n useEffect(() => {\n if (!debouncedConfig) {\n setResult(null)\n setStepResults([])\n setStatus('idle')\n setCurrentStepIndex(null)\n setError(null)\n }\n }, [debouncedConfig])\n\n /**\n * Execute the funnel query sequentially\n */\n const execute = useCallback(async (): Promise<FunnelExecutionResult | null> => {\n if (!debouncedConfig || !isValidConfig) {\n return null\n }\n\n // Cancel any previous execution\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n }\n\n // Create new execution context\n const executionId = ++executionIdRef.current\n abortControllerRef.current = new AbortController()\n\n // Reset state for new execution\n setStatus('executing')\n setError(null)\n setStepResults([])\n setCurrentStepIndex(0)\n setExecutedQueries([])\n\n const config = debouncedConfig\n const countUnique = config.countUnique !== false\n const bindingKeyLimit = config.bindingKeyLimit ?? DEFAULT_BINDING_KEY_LIMIT\n const accumulatedResults: FunnelStepResult[] = []\n const accumulatedQueries: CubeQuery[] = []\n let currentBindingKeyValues: (string | number)[] = []\n let firstStepCount = 0\n let executionError: Error | null = null\n\n try {\n for (let i = 0; i < config.steps.length; i++) {\n // Check if execution was cancelled\n if (executionIdRef.current !== executionId) {\n return null\n }\n\n const step = config.steps[i]\n setCurrentStepIndex(i)\n\n // Build query with binding key filter\n const stepQuery = buildStepQuery(\n step,\n config.bindingKey,\n i === 0 ? null : currentBindingKeyValues\n )\n\n // Clean query for server\n const serverQuery = cleanQueryForServer(stepQuery)\n\n // Execute step query\n const startTime = performance.now()\n let resultSet: CubeResultSet\n let stepError: Error | null = null\n let data: unknown[] = []\n\n try {\n resultSet = await cubeApi.load(serverQuery)\n data = resultSet.rawData()\n } catch (err) {\n stepError = err instanceof Error ? err : new Error(String(err))\n onError?.(stepError, i)\n }\n\n const executionTime = performance.now() - startTime\n\n // Get binding key field for this step\n const bindingKeyField = getBindingKeyField(config.bindingKey, stepQuery)\n\n // Extract binding key values for next step (with limit applied)\n if (!stepError) {\n const extracted = extractBindingKeyValues(data, bindingKeyField, bindingKeyLimit)\n currentBindingKeyValues = extracted.values\n }\n\n // Track first step count (uses total count before limiting)\n if (i === 0 && !stepError) {\n const extracted = extractBindingKeyValues(data, bindingKeyField, 0) // No limit for counting\n firstStepCount = countUnique\n ? extracted.totalCount\n : data.length\n }\n\n // Build step result (includes limit for binding key extraction)\n const previousCount = i === 0 ? null : accumulatedResults[i - 1]?.count || 0\n const stepResult = buildStepResult(\n step,\n i,\n data,\n bindingKeyField,\n countUnique,\n previousCount,\n firstStepCount,\n executionTime,\n stepError,\n bindingKeyLimit\n )\n\n accumulatedResults.push(stepResult)\n accumulatedQueries.push(stepQuery)\n\n // Update state progressively\n setStepResults([...accumulatedResults])\n setExecutedQueries([...accumulatedQueries])\n\n // Callback for step completion\n onStepComplete?.(stepResult)\n\n // Check if we should stop execution\n if (shouldStopFunnelExecution(stepResult)) {\n if (stepResult.error) {\n executionError = stepResult.error\n }\n break\n }\n }\n } catch (err) {\n executionError = err instanceof Error ? err : new Error(String(err))\n }\n\n // Check if execution was cancelled\n if (executionIdRef.current !== executionId) {\n return null\n }\n\n // Build final result\n const finalStatus: FunnelExecutionResult['status'] = executionError\n ? 'error'\n : accumulatedResults.length < config.steps.length\n ? 'partial'\n : 'success'\n\n const finalResult = buildFunnelResult(\n config,\n accumulatedResults,\n finalStatus,\n executionError,\n null\n )\n\n setResult(finalResult)\n setStatus(finalStatus)\n setCurrentStepIndex(null)\n setError(executionError)\n\n // Callback for completion\n onComplete?.(finalResult)\n\n return finalResult\n }, [debouncedConfig, isValidConfig, cubeApi, onStepComplete, onComplete, onError])\n\n /**\n * Cancel current execution\n */\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n abortControllerRef.current = null\n }\n executionIdRef.current++\n setStatus('idle')\n setCurrentStepIndex(null)\n }, [])\n\n /**\n * Reset to initial state\n */\n const reset = useCallback(() => {\n cancel()\n setResult(null)\n setStepResults([])\n setError(null)\n }, [cancel])\n\n // Auto-execute when debounced config changes (if not skipped)\n useEffect(() => {\n if (debouncedConfig && !skip && isValidConfig) {\n execute()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedConfig, skip, isValidConfig])\n\n // Compute step loading states\n const stepLoadingStates = useMemo(() => {\n if (!debouncedConfig) return []\n return debouncedConfig.steps.map((_, i) => {\n if (status !== 'executing') return false\n return currentStepIndex !== null && i >= currentStepIndex\n })\n }, [debouncedConfig, status, currentStepIndex])\n\n // Compute chart data from step results\n const chartData: FunnelChartData[] = useMemo(() => {\n return buildFunnelChartData(stepResults)\n }, [stepResults])\n\n return {\n result,\n status,\n isExecuting: status === 'executing',\n isDebouncing,\n currentStepIndex,\n stepLoadingStates,\n stepResults,\n chartData,\n error,\n execute,\n cancel,\n reset,\n // Expose the actually executed queries (with binding key dimension + IN filters)\n // for debug/inspection purposes\n executedQueries,\n }\n}\n\n/**\n * Create a stable query key for funnel queries\n * (useful if we want to integrate with TanStack Query in the future)\n */\nexport function createFunnelQueryKey(\n config: FunnelConfig | null\n): readonly unknown[] {\n if (!config) return ['cube', 'funnel', null] as const\n // Create a stable key based on config\n return ['cube', 'funnel', JSON.stringify(config)] as const\n}\n","import React, { Component, ReactNode } from 'react'\nimport { getIcon } from '../icons'\n\nconst RefreshIcon = getIcon('refresh')\n\ninterface Props {\n children: ReactNode\n fallback?: ReactNode\n portletTitle?: string\n portletConfig?: any\n cubeQuery?: string\n}\n\ninterface State {\n hasError: boolean\n error: Error | null\n errorInfo: string | null\n}\n\nexport default class ChartErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props)\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null\n }\n }\n\n static getDerivedStateFromError(error: Error): State {\n // Update state so the next render will show the fallback UI\n return {\n hasError: true,\n error,\n errorInfo: null\n }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n // Update state with error details\n this.setState({\n error,\n errorInfo: errorInfo.componentStack || null\n })\n\n // Log the error for debugging\n console.error('Chart Error Boundary caught a rendering error:', error, errorInfo)\n }\n\n handleReset = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null\n })\n }\n\n render() {\n if (this.state.hasError) {\n // Custom fallback UI\n if (this.props.fallback) {\n return this.props.fallback\n }\n\n // Default error display\n return (\n <div className=\"flex flex-col items-center justify-center w-full h-full p-6 text-center border border-dashed rounded-lg\"\n style={{ borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}>\n <div className=\"h-12 w-12 mb-4 text-dc-text-muted\">⚠️</div>\n <h3 className=\"text-lg font-semibold mb-2 text-dc-text\">\n {this.props.portletTitle ? `Unable to render ${this.props.portletTitle}` : 'Unable to render chart'}\n </h3>\n <p className=\"text-sm text-dc-text-secondary mb-4 max-w-md\">\n There was an error rendering this chart component. The error details are shown below.\n </p>\n\n {/* Error details */}\n <div className=\"w-full max-w-2xl mb-4\">\n <div className=\"bg-dc-surface-secondary rounded-lg p-3 text-left\">\n <div className=\"text-xs font-mono mb-2 text-dc-text\">\n <strong>Error:</strong> {this.state.error?.message}\n </div>\n {this.state.error?.name && (\n <div className=\"text-xs font-mono text-dc-text-secondary mb-2\">\n <strong>Type:</strong> {this.state.error.name}\n </div>\n )}\n\n {/* Portlet Config Debug Info */}\n {this.props.portletConfig && (\n <details className=\"text-xs font-mono text-dc-text-secondary mb-2\">\n <summary className=\"cursor-pointer\">Portlet Configuration</summary>\n <pre className=\"mt-2 whitespace-pre-wrap p-2 rounded-sm overflow-auto max-h-32\"\n style={{ backgroundColor: 'rgba(var(--dc-primary-rgb), 0.1)' }}>\n {JSON.stringify(this.props.portletConfig, null, 2)}\n </pre>\n </details>\n )}\n\n {/* Cube Query Debug Info */}\n {this.props.cubeQuery && (\n <details className=\"text-xs font-mono text-dc-text-secondary mb-2\">\n <summary className=\"cursor-pointer\">Cube Query</summary>\n <pre className=\"mt-2 whitespace-pre-wrap p-2 rounded-sm overflow-auto max-h-32\"\n style={{ backgroundColor: '#d1fae5' }}>\n {typeof this.props.cubeQuery === 'string' \n ? JSON.stringify(JSON.parse(this.props.cubeQuery), null, 2)\n : JSON.stringify(this.props.cubeQuery, null, 2)\n }\n </pre>\n </details>\n )}\n\n {this.state.errorInfo && (\n <details className=\"text-xs font-mono text-dc-text-secondary\">\n <summary className=\"cursor-pointer\">Component Stack</summary>\n <pre className=\"mt-2 whitespace-pre-wrap\">{this.state.errorInfo}</pre>\n </details>\n )}\n </div>\n </div>\n\n {/* Reset button */}\n <button\n onClick={this.handleReset}\n className=\"px-3 py-1 text-white rounded-sm text-sm hover:opacity-90 transition-opacity\"\n style={{\n backgroundColor: 'var(--dc-primary)'\n }}\n >\n <RefreshIcon style={{ width: '16px', height: '16px', display: 'inline', marginRight: '4px' }} />Try Again\n </button>\n </div>\n )\n }\n\n return this.props.children\n }\n}","/**\n * Type definitions for drizzle-cube client components\n */\n\nimport type { ReactNode } from 'react'\nimport type { ColorPalette } from './utils/colorPalettes'\n\n// Cube metadata types\nexport interface CubeMetaField {\n name: string\n title: string\n shortTitle: string\n type: string\n}\n\nexport interface CubeMetaRelationship {\n targetCube: string\n relationship: 'belongsTo' | 'hasOne' | 'hasMany'\n joinFields: Array<{\n sourceField: string\n targetField: string\n }>\n}\n\nexport interface CubeMetaCube {\n name: string\n title: string\n description?: string\n measures: CubeMetaField[]\n dimensions: CubeMetaField[]\n segments: CubeMetaField[]\n relationships?: CubeMetaRelationship[]\n}\n\nexport interface CubeMeta {\n cubes: CubeMetaCube[]\n}\n\nexport type FieldLabelMap = Record<string, string>\n\n// Re-export color palette types\nexport type { ColorPalette } from './utils/colorPalettes'\n\n// Chart types\nexport type ChartType =\n | 'line'\n | 'bar'\n | 'pie'\n | 'table'\n | 'area'\n | 'scatter'\n | 'radar'\n | 'radialBar'\n | 'treemap'\n | 'bubble'\n | 'activityGrid'\n | 'kpiNumber'\n | 'kpiDelta'\n | 'kpiText'\n | 'markdown'\n | 'funnel'\n\n// Axis formatting configuration\nexport interface AxisFormatConfig {\n label?: string // Custom axis label (overrides auto-generated)\n unit?: 'currency' | 'percent' | 'number' | 'custom' // Unit type for formatting\n abbreviate?: boolean // Use K, M, B suffixes for large numbers\n decimals?: number // Decimal places (0-4, undefined = auto)\n customPrefix?: string // Prefix for 'custom' unit type\n customSuffix?: string // Suffix for 'custom' unit type\n}\n\n// Chart configuration\nexport interface ChartAxisConfig {\n // New format (for advanced portlet editor)\n xAxis?: string[] // Dimension fields for X axis\n yAxis?: string[] // Measure fields for Y axis \n series?: string[] // Fields to use for series/grouping\n \n // Bubble chart specific fields\n sizeField?: string // Field for bubble size\n colorField?: string // Field for bubble color\n \n // Activity grid chart specific fields\n dateField?: string[] // Time dimension field for activity grid\n valueField?: string[] // Measure field for activity intensity\n \n // Legacy format (for backward compatibility)\n x?: string // Single dimension field for X axis\n y?: string[] // Measure fields for Y axis\n\n // Dual Y-axis support: per-measure axis assignment (left or right)\n // Default: 'left' for all measures (backward compatible)\n yAxisAssignment?: Record<string, 'left' | 'right'>\n}\n\nexport interface ChartDisplayConfig {\n showLegend?: boolean\n showGrid?: boolean\n showTooltip?: boolean\n colors?: string[]\n orientation?: 'horizontal' | 'vertical'\n stacked?: boolean // Deprecated: use stackType instead\n stackType?: 'none' | 'normal' | 'percent' // Stacking mode: none, normal (sum), or percent (100%)\n connectNulls?: boolean // For Area/Line charts: draw continuous lines through missing data\n hideHeader?: boolean // Hide portlet header in non-edit mode\n \n // Bubble chart specific display options\n minBubbleSize?: number\n maxBubbleSize?: number\n bubbleOpacity?: number\n \n // Activity grid specific display options\n showLabels?: boolean\n fitToWidth?: boolean\n\n // DataTable specific display options\n pivotTimeDimension?: boolean // Pivot time dimension as columns (default: true when time dimension present)\n\n // Target functionality\n target?: string // Target values as string (single value or comma-separated for spread)\n \n // KPI specific display options\n template?: string // JavaScript template string for KPI Text\n prefix?: string // Text prefix for KPI Number\n suffix?: string // Text suffix for KPI Number\n decimals?: number // Number of decimal places\n formatValue?: (value: number | null | undefined) => string // Custom value formatter function (takes precedence over prefix/suffix/decimals)\n valueColor?: string // Color for the KPI value (legacy)\n valueColorIndex?: number // Index of color from dashboard palette for KPI value\n \n // KPI Delta specific display options\n positiveColorIndex?: number // Index of color from dashboard palette for positive changes\n negativeColorIndex?: number // Index of color from dashboard palette for negative changes\n showHistogram?: boolean // Whether to show variance histogram\n\n // KPI time period handling\n useLastCompletePeriod?: boolean // Exclude incomplete current period (e.g., partial week/month)\n skipLastPeriod?: boolean // Always exclude the last period regardless of completeness\n \n // Markdown specific display options\n content?: string // Markdown content text\n accentColorIndex?: number // Index of color from dashboard palette for headers, bullets, links\n fontSize?: 'small' | 'medium' | 'large' // Text size for markdown content\n alignment?: 'left' | 'center' | 'right' // Text alignment for markdown content\n\n // Axis formatting options (for Line, Area, Bar, Scatter charts)\n xAxisFormat?: AxisFormatConfig // Formatting for X-axis values\n leftYAxisFormat?: AxisFormatConfig // Formatting for left Y-axis values\n rightYAxisFormat?: AxisFormatConfig // Formatting for right Y-axis values (dual-axis charts)\n\n // Period comparison display options (for compareDateRange queries)\n /**\n * How to display compared periods:\n * - 'separate': Each period as distinct series with different colors (default)\n * - 'overlay': Periods aligned by day-of-period index with ghost styling for prior periods\n */\n comparisonMode?: 'separate' | 'overlay'\n /** Line style for prior periods in overlay mode */\n priorPeriodStyle?: 'solid' | 'dashed' | 'dotted'\n /** Opacity for prior period lines (0-1), default: 0.5 */\n priorPeriodOpacity?: number\n /** Include period labels in legend */\n showPeriodLabels?: boolean\n\n // Funnel chart specific display options\n /** Custom labels for funnel steps (array indexed by step, e.g., [\"Signup\", \"Activation\", \"Purchase\"]) */\n funnelStepLabels?: string[]\n /** Hide the summary footer in funnel charts */\n hideSummaryFooter?: boolean\n /** Funnel orientation: horizontal (bars left to right) or vertical (bars bottom to top) */\n funnelOrientation?: 'horizontal' | 'vertical'\n}\n\n// Portlet configuration\nexport interface PortletConfig {\n id: string\n title: string\n query: string // JSON string of cube query\n chartType: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n dashboardFilterMapping?: string[] // Array of dashboard filter IDs that apply to this portlet\n eagerLoad?: boolean // Force immediate loading (overrides dashboard lazy loading setting)\n w: number // Grid width\n h: number // Grid height\n x: number // Grid x position\n y: number // Grid y position\n}\n\nexport type DashboardLayoutMode = 'grid' | 'rows'\n\nexport interface DashboardGridSettings {\n cols: number\n rowHeight: number\n minW: number\n minH: number\n}\n\nexport interface RowLayoutColumn {\n portletId: string\n w: number\n}\n\nexport interface RowLayout {\n id: string\n h: number\n columns: RowLayoutColumn[]\n}\n\n// Dashboard configuration\nexport interface DashboardConfig {\n portlets: PortletConfig[]\n layoutMode?: DashboardLayoutMode\n grid?: DashboardGridSettings\n rows?: RowLayout[]\n layouts?: { [key: string]: any } // react-grid-layout layouts\n colorPalette?: string // Name of the color palette to use (defaults to 'default')\n filters?: DashboardFilter[] // Dashboard-level filters that can be applied to portlets\n eagerLoad?: boolean // Force immediate loading for all portlets (default: false, lazy load enabled)\n}\n\n// Filter types - hierarchical structure supporting AND/OR logic\nexport type FilterOperator = \n // String operators\n | 'equals' | 'notEquals' | 'contains' | 'notContains' \n | 'startsWith' | 'notStartsWith' | 'endsWith' | 'notEndsWith'\n | 'like' | 'notLike' | 'ilike'\n // Numeric operators \n | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'notBetween'\n // Array operators\n | 'in' | 'notIn'\n // PostgreSQL array operators\n | 'arrayContains' | 'arrayOverlaps' | 'arrayContained'\n // Null/Empty operators\n | 'set' | 'notSet' | 'isEmpty' | 'isNotEmpty'\n // Date operators\n | 'inDateRange' | 'beforeDate' | 'afterDate'\n // Regex operators\n | 'regex' | 'notRegex'\n\nexport interface SimpleFilter {\n member: string\n operator: FilterOperator\n values: any[]\n dateRange?: string | string[]\n}\n\nexport interface GroupFilter {\n type: 'and' | 'or'\n filters: Filter[]\n}\n\nexport type Filter = SimpleFilter | GroupFilter\n\n// Dashboard filter with ID and label for dashboard-level filtering\nexport interface DashboardFilter {\n id: string // Unique identifier for the filter\n label: string // Display label for the filter\n filter: Filter // The actual filter definition\n isUniversalTime?: boolean // When true, applies to all timeDimensions in portlets (ignores member field)\n}\n\n// Cube query types\nexport interface CubeQuery {\n measures?: string[]\n dimensions?: string[]\n timeDimensions?: Array<{\n dimension: string\n granularity?: string\n dateRange?: string[] | string\n fillMissingDates?: boolean\n /**\n * Array of date ranges for period-over-period comparison.\n * When specified, queries are executed for each period and results are merged.\n */\n compareDateRange?: (string | [string, string])[]\n }>\n filters?: Filter[]\n order?: { [key: string]: 'asc' | 'desc' }\n limit?: number\n offset?: number\n segments?: string[]\n}\n\n/**\n * Merge strategy for combining multiple query results\n * - 'concat': Append rows with __queryIndex marker (for separate series per query)\n * - 'merge': Align data by common dimension key (for combined visualization)\n * - 'funnel': Execute queries sequentially, filtering each step by binding key from previous step\n */\nexport type QueryMergeStrategy = 'concat' | 'merge' | 'funnel'\n\n/**\n * Configuration for multi-query portlets\n * Detected by presence of 'queries' array property\n */\nexport interface MultiQueryConfig {\n queries: CubeQuery[]\n mergeStrategy: QueryMergeStrategy\n mergeKeys?: string[] // Dimensions to align on (for 'merge' strategy) - composite key\n queryLabels?: string[] // User-defined labels per query\n}\n\n/**\n * Type guard to detect multi-query configuration\n */\nexport function isMultiQueryConfig(obj: unknown): obj is MultiQueryConfig {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'queries' in obj &&\n Array.isArray((obj as MultiQueryConfig).queries) &&\n (obj as MultiQueryConfig).queries.length > 0\n )\n}\n\nexport interface CubeQueryOptions {\n skip?: boolean\n resetResultSetOnChange?: boolean\n subscribe?: boolean\n}\n\nexport interface CubeApiOptions {\n apiUrl?: string\n token?: string\n headers?: Record<string, string>\n credentials?: 'include' | 'omit' | 'same-origin'\n}\n\n// Result set types\nexport interface CubeResultSet {\n rawData(): any[]\n tablePivot(): any[]\n series(): any[]\n annotation(): any\n loadResponse?: any\n cacheInfo?(): { hit: true; cachedAt: string; ttlMs: number; ttlRemainingMs: number } | undefined\n}\n\n// Component props\nexport interface AnalyticsPortletProps {\n query: string\n chartType: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n dashboardFilters?: DashboardFilter[] // Dashboard-level filters to merge with portlet query\n dashboardFilterMapping?: string[] // Array of dashboard filter IDs that apply to this portlet\n eagerLoad?: boolean // Force immediate loading (default: false, lazy load enabled)\n isVisible?: boolean // Whether the portlet is visible in the viewport (for lazy loading)\n height?: string | number\n title?: string\n colorPalette?: ColorPalette // Complete palette with both colors and gradient\n loadingComponent?: ReactNode // Custom loading indicator (defaults to LoadingIndicator)\n onDebugDataReady?: (debugData: {\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n queryObject: any\n data: any[]\n chartType: ChartType\n cacheInfo?: { hit: true; cachedAt: string; ttlMs: number; ttlRemainingMs: number }\n }) => void\n}\n\nexport interface AnalyticsDashboardProps {\n config: DashboardConfig\n editable?: boolean\n dashboardFilters?: DashboardFilter[] // Programmatic dashboard filters (merged with config.filters)\n loadingComponent?: ReactNode // Custom loading indicator for all portlets (defaults to LoadingIndicator)\n onConfigChange?: (config: DashboardConfig) => void\n onSave?: (config: DashboardConfig) => Promise<void> | void\n onDirtyStateChange?: (isDirty: boolean) => void\n}\n\nexport interface ChartProps {\n data: any[]\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n queryObject?: CubeQuery\n height?: string | number\n colorPalette?: ColorPalette // Complete palette with both colors and gradient\n}\n\n// Features configuration\nexport interface FeaturesConfig {\n enableAI?: boolean // Default: true for backward compatibility\n aiEndpoint?: string // Custom AI endpoint (default: '/api/ai/generate')\n showSchemaDiagram?: boolean // Deprecated - schema diagram feature has been removed\n useAnalysisBuilder?: boolean // Deprecated - AnalysisBuilder modal is now always used (PortletEditModal was removed)\n editToolbar?: 'floating' | 'top' | 'both' // Which edit toolbar(s) to show: 'floating' only, 'top' only, or 'both' (default: 'both')\n floatingToolbarPosition?: 'left' | 'right' // Position of floating toolbar when enabled (default: 'right')\n}\n\n// Grid layout types (simplified)\nexport interface GridLayout {\n i: string\n x: number\n y: number\n w: number\n h: number\n minW?: number\n minH?: number\n}\n\nexport interface ResponsiveLayout {\n [breakpoint: string]: GridLayout[]\n}\n\n// Dashboard display modes for responsive layout\nexport type DashboardDisplayMode = 'desktop' | 'scaled' | 'mobile'\n\n// Re-export funnel types\nexport type {\n FunnelBindingKey,\n FunnelBindingKeyMapping,\n FunnelStep,\n FunnelConfig,\n FunnelStepResult,\n FunnelExecutionResult,\n FunnelChartData,\n FunnelValidationError,\n FunnelValidationResult,\n UseFunnelQueryOptions,\n UseFunnelQueryResult,\n} from './types/funnel'\n\nexport { isFunnelMergeStrategy } from './types/funnel'\n","/**\n * Filter utility functions for dashboard-level filtering\n *\n * NOTE: These are pure functions without internal caching.\n * Memoization should be handled at the component level using useMemo.\n */\n\nimport type { Filter, DashboardFilter, CubeMeta, GroupFilter, DashboardConfig, SimpleFilter } from '../types'\n\n/**\n * Check if a filter should be included in the query (has valid values or doesn't require values)\n * @param filter - The filter to check\n * @returns true if the filter should be included, false otherwise\n */\nfunction shouldIncludeFilter(filter: Filter): boolean {\n // Handle SimpleFilter\n if ('member' in filter && 'operator' in filter) {\n const simpleFilter = filter as SimpleFilter\n\n // Operators that don't require values\n const noValueOperators = ['set', 'notSet', 'isEmpty', 'isNotEmpty']\n if (noValueOperators.includes(simpleFilter.operator)) {\n return true\n }\n\n // For inDateRange, check if dateRange is provided as alternative to values\n if (simpleFilter.operator === 'inDateRange' && simpleFilter.dateRange) {\n return true\n }\n\n // For other operators, check if values exist and are non-empty\n return !!(simpleFilter.values && simpleFilter.values.length > 0)\n }\n\n // Handle GroupFilter - recursively check nested filters\n if ('type' in filter && 'filters' in filter) {\n const groupFilter = filter as GroupFilter\n // Include group filter if at least one nested filter is valid\n const validFilters = groupFilter.filters.filter(f => shouldIncludeFilter(f))\n return validFilters.length > 0\n }\n\n return false\n}\n\n/**\n * Get dashboard filters that should be applied to a portlet based on its mapping configuration\n *\n * @param dashboardFilters - All available dashboard filters\n * @param filterMapping - Array of filter IDs that apply to this portlet\n * @returns Array of filters that should be applied to the portlet\n */\nexport function getApplicableDashboardFilters(\n dashboardFilters: DashboardFilter[] | undefined,\n filterMapping: string[] | undefined\n): Filter[] {\n if (!dashboardFilters || !dashboardFilters.length) {\n return []\n }\n\n // If no mapping is specified, no dashboard filters apply\n if (!filterMapping || !filterMapping.length) {\n return []\n }\n\n // Compute filters that are in the mapping AND have valid values\n return dashboardFilters\n .filter(df => filterMapping.includes(df.id))\n .filter(df => shouldIncludeFilter(df.filter))\n .map(df => df.filter)\n}\n\n/**\n * Convert GroupFilter format to server format\n * GroupFilter: { type: 'and', filters: [...] }\n * Server format: { and: [...] } or { or: [...] }\n */\nfunction convertToServerFormat(filter: Filter): any {\n // Handle GroupFilter format\n if ('type' in filter && 'filters' in filter) {\n const groupFilter = filter as GroupFilter\n const convertedFilters = groupFilter.filters.map(convertToServerFormat)\n\n if (groupFilter.type === 'and') {\n return { and: convertedFilters }\n } else {\n return { or: convertedFilters }\n }\n }\n\n // Simple filter - return as-is\n return filter\n}\n\n/**\n * Filter format for merge operation:\n * - 'server': Returns {and: [...]} or {or: [...]} format (for API queries)\n * - 'client': Returns {type: 'and', filters: [...]} format (for UI components)\n */\nexport type FilterFormat = 'server' | 'client'\n\n/**\n * Merge dashboard filters with portlet filters using AND logic\n * Dashboard filters are combined with portlet filters so both sets of filters apply\n *\n * @param dashboardFilters - Filters from dashboard-level configuration\n * @param portletFilters - Filters from portlet query\n * @param format - Output format: 'server' for API queries, 'client' for UI (default: 'server')\n * @returns Merged filter array with AND logic in the specified format\n */\nexport function mergeDashboardAndPortletFilters(\n dashboardFilters: Filter[],\n portletFilters: Filter[] | undefined,\n format: FilterFormat = 'server'\n): Filter[] | undefined {\n // If no dashboard filters, return portlet filters as-is\n if (!dashboardFilters || dashboardFilters.length === 0) {\n return portletFilters\n }\n\n // If no portlet filters, return dashboard filters\n if (!portletFilters || portletFilters.length === 0) {\n return [...dashboardFilters]\n }\n\n // Both exist - need to merge with AND logic\n if (format === 'server') {\n // Server format: convert to {and: [...]} structure\n const allFilters = [...dashboardFilters, ...portletFilters].map(convertToServerFormat)\n return [{\n and: allFilters\n } as any]\n } else {\n // Client format: use {type: 'and', filters: [...]} structure\n const allFilters = [...dashboardFilters, ...portletFilters]\n return [{\n type: 'and',\n filters: allFilters\n } as GroupFilter]\n }\n}\n\n/**\n * @deprecated Use mergeDashboardAndPortletFilters(filters, portletFilters, 'client') instead\n */\nexport function mergeDashboardAndPortletFiltersClientFormat(\n dashboardFilters: Filter[],\n portletFilters: Filter[] | undefined\n): Filter[] | undefined {\n return mergeDashboardAndPortletFilters(dashboardFilters, portletFilters, 'client')\n}\n\n/**\n * Check if a filter field exists in the cube metadata\n * This helps identify filters that might not apply to a specific portlet's data\n * @param filter - The filter to validate\n * @param cubeMeta - Cube metadata to validate against\n * @returns true if the filter field exists in any cube's measures or dimensions\n */\nexport function validateFilterForCube(\n filter: Filter,\n cubeMeta: CubeMeta | null\n): boolean {\n if (!cubeMeta || !cubeMeta.cubes) {\n // If no metadata available, assume filter is valid (fail open)\n return true\n }\n\n // Extract member names from filter recursively\n const memberNames = extractMemberNamesFromFilter(filter)\n\n // Check if any of the member names exist in cube metadata\n return memberNames.some(memberName => {\n return cubeMeta.cubes.some(cube => {\n // Check measures\n const inMeasures = cube.measures?.some(m => m.name === memberName) ?? false\n // Check dimensions\n const inDimensions = cube.dimensions?.some(d => d.name === memberName) ?? false\n\n return inMeasures || inDimensions\n })\n })\n}\n\n/**\n * Extract all member names from a filter (handles nested group filters)\n * @param filter - The filter to extract members from\n * @returns Array of member names\n */\nfunction extractMemberNamesFromFilter(filter: Filter): string[] {\n if ('member' in filter) {\n // SimpleFilter\n return [filter.member]\n } else if ('type' in filter && 'filters' in filter) {\n // GroupFilter - recursively extract from nested filters\n return filter.filters.flatMap(f => extractMemberNamesFromFilter(f))\n }\n\n return []\n}\n\n/**\n * Validate that all dashboard filters in a portlet's mapping exist and are valid\n * @param dashboardFilters - All available dashboard filters\n * @param filterMapping - The portlet's filter mapping\n * @param cubeMeta - Cube metadata for validation\n * @returns Object with validation result and list of invalid filter IDs\n */\nexport function validatePortletFilterMapping(\n dashboardFilters: DashboardFilter[] | undefined,\n filterMapping: string[] | undefined,\n cubeMeta: CubeMeta | null\n): { isValid: boolean; invalidFilterIds: string[]; missingFilterIds: string[] } {\n if (!filterMapping || !filterMapping.length) {\n return { isValid: true, invalidFilterIds: [], missingFilterIds: [] }\n }\n\n if (!dashboardFilters || !dashboardFilters.length) {\n // Mapping references filters that don't exist\n return {\n isValid: false,\n invalidFilterIds: [],\n missingFilterIds: filterMapping\n }\n }\n\n const invalidFilterIds: string[] = []\n const missingFilterIds: string[] = []\n\n filterMapping.forEach(filterId => {\n const dashboardFilter = dashboardFilters.find(df => df.id === filterId)\n\n if (!dashboardFilter) {\n // Filter ID in mapping doesn't exist in dashboard filters\n missingFilterIds.push(filterId)\n } else {\n // Check if filter is valid for the cube metadata\n const isValid = validateFilterForCube(dashboardFilter.filter, cubeMeta)\n if (!isValid) {\n invalidFilterIds.push(filterId)\n }\n }\n })\n\n return {\n isValid: invalidFilterIds.length === 0 && missingFilterIds.length === 0,\n invalidFilterIds,\n missingFilterIds\n }\n}\n\n/**\n * Extract all unique measures, dimensions, and timeDimensions used across all portlets in a dashboard\n * This helps create a filtered schema view showing only fields relevant to the dashboard\n * @param dashboardConfig - Dashboard configuration\n * @returns Object with unique measures, dimensions, and timeDimensions\n */\nexport function extractDashboardFields(\n dashboardConfig: DashboardConfig\n): { measures: Set<string>; dimensions: Set<string>; timeDimensions: Set<string> } {\n const measures = new Set<string>()\n const dimensions = new Set<string>()\n const timeDimensions = new Set<string>()\n\n // Iterate through all portlets\n dashboardConfig.portlets.forEach(portlet => {\n try {\n // Parse the query JSON\n const query = JSON.parse(portlet.query)\n\n // Extract measures\n if (query.measures && Array.isArray(query.measures)) {\n query.measures.forEach((measure: string) => measures.add(measure))\n }\n\n // Extract dimensions\n if (query.dimensions && Array.isArray(query.dimensions)) {\n query.dimensions.forEach((dimension: string) => dimensions.add(dimension))\n }\n\n // Extract timeDimensions\n if (query.timeDimensions && Array.isArray(query.timeDimensions)) {\n query.timeDimensions.forEach((td: any) => {\n if (td.dimension) {\n timeDimensions.add(td.dimension)\n }\n })\n }\n\n // Also extract from filters to catch any filtered fields\n if (query.filters) {\n extractFieldsFromFilters(query.filters).forEach(field => {\n // Try to determine if it's a measure, dimension, or timeDimension\n // by checking cube metadata or convention (add to dimensions by default)\n dimensions.add(field)\n })\n }\n } catch (e) {\n // Skip portlets with invalid query JSON\n console.warn('Failed to parse portlet query:', portlet.id, e)\n }\n })\n\n return { measures, dimensions, timeDimensions }\n}\n\n/**\n * Extract field names from filters recursively\n * @param filters - Filter array\n * @returns Array of unique field names\n */\nfunction extractFieldsFromFilters(filters: Filter[]): string[] {\n const fields: string[] = []\n\n filters.forEach(filter => {\n if ('member' in filter) {\n // SimpleFilter\n fields.push(filter.member)\n } else if ('type' in filter && 'filters' in filter) {\n // GroupFilter - recurse\n fields.push(...extractFieldsFromFilters(filter.filters))\n }\n })\n\n return [...new Set(fields)] // Return unique fields\n}\n\n/**\n * Time dimension type from CubeQuery\n */\ntype TimeDimension = {\n dimension: string\n granularity?: string\n dateRange?: string[] | string\n}\n\n/**\n * Helper to get date range from a SimpleFilter (backward compatible)\n * Reads from both dateRange and values for compatibility\n * Handles both:\n * - Preset ranges: [\"this quarter\"], [\"last 7 days\"] (single string value)\n * - Custom ranges: [\"2024-01-01\", \"2024-12-31\"] (two date values)\n */\nfunction getDateRangeFromFilter(filter: SimpleFilter): string[] | string | undefined {\n // Prefer dateRange for backward compatibility, fall back to values\n if (filter.dateRange) {\n return filter.dateRange\n }\n if (filter.values && filter.values.length > 0) {\n // Single value = preset like \"this quarter\", return as string\n // Multiple values = custom date range, return as array\n return filter.values.length === 1 ? filter.values[0] : filter.values\n }\n return undefined\n}\n\n/**\n * Apply universal time filters to a portlet's timeDimensions\n * Universal time filters apply their dateRange to ALL time dimensions in the portlet\n *\n * @param dashboardFilters - All dashboard filters\n * @param filterMapping - Filter IDs that apply to this portlet\n * @param portletTimeDimensions - The portlet's existing timeDimensions array\n * @returns Updated timeDimensions array with date ranges applied\n */\nexport function applyUniversalTimeFilters(\n dashboardFilters: DashboardFilter[] | undefined,\n filterMapping: string[] | undefined,\n portletTimeDimensions: TimeDimension[] | undefined\n): TimeDimension[] | undefined {\n // Return as-is if no time dimensions in portlet (skip silently)\n if (!portletTimeDimensions || portletTimeDimensions.length === 0) {\n return portletTimeDimensions\n }\n\n // If no mapping specified, no filters apply\n if (!filterMapping || filterMapping.length === 0) {\n return portletTimeDimensions\n }\n\n // Find applicable universal time filters that have valid date ranges\n const universalTimeFilters = dashboardFilters\n ?.filter(df => df.isUniversalTime && filterMapping.includes(df.id))\n ?.filter(df => {\n // Must be a SimpleFilter with a valid dateRange\n if (!('member' in df.filter)) return false\n const simpleFilter = df.filter as SimpleFilter\n const dateRange = getDateRangeFromFilter(simpleFilter)\n return dateRange !== undefined\n })\n\n if (!universalTimeFilters || universalTimeFilters.length === 0) {\n return portletTimeDimensions\n }\n\n // Use the first universal time filter's dateRange (typically only one)\n const timeFilter = universalTimeFilters[0]\n const simpleFilter = timeFilter.filter as SimpleFilter\n const dateRange = getDateRangeFromFilter(simpleFilter)\n\n // Apply dateRange to ALL time dimensions (dashboard wins - overrides portlet dateRange)\n return portletTimeDimensions.map(td => ({\n ...td,\n dateRange: dateRange\n }))\n}\n","/**\n * Analytics Portlet Component\n * Simplified version with minimal dependencies\n */\n\nimport React, { useMemo, useCallback, forwardRef, useImperativeHandle, useEffect, useRef } from 'react'\nimport { useInView } from 'react-intersection-observer'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useCubeLoadQuery, useMultiCubeLoadQuery, createQueryKey, createMultiQueryKey } from '../hooks/queries'\nimport { useScrollContainer } from '../providers/ScrollContainerContext'\nimport ChartErrorBoundary from './ChartErrorBoundary'\nimport LoadingIndicator from './LoadingIndicator'\nimport { LazyChart, isValidChartType } from '../charts/ChartLoader'\nimport { useChartConfig } from '../charts/lazyChartConfigRegistry'\nimport type { AnalyticsPortletProps, MultiQueryConfig } from '../types'\nimport { isMultiQueryConfig } from '../types'\nimport { getApplicableDashboardFilters, mergeDashboardAndPortletFilters, applyUniversalTimeFilters } from '../utils/filterUtils'\nimport { cleanQueryForServer } from '../shared/utils'\n\n\ninterface AnalyticsPortletRef {\n refresh: () => void\n}\n\n// Memoize component to prevent re-renders when props haven't changed\nconst AnalyticsPortlet = React.memo(forwardRef<AnalyticsPortletRef, AnalyticsPortletProps>(({\n query,\n chartType,\n chartConfig,\n displayConfig,\n dashboardFilters,\n dashboardFilterMapping,\n eagerLoad = false,\n isVisible: _isVisible, // Deprecated - visibility now handled internally via useInView\n height = 300,\n title: _title,\n colorPalette,\n loadingComponent,\n onDebugDataReady\n}, ref) => {\n const onDebugDataReadyRef = useRef(onDebugDataReady)\n\n // Lazy loading: Use IntersectionObserver to detect when portlet is visible\n // Get scroll container from context (null = viewport, element = container scroll)\n const scrollContainer = useScrollContainer()\n const { ref: inViewRef, inView } = useInView({\n root: scrollContainer,\n rootMargin: '500px', // Start loading 500px before entering viewport (about half screen)\n triggerOnce: true, // Once visible, stay \"visible\" (don't unload data)\n initialInView: false, // Start as not visible, let observer determine actual state\n skip: eagerLoad // Skip observation entirely if eagerLoad is true\n })\n\n // Effective visibility: eagerLoad forces visible, otherwise use inView from IntersectionObserver\n // Note: Batching is handled by BatchCoordinator which collects queries for 100ms before flushing\n const isVisible = eagerLoad || inView\n\n // Update ref when callback changes\n useEffect(() => {\n onDebugDataReadyRef.current = onDebugDataReady\n }, [onDebugDataReady])\n\n // Check if this chart type skips queries (using lazy-loaded config)\n const { config: chartTypeConfig } = useChartConfig(chartType)\n const shouldSkipQuery = chartTypeConfig.skipQuery === true\n\n // Memoize regular filters to prevent array recreation on every render\n const regularFilters = useMemo(() => {\n return dashboardFilters?.filter(df => !df.isUniversalTime)\n }, [dashboardFilters])\n\n // Parse query from JSON string, merge dashboard filters, and include refresh counter to force re-query\n // Supports both single CubeQuery and MultiQueryConfig formats\n const { queryObject, multiQueryConfig } = useMemo(() => {\n // Skip query parsing for charts that don't need queries\n if (shouldSkipQuery) {\n return { queryObject: null, multiQueryConfig: null }\n }\n\n try {\n const parsed = JSON.parse(query)\n\n // Get applicable dashboard filters (excluding universal time filters - they apply to timeDimensions)\n const applicableFilters = getApplicableDashboardFilters(regularFilters, dashboardFilterMapping)\n\n // Check if this is a multi-query configuration\n if (isMultiQueryConfig(parsed)) {\n // Multi-query: apply filters to each query in the array\n const multiConfig: MultiQueryConfig = {\n ...parsed,\n queries: parsed.queries.map(q => ({\n ...q,\n filters: mergeDashboardAndPortletFilters(applicableFilters, q.filters),\n timeDimensions: applyUniversalTimeFilters(dashboardFilters, dashboardFilterMapping, q.timeDimensions)\n }))\n }\n return { queryObject: null, multiQueryConfig: multiConfig }\n }\n\n // Single query: existing behavior\n const mergedFilters = mergeDashboardAndPortletFilters(applicableFilters, parsed.filters)\n const mergedTimeDimensions = applyUniversalTimeFilters(\n dashboardFilters,\n dashboardFilterMapping,\n parsed.timeDimensions\n )\n\n return {\n queryObject: {\n ...parsed,\n filters: mergedFilters,\n timeDimensions: mergedTimeDimensions\n },\n multiQueryConfig: null\n }\n } catch (e) {\n console.error('AnalyticsPortlet: Invalid query JSON:', e)\n return { queryObject: null, multiQueryConfig: null }\n }\n }, [query, shouldSkipQuery, regularFilters, dashboardFilters, dashboardFilterMapping])\n\n // Determine whether to skip queries based on various conditions\n const isMultiQuery = multiQueryConfig !== null\n const shouldSkipSingle = !queryObject || shouldSkipQuery || (!eagerLoad && !isVisible) || isMultiQuery\n const shouldSkipMulti = !multiQueryConfig || shouldSkipQuery || (!eagerLoad && !isVisible)\n\n // Query client for cache invalidation\n const queryClient = useQueryClient()\n\n // Use single query hook with TanStack Query (skip if multi-query or other skip conditions)\n const singleQueryResult = useCubeLoadQuery(queryObject, {\n skip: shouldSkipSingle,\n resetResultSetOnChange: true,\n debounceMs: 100, // Lower debounce for portlets (faster response)\n })\n\n // Use multi-query hook with TanStack Query (skip if single query or other skip conditions)\n const multiQueryResult = useMultiCubeLoadQuery(multiQueryConfig, {\n skip: shouldSkipMulti,\n resetResultSetOnChange: true,\n debounceMs: 100, // Lower debounce for portlets (faster response)\n })\n\n // Combine results from both hooks\n const resultSet = isMultiQuery ? null : singleQueryResult.resultSet\n const isLoading = isMultiQuery ? multiQueryResult.isLoading : singleQueryResult.isLoading\n const isFetching = isMultiQuery ? multiQueryResult.isFetching : singleQueryResult.isFetching\n const error = isMultiQuery ? multiQueryResult.error : singleQueryResult.error\n const multiQueryData = isMultiQuery ? multiQueryResult.data : null\n\n // Expose refresh function through ref\n // Invalidates cache and forces a fresh fetch from the server\n useImperativeHandle(ref, () => ({\n refresh: () => {\n if (isMultiQuery && multiQueryConfig) {\n // Invalidate cache for this specific multi-query, then refetch\n // Clean each query to match the cache key format used by useMultiCubeLoadQuery\n const cleanedConfig = {\n ...multiQueryConfig,\n queries: multiQueryConfig.queries.map(q => cleanQueryForServer(q))\n }\n queryClient.invalidateQueries({ queryKey: createMultiQueryKey(cleanedConfig) })\n } else if (queryObject) {\n // Clean the query to match the cache key format used by useCubeLoadQuery\n // This is important because the cache uses cleanQueryForServer(query) which removes empty arrays\n const cleanedQuery = cleanQueryForServer(queryObject)\n queryClient.invalidateQueries({ queryKey: createQueryKey(cleanedQuery) })\n }\n }\n }), [isMultiQuery, multiQueryConfig, queryObject, queryClient])\n\n const handleRetry = useCallback(() => {\n if (isMultiQuery) {\n multiQueryResult.refetch()\n } else {\n singleQueryResult.refetch()\n }\n }, [isMultiQuery, multiQueryResult, singleQueryResult])\n\n\n // Send debug data to parent when ready (must be before any returns)\n useEffect(() => {\n if (onDebugDataReadyRef.current && chartConfig && queryObject && resultSet && !error) {\n const getData = () => {\n switch (chartType) {\n case 'pie':\n case 'table':\n return resultSet.tablePivot()\n default:\n return resultSet.rawData()\n }\n }\n const data = getData()\n\n if (data) {\n onDebugDataReadyRef.current({\n chartConfig: chartConfig || {},\n displayConfig: displayConfig || {},\n queryObject,\n data,\n chartType,\n cacheInfo: resultSet.cacheInfo?.()\n })\n }\n }\n }, [chartConfig, displayConfig, queryObject, resultSet, chartType, error]) // Use ref for callback to prevent infinite loops\n\n // Validate that chartConfig is provided when required (not required for skipQuery charts)\n // Check if any dropZones are mandatory for this chart type\n const hasMandatoryFields = !shouldSkipQuery && chartTypeConfig.dropZones.some(zone => zone.mandatory === true)\n \n if (!chartConfig && hasMandatoryFields) {\n return (\n <div ref={inViewRef} 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\">Configuration Required</div>\n <div className=\"text-xs text-dc-text-secondary\">Please configure this chart</div>\n </div>\n </div>\n )\n }\n\n // Show placeholder for lazy-loaded portlets that aren't visible yet\n if (!shouldSkipQuery && !eagerLoad && !isVisible) {\n return (\n <div ref={inViewRef} className=\"w-full h-full\" style={{ height }}>\n <div className=\"w-full h-full animate-pulse bg-dc-surface-secondary rounded\" style={{ minHeight: '100px' }} />\n </div>\n )\n }\n\n // Skip loading and error handling for charts that don't need queries\n if (!shouldSkipQuery) {\n // Show loading indicator during initial load OR during refresh (isFetching)\n if (isLoading || isFetching || (queryObject && !resultSet && !error)) {\n return (\n <div ref={inViewRef} className=\"flex items-center justify-center w-full\" style={{ height }}>\n {loadingComponent || <LoadingIndicator size=\"md\" />}\n </div>\n )\n }\n\n if (error) {\n return (\n <div ref={inViewRef} className=\"p-4 border rounded-sm\" style={{ height, borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}>\n <div className=\"mb-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-medium text-sm\" style={{ color: 'var(--dc-text)' }}>⚠️ Query Error</span>\n <button\n onClick={handleRetry}\n className=\"px-2 py-1 text-white rounded-sm text-xs\"\n style={{ backgroundColor: 'var(--dc-primary)' }}\n >\n Retry\n </button>\n </div>\n </div>\n\n <div className=\"mb-3\">\n <div className=\"text-xs p-2 rounded-sm border\" style={{ color: 'var(--dc-text-secondary)', backgroundColor: 'var(--dc-surface)', borderColor: 'var(--dc-border)' }}>\n {error.message || error.toString()}\n </div>\n </div>\n\n <div className=\"space-y-2 text-xs\">\n <details>\n <summary className=\"cursor-pointer font-medium\" style={{ color: 'var(--dc-text-secondary)' }}>Query (with filters applied)</summary>\n <pre className=\"mt-1 p-2 rounded-sm text-xs overflow-auto max-h-20\" style={{ backgroundColor: 'rgba(var(--dc-primary-rgb), 0.1)' }}>\n {queryObject ? JSON.stringify(queryObject, null, 2) : query}\n </pre>\n </details>\n\n <details>\n <summary className=\"cursor-pointer font-medium\" style={{ color: 'var(--dc-text-secondary)' }}>Chart Config</summary>\n <pre className=\"mt-1 p-2 rounded-sm text-xs overflow-auto max-h-20\" style={{ backgroundColor: 'rgba(var(--dc-primary-rgb), 0.05)' }}>\n {JSON.stringify({\n chartType,\n chartConfig,\n displayConfig: displayConfig\n }, null, 2)}\n </pre>\n </details>\n </div>\n </div>\n )\n }\n\n // Check for valid data based on query type\n const hasValidData = isMultiQuery\n ? (multiQueryData !== null && multiQueryConfig !== null)\n : (resultSet !== null && queryObject !== null)\n\n if (!hasValidData) {\n return (\n <div ref={inViewRef} 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\">Invalid query or no results</div>\n </div>\n </div>\n )\n }\n }\n\n // Get data based on chart type needs\n const getData = () => {\n // Return empty array for charts that don't use query data\n if (shouldSkipQuery) {\n return []\n }\n\n // Multi-query: return merged data directly\n if (isMultiQuery) {\n return multiQueryData || []\n }\n\n // Single query: return empty array if no resultSet\n if (!resultSet) {\n return []\n }\n\n switch (chartType) {\n case 'pie':\n case 'table':\n return resultSet.tablePivot()\n default:\n return resultSet.rawData()\n }\n }\n\n const data = getData()\n\n // Render appropriate chart component using lazy loading\n // Each chart type is dynamically imported for code splitting\n const renderChart = () => {\n try {\n const chartHeight = height\n\n // Handle unsupported chart types\n if (!isValidChartType(chartType)) {\n return (\n <div className=\"flex items-center justify-center w-full\" style={{ height }}>\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">Unsupported chart type</div>\n <div className=\"text-xs\">{chartType}</div>\n </div>\n </div>\n )\n }\n\n // For markdown chart, use empty data array\n const chartData = chartType === 'markdown' ? [] : data\n\n return (\n <LazyChart\n chartType={chartType}\n data={chartData}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n queryObject={queryObject ?? undefined}\n height={chartHeight}\n colorPalette={colorPalette}\n fallback={\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height: typeof chartHeight === 'number' ? `${chartHeight}px` : chartHeight }}\n >\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full min-h-[100px]\" />\n </div>\n }\n />\n )\n } catch (error) {\n console.error('Chart rendering error:', error)\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted p-4\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Unable to render chart</div>\n <div className=\"text-xs text-dc-text-secondary\">{error instanceof Error ? error.message : 'Unknown error'}</div>\n </div>\n </div>\n )\n }\n }\n\n return (\n <div ref={inViewRef} className=\"w-full h-full\">\n <ChartErrorBoundary\n portletTitle={_title}\n portletConfig={{\n chartType,\n chartConfig,\n displayConfig,\n height\n }}\n cubeQuery={query}\n >\n <div className=\"w-full h-full flex flex-col flex-1\" style={{ minHeight: '200px' }}>\n {renderChart()}\n </div>\n </ChartErrorBoundary>\n </div>\n )\n}))\n\nAnalyticsPortlet.displayName = 'AnalyticsPortlet'\n\nexport default AnalyticsPortlet\n","/**\n * useScrollDetection - Debounced Scroll Detection Hook\n *\n * Detects when a container has been scrolled past a threshold with debouncing\n * to prevent excessive state updates.\n *\n * This fixes the issue where scroll detection was listening to window.pageYOffset\n * instead of the actual scroll container (overflow-y-auto div in Layout).\n */\n\nimport { useEffect, useState, useRef, type RefObject } from 'react'\n\ninterface UseScrollDetectionOptions {\n /** Scroll threshold in pixels (default: 20) */\n threshold?: number\n /** Debounce delay in milliseconds (default: 150) */\n debounceMs?: number\n /** Optional container state to trigger re-initialization when found */\n container?: HTMLElement | null\n}\n\n/**\n * Hook to detect scroll position in a container\n *\n * @param containerRef - Ref to the scrollable container element\n * @param options - Configuration options for threshold and debounce\n * @returns Boolean indicating if scrolled past threshold\n *\n * @example\n * const scrollContainerRef = useRef<HTMLDivElement>(null)\n * const isScrolled = useScrollDetection(scrollContainerRef, {\n * threshold: 20,\n * debounceMs: 150\n * })\n *\n * <div ref={scrollContainerRef} className=\"overflow-y-auto\">\n * {isScrolled && <div>Shadow visible</div>}\n * </div>\n */\nexport function useScrollDetection(\n containerRef: RefObject<HTMLElement | null>,\n { threshold = 20, debounceMs = 150, container }: UseScrollDetectionOptions = {}\n) {\n const [isScrolled, setIsScrolled] = useState(false)\n const timeoutRef = useRef<number>()\n\n useEffect(() => {\n // Note: containerRef is intentionally not in deps - refs are stable and we access .current inside\n const scrollContainer = containerRef.current\n if (!scrollContainer) return\n\n const handleScroll = () => {\n // Clear existing timeout\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n\n // Debounce scroll updates\n timeoutRef.current = window.setTimeout(() => {\n const scrollTop = scrollContainer.scrollTop\n const shouldBeScrolled = scrollTop > threshold\n\n // Only update state if value actually changed\n setIsScrolled(prev => prev !== shouldBeScrolled ? shouldBeScrolled : prev)\n }, debounceMs)\n }\n\n // Attach scroll listener to actual container (not window!)\n scrollContainer.addEventListener('scroll', handleScroll, { passive: true })\n\n // Initial check\n handleScroll()\n\n // Cleanup\n return () => {\n scrollContainer.removeEventListener('scroll', handleScroll)\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [threshold, debounceMs, container]) // containerRef is stable, container triggers re-init\n\n return isScrolled\n}\n","/**\n * useElementVisibility - Detects when an element scrolls out of view\n *\n * Used to detect when the static edit bar scrolls out of view, triggering\n * the floating toolbar to appear. Works with both viewport and custom\n * scroll containers.\n */\n\nimport { useEffect, useState, useRef, type RefObject } from 'react'\n\ninterface UseElementVisibilityOptions {\n /** Threshold in pixels - element considered out of view when this much scrolls past top */\n threshold?: number\n /** Debounce delay in milliseconds */\n debounceMs?: number\n /** Custom scroll container ref (uses viewport if not provided) */\n containerRef?: RefObject<HTMLElement | null>\n /** Optional state value to trigger re-initialization when container is found */\n container?: HTMLElement | null\n}\n\n/**\n * Hook to detect whether an element is visible in the viewport/container\n *\n * @param elementRef - Ref to the element to track\n * @param options - Configuration options\n * @returns Boolean indicating if the element is visible (true when in view, false when scrolled out)\n *\n * @example\n * const editBarRef = useRef<HTMLDivElement>(null)\n * const isEditBarVisible = useElementVisibility(editBarRef, {\n * threshold: 80,\n * containerRef: scrollContainerRef\n * })\n *\n * // Show floating toolbar when edit bar scrolls out of view\n * {!isEditBarVisible && <FloatingToolbar />}\n */\nexport function useElementVisibility(\n elementRef: RefObject<HTMLElement | null>,\n { threshold = 80, debounceMs = 100, containerRef, container }: UseElementVisibilityOptions = {}\n): boolean {\n // Start with visible=true to prevent flash on initial render\n const [isVisible, setIsVisible] = useState(true)\n const timeoutRef = useRef<number>()\n // Track if we've ever seen the element visible (prevents animation on load)\n const hasBeenVisibleRef = useRef(false)\n\n useEffect(() => {\n const container = containerRef?.current\n\n const checkVisibility = () => {\n const element = elementRef.current\n // If element not yet mounted, stay visible (don't show floating toolbar)\n if (!element) return\n\n // Clear existing timeout for debouncing\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n\n timeoutRef.current = window.setTimeout(() => {\n const elementRect = element.getBoundingClientRect()\n\n if (container) {\n // Check against scroll container\n const containerRect = container.getBoundingClientRect()\n // Element is \"visible\" when its bottom is below the container's top by at least threshold\n const visible = elementRect.bottom > containerRect.top + threshold\n\n // Track that we've seen the element visible at least once\n if (visible) {\n hasBeenVisibleRef.current = true\n }\n\n // Only update state if value changed\n setIsVisible(prev => prev !== visible ? visible : prev)\n } else {\n // Check against viewport (window)\n // Element is \"visible\" when its bottom is in the viewport (plus threshold buffer)\n const visible = elementRect.bottom > threshold\n\n // Track that we've seen the element visible at least once\n if (visible) {\n hasBeenVisibleRef.current = true\n }\n\n // Only update state if value changed\n setIsVisible(prev => prev !== visible ? visible : prev)\n }\n }, debounceMs)\n }\n\n // Attach scroll listener to container or window\n const scrollTarget = container || window\n scrollTarget.addEventListener('scroll', checkVisibility, { passive: true })\n\n // Also listen for resize events\n window.addEventListener('resize', checkVisibility, { passive: true })\n\n // Initial check\n checkVisibility()\n\n // Deferred re-check after React render cycle completes\n // This handles the case where elementRef.current isn't set yet on first render\n const rafId = requestAnimationFrame(() => {\n checkVisibility()\n })\n\n // Cleanup\n return () => {\n scrollTarget.removeEventListener('scroll', checkVisibility)\n window.removeEventListener('resize', checkVisibility)\n cancelAnimationFrame(rafId)\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n }\n }, [elementRef, containerRef, threshold, debounceMs, container])\n\n return isVisible\n}\n","/**\n * Syntax Highlighting Utility\n *\n * Lazy-loads highlight.js only when needed for syntax highlighting in debug panels.\n * This minimizes bundle size impact since syntax highlighting is not needed on initial load.\n *\n * Usage:\n * await highlightCodeBlocks()\n */\n\nlet highlightJs: any = null\nlet loadingPromise: Promise<void> | null = null\n\n/**\n * Lazy-loads highlight.js and registers supported languages.\n * Only loads once - subsequent calls return immediately.\n */\nexport async function loadSyntaxHighlighter(): Promise<void> {\n // Already loaded\n if (highlightJs) {\n return\n }\n\n // Loading in progress - wait for it\n if (loadingPromise) {\n return loadingPromise\n }\n\n loadingPromise = (async () => {\n try {\n // Dynamic imports to enable code splitting\n const hljs = await import('highlight.js/lib/core')\n const javascript = await import('highlight.js/lib/languages/javascript')\n const sql = await import('highlight.js/lib/languages/sql')\n const json = await import('highlight.js/lib/languages/json')\n\n // Register languages we need\n hljs.default.registerLanguage('javascript', javascript.default)\n hljs.default.registerLanguage('sql', sql.default)\n hljs.default.registerLanguage('json', json.default)\n\n // Store the instance\n highlightJs = hljs.default\n } catch (err) {\n console.error('Failed to load syntax highlighter:', err)\n // Clear loading promise so it can be retried\n loadingPromise = null\n }\n })()\n\n return loadingPromise\n}\n\n/**\n * Highlights all code blocks on the page that haven't been highlighted yet.\n * Gracefully handles cases where highlight.js fails to load.\n */\nexport async function highlightCodeBlocks(): Promise<void> {\n // Load highlighter if not already loaded\n await loadSyntaxHighlighter()\n\n // If loading failed, return silently (code blocks remain unstyled)\n if (!highlightJs) {\n return\n }\n\n // Find all code blocks and highlight them\n document.querySelectorAll('pre code').forEach((block) => {\n // Skip if already highlighted\n if (!block.classList.contains('hljs')) {\n highlightJs.highlightElement(block)\n }\n })\n}\n\n/**\n * Highlights a specific code block element.\n * Useful for dynamically added content.\n *\n * @param element - The code block element to highlight\n */\nexport async function highlightCodeBlock(element: HTMLElement): Promise<void> {\n await loadSyntaxHighlighter()\n\n if (!highlightJs) {\n return\n }\n\n if (!element.classList.contains('hljs')) {\n highlightJs.highlightElement(element)\n }\n}\n\n/**\n * Returns whether syntax highlighting is available.\n * Useful for conditional rendering or feature detection.\n */\nexport function isSyntaxHighlightingAvailable(): boolean {\n return highlightJs !== null\n}\n","import { useState, useEffect } from 'react'\nimport { highlightCodeBlocks } from '../utils/syntaxHighlighting'\n\ninterface DebugModalProps {\n chartConfig: any\n displayConfig: any\n queryObject: any\n data: any[]\n chartType: string\n cacheInfo?: { hit: true; cachedAt: string; ttlMs: number; ttlRemainingMs: number }\n}\n\nexport default function DebugModal({\n chartConfig,\n displayConfig,\n queryObject,\n data,\n chartType,\n cacheInfo\n}: DebugModalProps) {\n const [isOpen, setIsOpen] = useState(false)\n\n // Handle ESC key to close modal\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && isOpen) {\n setIsOpen(false)\n }\n }\n\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen])\n\n // Trigger syntax highlighting when modal opens and content is rendered\n useEffect(() => {\n if (isOpen) {\n // Small delay to ensure DOM is updated\n const timer = setTimeout(() => {\n highlightCodeBlocks().catch((err) => {\n console.debug('Syntax highlighting not available:', err)\n })\n }, 10)\n\n return () => clearTimeout(timer)\n }\n }, [isOpen])\n\n\n if (!isOpen) {\n return (\n <button\n onClick={() => setIsOpen(true)}\n className=\"p-1 text-dc-text-muted hover:text-dc-text-secondary transition-colors\"\n title=\"Debug chart configuration\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n </button>\n )\n }\n\n return (\n <div\n className=\"absolute inset-0 bg-dc-surface border border-dc-border rounded-lg z-50 overflow-auto\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"p-4 h-full flex flex-col\">\n <div className=\"flex justify-between items-center mb-4 shrink-0\">\n <h2 className=\"text-lg font-semibold text-dc-text\">Chart Debug Information</h2>\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 text-dc-text-muted hover:text-dc-text-secondary hover:bg-dc-surface-secondary rounded-sm\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4 flex-1 overflow-auto\">\n <div>\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Chart Type</h3>\n <div className=\"bg-dc-surface-secondary p-2 rounded-sm text-sm font-mono border border-dc-border\">\n {chartType}\n </div>\n </div>\n\n <div>\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Field Analysis</h3>\n <div className=\"bg-dc-surface-secondary p-2 rounded-sm text-xs space-y-1 border border-dc-border\">\n <div>\n <strong>xAxis:</strong> {Array.isArray(chartConfig?.xAxis) ? `Array: [${chartConfig.xAxis.join(', ')}]` : `String: \"${chartConfig?.xAxis}\"`}\n </div>\n <div>\n <strong>yAxis:</strong> {Array.isArray(chartConfig?.yAxis) ? `Array: [${chartConfig.yAxis.join(', ')}]` : `String: \"${chartConfig?.yAxis}\"`}\n </div>\n <div>\n <strong>series:</strong> {Array.isArray(chartConfig?.series) ? `Array: [${chartConfig.series.join(', ')}]` : `String: \"${chartConfig?.series}\"`}\n </div>\n {chartConfig?.sizeField && (\n <div>\n <strong>sizeField:</strong> {Array.isArray(chartConfig?.sizeField) ? `Array: [${chartConfig.sizeField.join(', ')}]` : `String: \"${chartConfig?.sizeField}\"`}\n </div>\n )}\n {chartConfig?.colorField && (\n <div>\n <strong>colorField:</strong> {Array.isArray(chartConfig?.colorField) ? `Array: [${chartConfig.colorField.join(', ')}]` : `String: \"${chartConfig?.colorField}\"`}\n </div>\n )}\n </div>\n </div>\n\n <div className=\"lg:col-span-2\">\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Chart Config</h3>\n <pre className=\"text-dc-text-secondary overflow-x-auto font-mono p-2 rounded-sm border border-dc-border\" style={{ fontSize: '10px', lineHeight: '1.4' }}>\n <code className=\"language-json\">{JSON.stringify(chartConfig, null, 2)}</code>\n </pre>\n </div>\n\n <div className=\"lg:col-span-2\">\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Display Config</h3>\n <pre className=\"text-dc-text-secondary overflow-x-auto font-mono p-2 rounded-sm border border-dc-border\" style={{ fontSize: '10px', lineHeight: '1.4' }}>\n <code className=\"language-json\">{JSON.stringify(displayConfig, null, 2)}</code>\n </pre>\n </div>\n\n <div className=\"lg:col-span-2\">\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Query Object</h3>\n <pre className=\"text-dc-text-secondary overflow-x-auto font-mono p-2 rounded-sm border border-dc-border\" style={{ fontSize: '10px', lineHeight: '1.4' }}>\n <code className=\"language-json\">{JSON.stringify(queryObject, null, 2)}</code>\n </pre>\n </div>\n\n <div className=\"lg:col-span-2\">\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Data Sample (first 3 rows)</h3>\n <pre className=\"text-dc-text-secondary overflow-x-auto font-mono p-2 rounded-sm border border-dc-border\" style={{ fontSize: '10px', lineHeight: '1.4' }}>\n <code className=\"language-json\">{JSON.stringify(data?.slice(0, 3) || [], null, 2)}</code>\n </pre>\n </div>\n\n <div className=\"lg:col-span-2\">\n <h3 className=\"text-sm font-medium text-dc-text-secondary mb-2\">Cache Status</h3>\n <div className=\"bg-dc-surface-secondary p-2 rounded-sm text-xs border border-dc-border\">\n {cacheInfo ? (\n <div className=\"flex items-center gap-4 flex-wrap\">\n <span className=\"inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-dc-success-bg text-dc-success\">\n Cache Hit\n </span>\n <span><strong>Cached At:</strong> {new Date(cacheInfo.cachedAt).toLocaleString()}</span>\n <span><strong>TTL:</strong> {Math.round(cacheInfo.ttlMs / 1000)}s</span>\n <span><strong>TTL Remaining:</strong> {Math.round(cacheInfo.ttlRemainingMs / 1000)}s</span>\n </div>\n ) : (\n <div className=\"flex items-center gap-2\">\n <span className=\"inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-dc-surface text-dc-text-muted border border-dc-border\">\n Fresh Query\n </span>\n <span className=\"text-dc-text-muted\">Result not served from cache</span>\n </div>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 pt-2 border-t border-dc-border text-xs text-dc-text-muted shrink-0\">\n Press <kbd className=\"px-1 py-0.5 bg-dc-surface-secondary rounded-sm text-xs\">ESC</kbd> to close\n </div>\n </div>\n </div>\n )\n}","const createStoreImpl = (createState) => {\n let state;\n const listeners = /* @__PURE__ */ new Set();\n const setState = (partial, replace) => {\n const nextState = typeof partial === \"function\" ? partial(state) : partial;\n if (!Object.is(nextState, state)) {\n const previousState = state;\n state = (replace != null ? replace : typeof nextState !== \"object\" || nextState === null) ? nextState : Object.assign({}, state, nextState);\n listeners.forEach((listener) => listener(state, previousState));\n }\n };\n const getState = () => state;\n const getInitialState = () => initialState;\n const subscribe = (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n const api = { setState, getState, getInitialState, subscribe };\n const initialState = state = createState(setState, getState, api);\n return api;\n};\nconst createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);\n\nexport { createStore };\n","import React from 'react';\nimport { createStore } from 'zustand/vanilla';\n\nconst identity = (arg) => arg;\nfunction useStore(api, selector = identity) {\n const slice = React.useSyncExternalStore(\n api.subscribe,\n React.useCallback(() => selector(api.getState()), [api, selector]),\n React.useCallback(() => selector(api.getInitialState()), [api, selector])\n );\n React.useDebugValue(slice);\n return slice;\n}\nconst createImpl = (createState) => {\n const api = createStore(createState);\n const useBoundStore = (selector) => useStore(api, selector);\n Object.assign(useBoundStore, api);\n return useBoundStore;\n};\nconst create = ((createState) => createState ? createImpl(createState) : createImpl);\n\nexport { create, useStore };\n","const reduxImpl = (reducer, initial) => (set, _get, api) => {\n api.dispatch = (action) => {\n set((state) => reducer(state, action), false, action);\n return action;\n };\n api.dispatchFromDevtools = true;\n return { dispatch: (...args) => api.dispatch(...args), ...initial };\n};\nconst redux = reduxImpl;\n\nconst trackedConnections = /* @__PURE__ */ new Map();\nconst getTrackedConnectionState = (name) => {\n const api = trackedConnections.get(name);\n if (!api) return {};\n return Object.fromEntries(\n Object.entries(api.stores).map(([key, api2]) => [key, api2.getState()])\n );\n};\nconst extractConnectionInformation = (store, extensionConnector, options) => {\n if (store === void 0) {\n return {\n type: \"untracked\",\n connection: extensionConnector.connect(options)\n };\n }\n const existingConnection = trackedConnections.get(options.name);\n if (existingConnection) {\n return { type: \"tracked\", store, ...existingConnection };\n }\n const newConnection = {\n connection: extensionConnector.connect(options),\n stores: {}\n };\n trackedConnections.set(options.name, newConnection);\n return { type: \"tracked\", store, ...newConnection };\n};\nconst removeStoreFromTrackedConnections = (name, store) => {\n if (store === void 0) return;\n const connectionInfo = trackedConnections.get(name);\n if (!connectionInfo) return;\n delete connectionInfo.stores[store];\n if (Object.keys(connectionInfo.stores).length === 0) {\n trackedConnections.delete(name);\n }\n};\nconst findCallerName = (stack) => {\n var _a, _b;\n if (!stack) return void 0;\n const traceLines = stack.split(\"\\n\");\n const apiSetStateLineIndex = traceLines.findIndex(\n (traceLine) => traceLine.includes(\"api.setState\")\n );\n if (apiSetStateLineIndex < 0) return void 0;\n const callerLine = ((_a = traceLines[apiSetStateLineIndex + 1]) == null ? void 0 : _a.trim()) || \"\";\n return (_b = /.+ (.+) .+/.exec(callerLine)) == null ? void 0 : _b[1];\n};\nconst devtoolsImpl = (fn, devtoolsOptions = {}) => (set, get, api) => {\n const { enabled, anonymousActionType, store, ...options } = devtoolsOptions;\n let extensionConnector;\n try {\n extensionConnector = (enabled != null ? enabled : (import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") && window.__REDUX_DEVTOOLS_EXTENSION__;\n } catch (e) {\n }\n if (!extensionConnector) {\n return fn(set, get, api);\n }\n const { connection, ...connectionInformation } = extractConnectionInformation(store, extensionConnector, options);\n let isRecording = true;\n api.setState = ((state, replace, nameOrAction) => {\n const r = set(state, replace);\n if (!isRecording) return r;\n const action = nameOrAction === void 0 ? {\n type: anonymousActionType || findCallerName(new Error().stack) || \"anonymous\"\n } : typeof nameOrAction === \"string\" ? { type: nameOrAction } : nameOrAction;\n if (store === void 0) {\n connection == null ? void 0 : connection.send(action, get());\n return r;\n }\n connection == null ? void 0 : connection.send(\n {\n ...action,\n type: `${store}/${action.type}`\n },\n {\n ...getTrackedConnectionState(options.name),\n [store]: api.getState()\n }\n );\n return r;\n });\n api.devtools = {\n cleanup: () => {\n if (connection && typeof connection.unsubscribe === \"function\") {\n connection.unsubscribe();\n }\n removeStoreFromTrackedConnections(options.name, store);\n }\n };\n const setStateFromDevtools = (...a) => {\n const originalIsRecording = isRecording;\n isRecording = false;\n set(...a);\n isRecording = originalIsRecording;\n };\n const initialState = fn(api.setState, get, api);\n if (connectionInformation.type === \"untracked\") {\n connection == null ? void 0 : connection.init(initialState);\n } else {\n connectionInformation.stores[connectionInformation.store] = api;\n connection == null ? void 0 : connection.init(\n Object.fromEntries(\n Object.entries(connectionInformation.stores).map(([key, store2]) => [\n key,\n key === connectionInformation.store ? initialState : store2.getState()\n ])\n )\n );\n }\n if (api.dispatchFromDevtools && typeof api.dispatch === \"function\") {\n let didWarnAboutReservedActionType = false;\n const originalDispatch = api.dispatch;\n api.dispatch = (...args) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\" && args[0].type === \"__setState\" && !didWarnAboutReservedActionType) {\n console.warn(\n '[zustand devtools middleware] \"__setState\" action type is reserved to set state from the devtools. Avoid using it.'\n );\n didWarnAboutReservedActionType = true;\n }\n originalDispatch(...args);\n };\n }\n connection.subscribe((message) => {\n var _a;\n switch (message.type) {\n case \"ACTION\":\n if (typeof message.payload !== \"string\") {\n console.error(\n \"[zustand devtools middleware] Unsupported action format\"\n );\n return;\n }\n return parseJsonThen(\n message.payload,\n (action) => {\n if (action.type === \"__setState\") {\n if (store === void 0) {\n setStateFromDevtools(action.state);\n return;\n }\n if (Object.keys(action.state).length !== 1) {\n console.error(\n `\n [zustand devtools middleware] Unsupported __setState action format.\n When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),\n and value of this only key should be a state object. Example: { \"type\": \"__setState\", \"state\": { \"abc123Store\": { \"foo\": \"bar\" } } }\n `\n );\n }\n const stateFromDevtools = action.state[store];\n if (stateFromDevtools === void 0 || stateFromDevtools === null) {\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(stateFromDevtools)) {\n setStateFromDevtools(stateFromDevtools);\n }\n return;\n }\n if (!api.dispatchFromDevtools) return;\n if (typeof api.dispatch !== \"function\") return;\n api.dispatch(action);\n }\n );\n case \"DISPATCH\":\n switch (message.payload.type) {\n case \"RESET\":\n setStateFromDevtools(initialState);\n if (store === void 0) {\n return connection == null ? void 0 : connection.init(api.getState());\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"COMMIT\":\n if (store === void 0) {\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"ROLLBACK\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n setStateFromDevtools(state[store]);\n connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n });\n case \"JUMP_TO_STATE\":\n case \"JUMP_TO_ACTION\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(state[store])) {\n setStateFromDevtools(state[store]);\n }\n });\n case \"IMPORT_STATE\": {\n const { nextLiftedState } = message.payload;\n const lastComputedState = (_a = nextLiftedState.computedStates.slice(-1)[0]) == null ? void 0 : _a.state;\n if (!lastComputedState) return;\n if (store === void 0) {\n setStateFromDevtools(lastComputedState);\n } else {\n setStateFromDevtools(lastComputedState[store]);\n }\n connection == null ? void 0 : connection.send(\n null,\n // FIXME no-any\n nextLiftedState\n );\n return;\n }\n case \"PAUSE_RECORDING\":\n return isRecording = !isRecording;\n }\n return;\n }\n });\n return initialState;\n};\nconst devtools = devtoolsImpl;\nconst parseJsonThen = (stringified, fn) => {\n let parsed;\n try {\n parsed = JSON.parse(stringified);\n } catch (e) {\n console.error(\n \"[zustand devtools middleware] Could not parse the received json\",\n e\n );\n }\n if (parsed !== void 0) fn(parsed);\n};\n\nconst subscribeWithSelectorImpl = (fn) => (set, get, api) => {\n const origSubscribe = api.subscribe;\n api.subscribe = ((selector, optListener, options) => {\n let listener = selector;\n if (optListener) {\n const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;\n let currentSlice = selector(api.getState());\n listener = (state) => {\n const nextSlice = selector(state);\n if (!equalityFn(currentSlice, nextSlice)) {\n const previousSlice = currentSlice;\n optListener(currentSlice = nextSlice, previousSlice);\n }\n };\n if (options == null ? void 0 : options.fireImmediately) {\n optListener(currentSlice, currentSlice);\n }\n }\n return origSubscribe(listener);\n });\n const initialState = fn(set, get, api);\n return initialState;\n};\nconst subscribeWithSelector = subscribeWithSelectorImpl;\n\nfunction combine(initialState, create) {\n return (...args) => Object.assign({}, initialState, create(...args));\n}\n\nfunction createJSONStorage(getStorage, options) {\n let storage;\n try {\n storage = getStorage();\n } catch (e) {\n return;\n }\n const persistStorage = {\n getItem: (name) => {\n var _a;\n const parse = (str2) => {\n if (str2 === null) {\n return null;\n }\n return JSON.parse(str2, options == null ? void 0 : options.reviver);\n };\n const str = (_a = storage.getItem(name)) != null ? _a : null;\n if (str instanceof Promise) {\n return str.then(parse);\n }\n return parse(str);\n },\n setItem: (name, newValue) => storage.setItem(name, JSON.stringify(newValue, options == null ? void 0 : options.replacer)),\n removeItem: (name) => storage.removeItem(name)\n };\n return persistStorage;\n}\nconst toThenable = (fn) => (input) => {\n try {\n const result = fn(input);\n if (result instanceof Promise) {\n return result;\n }\n return {\n then(onFulfilled) {\n return toThenable(onFulfilled)(result);\n },\n catch(_onRejected) {\n return this;\n }\n };\n } catch (e) {\n return {\n then(_onFulfilled) {\n return this;\n },\n catch(onRejected) {\n return toThenable(onRejected)(e);\n }\n };\n }\n};\nconst persistImpl = (config, baseOptions) => (set, get, api) => {\n let options = {\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => state,\n version: 0,\n merge: (persistedState, currentState) => ({\n ...currentState,\n ...persistedState\n }),\n ...baseOptions\n };\n let hasHydrated = false;\n const hydrationListeners = /* @__PURE__ */ new Set();\n const finishHydrationListeners = /* @__PURE__ */ new Set();\n let storage = options.storage;\n if (!storage) {\n return config(\n (...args) => {\n console.warn(\n `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`\n );\n set(...args);\n },\n get,\n api\n );\n }\n const setItem = () => {\n const state = options.partialize({ ...get() });\n return storage.setItem(options.name, {\n state,\n version: options.version\n });\n };\n const savedSetState = api.setState;\n api.setState = (state, replace) => {\n savedSetState(state, replace);\n return setItem();\n };\n const configResult = config(\n (...args) => {\n set(...args);\n return setItem();\n },\n get,\n api\n );\n api.getInitialState = () => configResult;\n let stateFromStorage;\n const hydrate = () => {\n var _a, _b;\n if (!storage) return;\n hasHydrated = false;\n hydrationListeners.forEach((cb) => {\n var _a2;\n return cb((_a2 = get()) != null ? _a2 : configResult);\n });\n const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? void 0 : _b.call(options, (_a = get()) != null ? _a : configResult)) || void 0;\n return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {\n if (deserializedStorageValue) {\n if (typeof deserializedStorageValue.version === \"number\" && deserializedStorageValue.version !== options.version) {\n if (options.migrate) {\n const migration = options.migrate(\n deserializedStorageValue.state,\n deserializedStorageValue.version\n );\n if (migration instanceof Promise) {\n return migration.then((result) => [true, result]);\n }\n return [true, migration];\n }\n console.error(\n `State loaded from storage couldn't be migrated since no migrate function was provided`\n );\n } else {\n return [false, deserializedStorageValue.state];\n }\n }\n return [false, void 0];\n }).then((migrationResult) => {\n var _a2;\n const [migrated, migratedState] = migrationResult;\n stateFromStorage = options.merge(\n migratedState,\n (_a2 = get()) != null ? _a2 : configResult\n );\n set(stateFromStorage, true);\n if (migrated) {\n return setItem();\n }\n }).then(() => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0);\n stateFromStorage = get();\n hasHydrated = true;\n finishHydrationListeners.forEach((cb) => cb(stateFromStorage));\n }).catch((e) => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e);\n });\n };\n api.persist = {\n setOptions: (newOptions) => {\n options = {\n ...options,\n ...newOptions\n };\n if (newOptions.storage) {\n storage = newOptions.storage;\n }\n },\n clearStorage: () => {\n storage == null ? void 0 : storage.removeItem(options.name);\n },\n getOptions: () => options,\n rehydrate: () => hydrate(),\n hasHydrated: () => hasHydrated,\n onHydrate: (cb) => {\n hydrationListeners.add(cb);\n return () => {\n hydrationListeners.delete(cb);\n };\n },\n onFinishHydration: (cb) => {\n finishHydrationListeners.add(cb);\n return () => {\n finishHydrationListeners.delete(cb);\n };\n }\n };\n if (!options.skipHydration) {\n hydrate();\n }\n return stateFromStorage || configResult;\n};\nconst persist = persistImpl;\n\nfunction ssrSafe(config, isSSR = typeof window === \"undefined\") {\n return (set, get, api) => {\n if (!isSSR) {\n return config(set, get, api);\n }\n const ssrSet = () => {\n throw new Error(\"Cannot set state of Zustand store in SSR\");\n };\n api.setState = ssrSet;\n return config(ssrSet, get, api);\n };\n}\n\nexport { combine, createJSONStorage, devtools, persist, redux, subscribeWithSelector, ssrSafe as unstable_ssrSafe };\n","/**\n * Dashboard Zustand Store (Instance-based)\n *\n * Centralized state management for Dashboard components, consolidating:\n * - Edit mode state (isEditMode, selectedFilterId)\n * - Modal state (portlet edit, analysis, filter config)\n * - Layout state (draftRows, drag state, initialization)\n * - Debug data (per-portlet debug information)\n *\n * KEY ARCHITECTURE: Instance-based stores\n * - Each Dashboard gets its own store instance via Context\n * - No localStorage persistence (dashboard state is transient)\n * - State is per-dashboard session, not persisted\n *\n * Uses Zustand's createStore (factory) instead of create (singleton).\n * Store is provided via React Context.\n */\n\nimport { createContext, useContext, useRef, type ReactNode } from 'react'\nimport { createStore, useStore, type StoreApi } from 'zustand'\nimport { devtools, subscribeWithSelector } from 'zustand/middleware'\nimport type { LayoutItem } from 'react-grid-layout'\nimport type {\n PortletConfig,\n RowLayout,\n ChartType,\n ChartAxisConfig,\n ChartDisplayConfig,\n CubeQuery,\n} from '../types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Debug data entry for a portlet (used by chart inspector)\n */\nexport interface PortletDebugDataEntry {\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n queryObject: CubeQuery | null\n data: unknown[]\n chartType: ChartType\n cacheInfo?: {\n hit: boolean\n cachedAt: string\n ttlMs: number\n ttlRemainingMs: number\n }\n}\n\n/**\n * @deprecated Use PortletDebugDataEntry instead. Kept for backward compatibility.\n */\nexport type DebugDataEntry = PortletDebugDataEntry\n\n/**\n * Drag state for row-based layout\n */\nexport interface DragState {\n rowIndex: number\n colIndex: number\n portletId: string\n}\n\n/**\n * Complete store state interface\n */\nexport interface DashboardStoreState {\n // =========================================================================\n // Edit Mode State\n // =========================================================================\n /** Whether dashboard is in edit mode */\n isEditMode: boolean\n /** Currently selected filter ID for filter-assignment mode */\n selectedFilterId: string | null\n\n // =========================================================================\n // Modal State\n // =========================================================================\n /** Whether portlet edit modal is open */\n isPortletModalOpen: boolean\n /** Portlet being edited (null = adding new) */\n editingPortlet: PortletConfig | null\n /** Whether filter config modal is open */\n isFilterConfigModalOpen: boolean\n /** Portlet for filter configuration */\n filterConfigPortlet: PortletConfig | null\n /** Portlet ID pending delete confirmation (null = no confirmation active) */\n deleteConfirmPortletId: string | null\n\n // =========================================================================\n // Layout State\n // =========================================================================\n /** Draft row layout during drag operations (rows mode) */\n draftRows: RowLayout[] | null\n /** Whether a portlet is currently being dragged */\n isDraggingPortlet: boolean\n /** Last known layout for change detection */\n lastKnownLayout: LayoutItem[]\n /** Whether component has been initialized (prevents saves during load) */\n isInitialized: boolean\n /** Current drag state for row-based layout */\n dragState: DragState | null\n\n // =========================================================================\n // Debug Data\n // =========================================================================\n /** Debug data keyed by portlet ID (for chart inspector) */\n debugData: Record<string, DebugDataEntry>\n}\n\n/**\n * Store actions interface\n */\nexport interface DashboardStoreActions {\n // =========================================================================\n // Edit Mode Actions\n // =========================================================================\n /** Set edit mode */\n setEditMode: (isEdit: boolean) => void\n /** Toggle edit mode */\n toggleEditMode: () => void\n /** Set selected filter ID for filter selection mode */\n setSelectedFilterId: (filterId: string | null) => void\n /** Exit filter selection mode */\n exitFilterSelectionMode: () => void\n\n // =========================================================================\n // Modal Actions\n // =========================================================================\n /** Open portlet modal (optionally with a portlet to edit) */\n openPortletModal: (portlet?: PortletConfig | null) => void\n /** Close portlet modal */\n closePortletModal: () => void\n /** Open filter config modal for a portlet */\n openFilterConfigModal: (portlet: PortletConfig) => void\n /** Close filter config modal */\n closeFilterConfigModal: () => void\n /** Open delete confirmation for a portlet */\n openDeleteConfirm: (portletId: string) => void\n /** Close delete confirmation */\n closeDeleteConfirm: () => void\n\n // =========================================================================\n // Layout Actions\n // =========================================================================\n /** Set draft rows during drag operations */\n setDraftRows: (rows: RowLayout[] | null) => void\n /** Set whether a portlet is being dragged */\n setIsDraggingPortlet: (isDragging: boolean) => void\n /** Set last known layout for change detection */\n setLastKnownLayout: (layout: LayoutItem[]) => void\n /** Set whether component is initialized */\n setIsInitialized: (initialized: boolean) => void\n /** Set drag state */\n setDragState: (state: DragState | null) => void\n /** Clear drag state */\n clearDragState: () => void\n\n // =========================================================================\n // Debug Data Actions\n // =========================================================================\n /** Set debug data for a portlet */\n setDebugData: (portletId: string, data: DebugDataEntry) => void\n /** Clear debug data for a portlet (or all if no portletId) */\n clearDebugData: (portletId?: string) => void\n\n // =========================================================================\n // Utility Actions\n // =========================================================================\n /** Reset store to initial state */\n reset: () => void\n}\n\n/**\n * Combined store type\n */\nexport type DashboardStore = DashboardStoreState & DashboardStoreActions\n\n/**\n * Options for creating a store instance\n */\nexport interface CreateDashboardStoreOptions {\n /** Initial edit mode state */\n initialEditMode?: boolean\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst createDefaultState = (): DashboardStoreState => ({\n // Edit mode\n isEditMode: false,\n selectedFilterId: null,\n\n // Modal state\n isPortletModalOpen: false,\n editingPortlet: null,\n isFilterConfigModalOpen: false,\n filterConfigPortlet: null,\n deleteConfirmPortletId: null,\n\n // Layout state\n draftRows: null,\n isDraggingPortlet: false,\n lastKnownLayout: [],\n isInitialized: false,\n dragState: null,\n\n // Debug data\n debugData: {},\n})\n\n/**\n * Build initial state from options\n */\nfunction buildInitialState(options: CreateDashboardStoreOptions): DashboardStoreState {\n const defaultState = createDefaultState()\n\n return {\n ...defaultState,\n isEditMode: options.initialEditMode ?? false,\n }\n}\n\n// ============================================================================\n// Store Factory\n// ============================================================================\n\n/**\n * Create store actions\n */\nfunction createStoreActions(\n set: (\n partial:\n | Partial<DashboardStore>\n | ((state: DashboardStore) => Partial<DashboardStore>)\n ) => void,\n _get: () => DashboardStore,\n initialState: DashboardStoreState\n): DashboardStoreActions {\n return {\n // =================================================================\n // Edit Mode Actions\n // =================================================================\n\n setEditMode: (isEdit) =>\n set({\n isEditMode: isEdit,\n // Exit filter selection mode when leaving edit mode\n selectedFilterId: isEdit ? null : null,\n }),\n\n toggleEditMode: () =>\n set((state) => ({\n isEditMode: !state.isEditMode,\n // Exit filter selection mode when toggling\n selectedFilterId: null,\n })),\n\n setSelectedFilterId: (filterId) => set({ selectedFilterId: filterId }),\n\n exitFilterSelectionMode: () => set({ selectedFilterId: null }),\n\n // =================================================================\n // Modal Actions\n // =================================================================\n\n openPortletModal: (portlet) =>\n set({\n isPortletModalOpen: true,\n editingPortlet: portlet ?? null,\n }),\n\n closePortletModal: () =>\n set({\n isPortletModalOpen: false,\n editingPortlet: null,\n }),\n\n openFilterConfigModal: (portlet) =>\n set({\n isFilterConfigModalOpen: true,\n filterConfigPortlet: portlet,\n }),\n\n closeFilterConfigModal: () =>\n set({\n isFilterConfigModalOpen: false,\n filterConfigPortlet: null,\n }),\n\n openDeleteConfirm: (portletId: string) =>\n set({ deleteConfirmPortletId: portletId }),\n\n closeDeleteConfirm: () =>\n set({ deleteConfirmPortletId: null }),\n\n // =================================================================\n // Layout Actions\n // =================================================================\n\n setDraftRows: (rows) => set({ draftRows: rows }),\n\n setIsDraggingPortlet: (isDragging) => set({ isDraggingPortlet: isDragging }),\n\n setLastKnownLayout: (layout) => set({ lastKnownLayout: layout }),\n\n setIsInitialized: (initialized) => set({ isInitialized: initialized }),\n\n setDragState: (state) => set({ dragState: state }),\n\n clearDragState: () =>\n set({\n dragState: null,\n isDraggingPortlet: false,\n }),\n\n // =================================================================\n // Debug Data Actions\n // =================================================================\n\n setDebugData: (portletId, data) =>\n set((state) => ({\n debugData: {\n ...state.debugData,\n [portletId]: data,\n },\n })),\n\n clearDebugData: (portletId) =>\n set((state) => {\n if (portletId) {\n const { [portletId]: _, ...rest } = state.debugData\n return { debugData: rest }\n }\n return { debugData: {} }\n }),\n\n // =================================================================\n // Utility Actions\n // =================================================================\n\n reset: () => set(initialState),\n }\n}\n\n/**\n * Create a new dashboard store instance\n */\nexport function createDashboardStore(options: CreateDashboardStoreOptions = {}) {\n const initialState = buildInitialState(options)\n\n // No localStorage persistence - dashboard state is transient\n return createStore<DashboardStore>()(\n devtools(\n subscribeWithSelector((set, get) => ({\n ...initialState,\n ...createStoreActions(set, get, initialState),\n })),\n { name: 'DashboardStore' }\n )\n )\n}\n\n/**\n * Fallback store for useDashboardStoreOptional - created lazily at module level\n * This allows the hook to always call useStore unconditionally (React hooks rules)\n */\nlet fallbackStore: StoreApi<DashboardStore> | null = null\nfunction getFallbackStore(): StoreApi<DashboardStore> {\n if (!fallbackStore) {\n fallbackStore = createDashboardStore()\n }\n return fallbackStore\n}\n\n// ============================================================================\n// React Context & Provider\n// ============================================================================\n\n/**\n * Context for the store instance\n */\nconst DashboardStoreContext = createContext<StoreApi<DashboardStore> | null>(null)\n\n/**\n * Provider props\n */\nexport interface DashboardStoreProviderProps {\n children: ReactNode\n /** Initial edit mode state */\n initialEditMode?: boolean\n}\n\n/**\n * Provider component that creates a store instance per Dashboard\n */\nexport function DashboardStoreProvider({\n children,\n initialEditMode,\n}: DashboardStoreProviderProps) {\n // Create store instance once per provider mount\n const storeRef = useRef<StoreApi<DashboardStore> | null>(null)\n\n if (!storeRef.current) {\n storeRef.current = createDashboardStore({\n initialEditMode,\n })\n }\n\n return (\n <DashboardStoreContext.Provider value={storeRef.current}>\n {children}\n </DashboardStoreContext.Provider>\n )\n}\n\n/**\n * Hook to access the store from context\n * @throws Error if used outside of provider\n */\nexport function useDashboardStore<T>(selector: (state: DashboardStore) => T): T {\n const store = useContext(DashboardStoreContext)\n if (!store) {\n throw new Error('useDashboardStore must be used within DashboardStoreProvider')\n }\n return useStore(store, selector)\n}\n\n/**\n * Hook to get the raw store API (for actions that need direct access)\n */\nexport function useDashboardStoreApi(): StoreApi<DashboardStore> {\n const store = useContext(DashboardStoreContext)\n if (!store) {\n throw new Error('useDashboardStoreApi must be used within DashboardStoreProvider')\n }\n return store\n}\n\n/**\n * Optional hook that returns null if used outside provider (for optional store access)\n * Uses a fallback store to ensure useStore is always called (React hooks rules compliance)\n */\nexport function useDashboardStoreOptional<T>(\n selector: (state: DashboardStore) => T\n): T | null {\n const contextStore = useContext(DashboardStoreContext)\n // Always call useStore unconditionally (React hooks rules)\n // Use fallback store when context is null to maintain hook order\n const result = useStore(contextStore ?? getFallbackStore(), selector)\n // Return null if there was no real store (using fallback)\n return contextStore ? result : null\n}\n\n// ============================================================================\n// Selectors (for optimized re-renders)\n// ============================================================================\n\n/**\n * Select edit mode state\n */\nexport const selectEditModeState = (state: DashboardStore) => ({\n isEditMode: state.isEditMode,\n selectedFilterId: state.selectedFilterId,\n})\n\n/**\n * Select modal state\n */\nexport const selectModalState = (state: DashboardStore) => ({\n isPortletModalOpen: state.isPortletModalOpen,\n editingPortlet: state.editingPortlet,\n isFilterConfigModalOpen: state.isFilterConfigModalOpen,\n filterConfigPortlet: state.filterConfigPortlet,\n})\n\n/**\n * Select layout state\n */\nexport const selectLayoutState = (state: DashboardStore) => ({\n draftRows: state.draftRows,\n isDraggingPortlet: state.isDraggingPortlet,\n lastKnownLayout: state.lastKnownLayout,\n isInitialized: state.isInitialized,\n dragState: state.dragState,\n})\n\n/**\n * Select debug data\n */\nexport const selectDebugData = (state: DashboardStore) => state.debugData\n\n/**\n * Select debug data for a specific portlet\n */\nexport const selectPortletDebugData = (portletId: string) => (state: DashboardStore) =>\n state.debugData[portletId]\n\n/**\n * Select all edit mode actions\n */\nexport const selectEditModeActions = (state: DashboardStore) => ({\n setEditMode: state.setEditMode,\n toggleEditMode: state.toggleEditMode,\n setSelectedFilterId: state.setSelectedFilterId,\n exitFilterSelectionMode: state.exitFilterSelectionMode,\n})\n\n/**\n * Select all modal actions\n */\nexport const selectModalActions = (state: DashboardStore) => ({\n openPortletModal: state.openPortletModal,\n closePortletModal: state.closePortletModal,\n openFilterConfigModal: state.openFilterConfigModal,\n closeFilterConfigModal: state.closeFilterConfigModal,\n openDeleteConfirm: state.openDeleteConfirm,\n closeDeleteConfirm: state.closeDeleteConfirm,\n})\n\n/**\n * Select all layout actions\n */\nexport const selectLayoutActions = (state: DashboardStore) => ({\n setDraftRows: state.setDraftRows,\n setIsDraggingPortlet: state.setIsDraggingPortlet,\n setLastKnownLayout: state.setLastKnownLayout,\n setIsInitialized: state.setIsInitialized,\n setDragState: state.setDragState,\n clearDragState: state.clearDragState,\n})\n\n/**\n * Select all debug data actions\n */\nexport const selectDebugDataActions = (state: DashboardStore) => ({\n setDebugData: state.setDebugData,\n clearDebugData: state.clearDebugData,\n})\n\n/**\n * Select all actions\n */\nexport const selectAllActions = (state: DashboardStore) => ({\n // Edit mode\n setEditMode: state.setEditMode,\n toggleEditMode: state.toggleEditMode,\n setSelectedFilterId: state.setSelectedFilterId,\n exitFilterSelectionMode: state.exitFilterSelectionMode,\n // Modals\n openPortletModal: state.openPortletModal,\n closePortletModal: state.closePortletModal,\n openFilterConfigModal: state.openFilterConfigModal,\n closeFilterConfigModal: state.closeFilterConfigModal,\n openDeleteConfirm: state.openDeleteConfirm,\n closeDeleteConfirm: state.closeDeleteConfirm,\n // Layout\n setDraftRows: state.setDraftRows,\n setIsDraggingPortlet: state.setIsDraggingPortlet,\n setLastKnownLayout: state.setLastKnownLayout,\n setIsInitialized: state.setIsInitialized,\n setDragState: state.setDragState,\n clearDragState: state.clearDragState,\n // Debug data\n setDebugData: state.setDebugData,\n clearDebugData: state.clearDebugData,\n // Utility\n reset: state.reset,\n})\n","import React, { useCallback, type HTMLAttributes, type ReactNode, type CSSProperties, type ComponentType } from 'react'\nimport type { DashboardFilter, PortletConfig } from '../types'\nimport AnalyticsPortlet from './AnalyticsPortlet'\nimport DebugModal from './DebugModal'\nimport type { ColorPalette } from '../utils/colorPalettes'\nimport { useDashboardStore, type PortletDebugDataEntry } from '../stores/dashboardStore'\n\n// Constant style object to prevent re-renders from inline object recreation\nconst ICON_STYLE: CSSProperties = { width: '16px', height: '16px', color: 'currentColor' }\n\n/**\n * Simplified props interface after Zustand migration.\n * State (isEditMode, selectedFilterId, debugData) now comes from store.\n * Actions now come from callbacks prop or store.\n */\ninterface DashboardPortletCardProps {\n portlet: PortletConfig\n editable: boolean\n dashboardFilters?: DashboardFilter[]\n configEagerLoad?: boolean\n loadingComponent?: ReactNode\n colorPalette?: ColorPalette\n containerProps?: HTMLAttributes<HTMLDivElement>\n headerProps?: HTMLAttributes<HTMLDivElement>\n // Ref callbacks - must remain as props (parent manages refs)\n setPortletRef: (portletId: string, element: HTMLDivElement | null) => void\n setPortletComponentRef: (portletId: string, element: { refresh: () => void } | null) => void\n // Action callbacks - provided by parent for flexibility\n callbacks: {\n onToggleFilter: (portletId: string, filterId: string) => void\n onRefresh: (portletId: string) => void\n onDuplicate: (portletId: string) => void\n onEdit: (portlet: PortletConfig) => void\n onDelete: (portletId: string) => void\n onOpenFilterConfig: (portlet: PortletConfig) => void\n }\n icons: {\n RefreshIcon: ComponentType<{ className?: string; style?: CSSProperties }>\n EditIcon: ComponentType<{ className?: string; style?: CSSProperties }>\n DeleteIcon: ComponentType<{ className?: string; style?: CSSProperties }>\n CopyIcon: ComponentType<{ className?: string; style?: CSSProperties }>\n FilterIcon: ComponentType<{ className?: string; style?: CSSProperties }>\n }\n}\n\n// Custom comparison function to handle containerProps/headerProps object recreation\nfunction arePropsEqual(\n prevProps: DashboardPortletCardProps,\n nextProps: DashboardPortletCardProps\n): boolean {\n // Fast path: if object references are the same, props are equal\n if (prevProps === nextProps) return true\n\n // Check scalar props\n if (\n prevProps.editable !== nextProps.editable ||\n prevProps.configEagerLoad !== nextProps.configEagerLoad\n ) {\n return false\n }\n\n // Check object/array props by reference\n if (\n prevProps.portlet !== nextProps.portlet ||\n prevProps.dashboardFilters !== nextProps.dashboardFilters ||\n prevProps.colorPalette !== nextProps.colorPalette ||\n prevProps.loadingComponent !== nextProps.loadingComponent ||\n prevProps.callbacks !== nextProps.callbacks ||\n prevProps.icons !== nextProps.icons\n ) {\n return false\n }\n\n // Check function props by reference\n if (\n prevProps.setPortletRef !== nextProps.setPortletRef ||\n prevProps.setPortletComponentRef !== nextProps.setPortletComponentRef\n ) {\n return false\n }\n\n // Special handling for containerProps and headerProps - compare properties shallowly\n const containerPropsEqual = shallowEqualObjects(prevProps.containerProps, nextProps.containerProps)\n const headerPropsEqual = shallowEqualObjects(prevProps.headerProps, nextProps.headerProps)\n\n return containerPropsEqual && headerPropsEqual\n}\n\n// Shallow comparison for objects\nfunction shallowEqualObjects<T extends object>(\n a: T | undefined,\n b: T | undefined\n): boolean {\n if (a === b) return true\n if (!a || !b) return a === b\n\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n\n if (keysA.length !== keysB.length) return false\n\n for (const key of keysA) {\n if ((a as Record<string, unknown>)[key] !== (b as Record<string, unknown>)[key]) return false\n }\n\n return true\n}\n\n// Memoize component - now using store for state, so fewer props to compare\nconst DashboardPortletCard = React.memo(function DashboardPortletCard({\n portlet,\n editable,\n dashboardFilters,\n configEagerLoad,\n loadingComponent,\n colorPalette,\n containerProps,\n headerProps,\n setPortletRef,\n setPortletComponentRef,\n callbacks,\n icons\n}: DashboardPortletCardProps) {\n // Get state from Zustand store - automatic memoization via selectors\n const isEditMode = useDashboardStore(state => state.isEditMode)\n const selectedFilterId = useDashboardStore(state => state.selectedFilterId)\n const debugData = useDashboardStore(state => state.debugData[portlet.id])\n\n // Get setDebugData action from store\n const setDebugData = useDashboardStore(state => state.setDebugData)\n\n const hasSelectedFilter = selectedFilterId\n ? (portlet.dashboardFilterMapping || []).includes(selectedFilterId)\n : false\n const isInSelectionMode = !!selectedFilterId\n\n const mergedContainerClassName = [\n 'bg-dc-surface border rounded-lg flex flex-col h-full transition-all',\n isInSelectionMode ? 'cursor-pointer' : '',\n containerProps?.className\n ]\n .filter(Boolean)\n .join(' ')\n\n const mergedHeaderClassName = [\n 'flex items-center justify-between px-3 py-1.5 md:px-4 md:py-1 border-b border-dc-border shrink-0 bg-dc-surface-secondary rounded-t-lg portlet-drag-handle',\n isEditMode ? 'cursor-move' : 'cursor-default',\n headerProps?.className\n ]\n .filter(Boolean)\n .join(' ')\n\n const {\n onClick: containerOnClick,\n className: _containerClassName,\n style: containerStyle,\n ...restContainerProps\n } = containerProps ?? {}\n\n const {\n onClick: headerOnClick,\n className: _headerClassName,\n style: headerStyle,\n ...restHeaderProps\n } = headerProps ?? {}\n\n // Memoize debug data callback - now uses store action directly\n const handleDebugDataReady = useCallback((data: PortletDebugDataEntry) => {\n setDebugData(portlet.id, data)\n }, [portlet.id, setDebugData])\n\n return (\n <div\n data-portlet-id={portlet.id}\n ref={el => setPortletRef(portlet.id, el)}\n className={mergedContainerClassName}\n style={{\n boxShadow: 'var(--dc-shadow-sm)',\n borderColor: isInSelectionMode && hasSelectedFilter\n ? 'var(--dc-primary)'\n : 'var(--dc-border)',\n borderWidth: isInSelectionMode && hasSelectedFilter ? '2px' : '1px',\n backgroundColor: isInSelectionMode && hasSelectedFilter\n ? 'rgba(var(--dc-primary-rgb), 0.05)'\n : 'var(--dc-surface)',\n opacity: isInSelectionMode && !hasSelectedFilter ? '0.5' : '1',\n ...containerStyle\n }}\n onClick={(event) => {\n if (isInSelectionMode && selectedFilterId) {\n event.stopPropagation()\n callbacks.onToggleFilter(portlet.id, selectedFilterId)\n }\n containerOnClick?.(event)\n }}\n {...restContainerProps}\n >\n {(!portlet.displayConfig?.hideHeader || isEditMode) && (\n <div\n className={mergedHeaderClassName}\n style={headerStyle}\n onClick={(event) => {\n headerOnClick?.(event)\n }}\n {...restHeaderProps}\n >\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n <h3 className=\"font-semibold text-sm text-dc-text truncate\">{portlet.title}</h3>\n {editable && isEditMode && debugData && (\n <div\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n onTouchStart={(event) => event.stopPropagation()}\n onTouchEnd={(event) => event.stopPropagation()}\n >\n <DebugModal\n chartConfig={debugData.chartConfig}\n displayConfig={debugData.displayConfig}\n queryObject={debugData.queryObject}\n data={debugData.data}\n chartType={debugData.chartType}\n cacheInfo={debugData.cacheInfo as { hit: true; cachedAt: string; ttlMs: number; ttlRemainingMs: number } | undefined}\n />\n </div>\n )}\n </div>\n <div\n className=\"flex items-center gap-1 shrink-0 ml-4 -mr-2\"\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n onTouchStart={(event) => event.stopPropagation()}\n onTouchEnd={(event) => event.stopPropagation()}\n >\n {/* Cache indicator - show when result was served from cache */}\n {debugData?.cacheInfo && (\n <span\n className=\"p-1 text-dc-text-muted opacity-40\"\n title={`Cached ${Math.round((Date.now() - new Date(debugData.cacheInfo.cachedAt).getTime()) / 1000)}s ago`}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n <path d=\"M3 12c0 1.66 4 3 9 3s9-1.34 9-3\" />\n </svg>\n </span>\n )}\n <button\n onClick={(event) => {\n event.stopPropagation()\n callbacks.onRefresh(portlet.id)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n callbacks.onRefresh(portlet.id)\n }}\n disabled={isInSelectionMode}\n className={`p-1 bg-transparent border-none rounded-sm text-dc-text-secondary transition-colors ${\n isInSelectionMode ? 'cursor-not-allowed opacity-50' : 'cursor-pointer hover:bg-dc-surface-hover'\n }`}\n title=\"Refresh portlet data\"\n >\n <icons.RefreshIcon style={ICON_STYLE} />\n </button>\n\n {editable && isEditMode && !isInSelectionMode && (\n <>\n <button\n onClick={(event) => {\n event.stopPropagation()\n callbacks.onOpenFilterConfig(portlet)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n callbacks.onOpenFilterConfig(portlet)\n }}\n className=\"p-1 bg-transparent border-none rounded-sm cursor-pointer hover:bg-dc-surface-hover transition-colors relative\"\n title={`Configure dashboard filters${portlet.dashboardFilterMapping && portlet.dashboardFilterMapping.length > 0 ? ` (${portlet.dashboardFilterMapping.length} active)` : ''}`}\n style={{\n color: portlet.dashboardFilterMapping && portlet.dashboardFilterMapping.length > 0\n ? 'var(--dc-primary)'\n : 'var(--dc-text-secondary)'\n }}\n >\n <icons.FilterIcon style={ICON_STYLE} />\n </button>\n\n <button\n onClick={(event) => {\n event.stopPropagation()\n callbacks.onDuplicate(portlet.id)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n callbacks.onDuplicate(portlet.id)\n }}\n className=\"p-1 bg-transparent border-none rounded-sm text-dc-text-secondary cursor-pointer hover:bg-dc-surface-hover transition-colors\"\n title=\"Duplicate portlet\"\n >\n <icons.CopyIcon style={ICON_STYLE} />\n </button>\n <button\n onClick={(event) => {\n event.stopPropagation()\n callbacks.onEdit(portlet)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n callbacks.onEdit(portlet)\n }}\n className=\"p-1 bg-transparent border-none rounded-sm text-dc-text-secondary cursor-pointer hover:bg-dc-surface-hover transition-colors\"\n title=\"Edit portlet\"\n >\n <icons.EditIcon style={ICON_STYLE} />\n </button>\n <button\n onClick={(event) => {\n event.stopPropagation()\n callbacks.onDelete(portlet.id)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n callbacks.onDelete(portlet.id)\n }}\n className=\"p-1 mr-0.5 bg-transparent border-none rounded-sm cursor-pointer hover:bg-dc-danger-bg text-dc-danger transition-colors\"\n title=\"Delete portlet\"\n >\n <icons.DeleteIcon style={ICON_STYLE} />\n </button>\n </>\n )}\n </div>\n </div>\n )}\n\n <div className=\"flex-1 px-2 py-3 md:px-4 md:py-4 min-h-0 overflow-visible flex flex-col\">\n <AnalyticsPortlet\n ref={el => setPortletComponentRef(portlet.id, el)}\n query={portlet.query}\n chartType={portlet.chartType}\n chartConfig={portlet.chartConfig}\n displayConfig={portlet.displayConfig}\n dashboardFilters={dashboardFilters}\n dashboardFilterMapping={portlet.dashboardFilterMapping}\n eagerLoad={portlet.eagerLoad ?? configEagerLoad ?? false}\n title={portlet.title}\n height=\"100%\"\n colorPalette={colorPalette}\n loadingComponent={loadingComponent}\n onDebugDataReady={handleDebugDataReady}\n />\n </div>\n </div>\n )\n}, arePropsEqual)\n\nexport default DashboardPortletCard\n","import { useState, useCallback, type HTMLAttributes, type ReactNode, type MouseEvent, type DragEvent } from 'react'\nimport type { DashboardGridSettings, PortletConfig, RowLayout } from '../types'\n\ninterface RowManagedLayoutProps {\n rows: RowLayout[]\n portlets: PortletConfig[]\n gridSettings: DashboardGridSettings\n gridWidth: number\n canEdit: boolean\n isDragging: boolean\n onRowResize: (rowIndex: number, event: MouseEvent<HTMLDivElement>) => void\n onColumnResize: (rowIndex: number, columnIndex: number, event: MouseEvent<HTMLDivElement>) => void\n onPortletDragStart: (rowIndex: number, columnIndex: number, portletId: string, event: DragEvent<HTMLDivElement>) => void\n onPortletDragEnd: () => void\n onRowDrop: (rowIndex: number, insertIndex: number | null) => void\n onNewRowDrop: (insertIndex: number) => void\n renderPortlet: (portlet: PortletConfig, containerProps?: HTMLAttributes<HTMLDivElement>, headerProps?: HTMLAttributes<HTMLDivElement>) => ReactNode\n}\n\nconst COLUMN_GAP = 16\n\nexport default function RowManagedLayout({\n rows,\n portlets,\n gridSettings,\n gridWidth,\n canEdit,\n isDragging,\n onRowResize,\n onColumnResize,\n onPortletDragStart,\n onPortletDragEnd,\n onRowDrop,\n onNewRowDrop,\n renderPortlet\n}: RowManagedLayoutProps) {\n const portletMap = new Map(portlets.map(portlet => [portlet.id, portlet]))\n const [activeDropKey, setActiveDropKey] = useState<string | null>(null)\n\n const setDropActive = (key: string | null) => {\n setActiveDropKey(key)\n }\n\n const isDragActive = isDragging || activeDropKey !== null\n\n // Stable drag event handlers using data attributes to prevent containerProps recreation\n const handlePortletDragStart = useCallback((event: DragEvent<HTMLDivElement>) => {\n const rowIndex = parseInt(event.currentTarget.dataset.rowIndex || '0', 10)\n const columnIndex = parseInt(event.currentTarget.dataset.columnIndex || '0', 10)\n const portletId = event.currentTarget.dataset.portletId || ''\n onPortletDragStart(rowIndex, columnIndex, portletId, event)\n }, [onPortletDragStart])\n\n const handlePortletDragEnd = useCallback(() => {\n setDropActive(null)\n onPortletDragEnd()\n }, [onPortletDragEnd])\n\n const topDropActive = activeDropKey === 'row-insert-0'\n const bottomDropActive = activeDropKey === 'row-bottom'\n\n return (\n <div\n className={`dc-row-layout${canEdit ? ' dc-row-layout-editable' : ''}${isDragActive ? ' dc-row-layout-dragging' : ''}`}\n style={{\n ['--dc-row-gap' as string]: '24px',\n ['--dc-column-gap' as string]: `${COLUMN_GAP}px`,\n ['--dc-top-drop-space' as string]: topDropActive ? '24px' : '0px',\n ['--dc-bottom-drop-space' as string]: bottomDropActive ? '24px' : '0px'\n }}\n >\n {canEdit && (\n <div\n className={`dc-row-boundary-drop dc-row-boundary-drop-top dc-split-handle${activeDropKey === 'row-insert-0' ? ' dc-drop-zone-active' : ''}`}\n onDragOver={(event) => {\n event.preventDefault()\n setDropActive('row-insert-0')\n }}\n onDragLeave={() => setDropActive(null)}\n onDrop={(event) => {\n event.preventDefault()\n setDropActive(null)\n onNewRowDrop(0)\n }}\n />\n )}\n {rows.map((row, rowIndex) => {\n const rowHeight = row.h * gridSettings.rowHeight\n const safeGridWidth = gridWidth || gridSettings.cols * gridSettings.rowHeight\n const paddingLeft = activeDropKey === `row-${rowIndex}-insert-0` ? COLUMN_GAP : 0\n const paddingRight = activeDropKey === `row-${rowIndex}-insert-${row.columns.length}` ? COLUMN_GAP : 0\n const rowContentWidth = safeGridWidth - (row.columns.length - 1) * COLUMN_GAP - paddingLeft - paddingRight\n const unitWidth = rowContentWidth / gridSettings.cols\n\n return (\n <div key={row.id} className=\"dc-row-layout-row-wrapper\">\n <div\n className=\"dc-row-layout-row\"\n style={{ height: rowHeight, paddingLeft, paddingRight }}\n >\n {row.columns.map((column, columnIndex) => {\n const portlet = portletMap.get(column.portletId)\n if (!portlet) return null\n const width = column.w * unitWidth\n\n const containerProps = {\n draggable: canEdit,\n 'data-row-index': rowIndex.toString(),\n 'data-column-index': columnIndex.toString(),\n 'data-portlet-id': portlet.id,\n onDragStart: handlePortletDragStart,\n onDragEnd: handlePortletDragEnd,\n className: 'dc-row-layout-column'\n } as HTMLAttributes<HTMLDivElement>\n\n return (\n <div\n key={portlet.id}\n className=\"dc-row-layout-column-wrapper\"\n style={{\n flex: `0 0 ${width}px`,\n maxWidth: `${width}px`\n }}\n >\n {renderPortlet(portlet, containerProps)}\n {columnIndex < row.columns.length - 1 && (\n <div\n className={`dc-column-resize-handle dc-split-handle${activeDropKey === `row-${rowIndex}-insert-${columnIndex + 1}` ? ' dc-drop-zone-active' : ''}`}\n onMouseDown={(event) => onColumnResize(rowIndex, columnIndex, event)}\n onDragOver={(event) => {\n if (!canEdit) return\n event.preventDefault()\n setDropActive(`row-${rowIndex}-insert-${columnIndex + 1}`)\n }}\n onDragLeave={() => setDropActive(null)}\n onDrop={(event) => {\n if (!canEdit) return\n event.preventDefault()\n event.stopPropagation()\n setDropActive(null)\n onRowDrop(rowIndex, columnIndex + 1)\n }}\n />\n )}\n </div>\n )\n })}\n </div>\n {canEdit && (\n <>\n <div\n className={`dc-row-edge-drop dc-row-edge-drop-left dc-split-handle${activeDropKey === `row-${rowIndex}-insert-0` ? ' dc-drop-zone-active' : ''}`}\n onDragOver={(event) => {\n event.preventDefault()\n setDropActive(`row-${rowIndex}-insert-0`)\n }}\n onDragLeave={() => {\n setDropActive(null)\n }}\n onDrop={(event) => {\n event.preventDefault()\n setDropActive(null)\n onRowDrop(rowIndex, 0)\n }}\n />\n <div\n className={`dc-row-edge-drop dc-row-edge-drop-right dc-split-handle${activeDropKey === `row-${rowIndex}-insert-${row.columns.length}` ? ' dc-drop-zone-active' : ''}`}\n onDragOver={(event) => {\n event.preventDefault()\n setDropActive(`row-${rowIndex}-insert-${row.columns.length}`)\n }}\n onDragLeave={() => {\n setDropActive(null)\n }}\n onDrop={(event) => {\n event.preventDefault()\n setDropActive(null)\n onRowDrop(rowIndex, row.columns.length)\n }}\n />\n </>\n )}\n {canEdit && (\n <div\n className={`dc-row-resize-handle dc-split-handle${activeDropKey === `row-insert-${rowIndex + 1}` ? ' dc-drop-zone-active' : ''}`}\n onMouseDown={(event) => onRowResize(rowIndex, event)}\n onDragOver={(event) => {\n event.preventDefault()\n setDropActive(`row-insert-${rowIndex + 1}`)\n }}\n onDragLeave={() => setDropActive(null)}\n onDrop={(event) => {\n event.preventDefault()\n setDropActive(null)\n onNewRowDrop(rowIndex + 1)\n }}\n />\n )}\n </div>\n )\n })}\n {canEdit && (\n <div\n className={`dc-row-boundary-drop dc-row-boundary-drop-bottom dc-split-handle${activeDropKey === 'row-bottom' ? ' dc-drop-zone-active' : ''}`}\n onDragOver={(event) => {\n event.preventDefault()\n setDropActive('row-bottom')\n }}\n onDragLeave={() => setDropActive(null)}\n onDrop={(event) => {\n event.preventDefault()\n setDropActive(null)\n onNewRowDrop(rows.length)\n }}\n />\n )}\n </div>\n )\n}\n","/**\n * Unified Color Palette System\n * Each palette contains coordinated series and gradient colors that work well together\n */\n\nexport interface ColorPalette {\n name: string\n label: string\n colors: string[] // For series-based charts (bar, line, pie, area, scatter, radar, etc.)\n gradient: string[] // For gradient-based charts (bubble, activity grid)\n}\n\n// Predefined color palettes with visually coordinated series and gradient colors\nexport const COLOR_PALETTES: ColorPalette[] = [\n {\n name: 'default',\n label: 'Default',\n colors: [\n '#3b82f6', // blue\n '#10b981', // green\n '#f59e0b', // yellow\n '#ef4444', // red\n '#8b5cf6', // purple\n '#f97316', // orange\n '#06b6d4', // cyan\n '#84cc16', // lime\n ],\n gradient: [\n '#440154', // dark purple\n '#414487', // purple-blue\n '#2a788e', // teal\n '#22a884', // green-teal \n '#7ad151', // green\n '#fde725', // yellow\n ]\n },\n {\n name: 'ocean',\n label: 'Ocean',\n colors: [\n '#1e3a8a', // deep blue\n '#1e40af', // blue\n '#2563eb', // bright blue\n '#3b82f6', // light blue\n '#06b6d4', // cyan\n '#0891b2', // dark cyan\n '#0e7490', // teal\n '#0f766e', // dark teal\n ],\n gradient: [\n '#0c4a6e', // very dark blue\n '#075985', // dark blue\n '#0369a1', // medium blue\n '#0284c7', // bright blue\n '#0ea5e9', // light blue\n '#38bdf8', // cyan blue\n ]\n },\n {\n name: 'sunset',\n label: 'Sunset',\n colors: [\n '#dc2626', // red\n '#ea580c', // orange-red\n '#f59e0b', // orange\n '#eab308', // yellow-orange\n '#d97706', // amber\n '#b45309', // dark amber\n '#92400e', // brown\n '#7c2d12', // dark brown\n ],\n gradient: [\n '#7c2d12', // dark brown\n '#92400e', // brown\n '#b45309', // dark amber\n '#d97706', // amber\n '#f59e0b', // orange\n '#fbbf24', // light orange\n ]\n },\n {\n name: 'forest',\n label: 'Forest',\n colors: [\n '#166534', // dark green\n '#15803d', // green\n '#16a34a', // bright green\n '#22c55e', // light green\n '#4ade80', // lighter green\n '#65a30d', // lime green\n '#84cc16', // lime\n '#a3e635', // light lime\n ],\n gradient: [\n '#14532d', // very dark green\n '#166534', // dark green\n '#15803d', // green\n '#16a34a', // bright green\n '#22c55e', // light green\n '#4ade80', // lighter green\n ]\n },\n {\n name: 'purple',\n label: 'Purple',\n colors: [\n '#581c87', // dark purple\n '#7c3aed', // purple\n '#8b5cf6', // bright purple\n '#a855f7', // light purple\n '#c084fc', // lighter purple\n '#e879f9', // magenta\n '#f0abfc', // light magenta\n '#fbbf24', // accent yellow\n ],\n gradient: [\n '#4c1d95', // very dark purple\n '#581c87', // dark purple\n '#6d28d9', // medium purple\n '#7c3aed', // purple\n '#8b5cf6', // bright purple\n '#a855f7', // light purple\n ]\n },\n {\n name: 'monochrome',\n label: 'Monochrome',\n colors: [\n '#1f2937', // very dark gray\n '#374151', // dark gray\n '#4b5563', // medium gray\n '#6b7280', // gray\n '#9ca3af', // light gray\n '#d1d5db', // lighter gray\n '#e5e7eb', // very light gray\n '#f3f4f6', // almost white\n ],\n gradient: [\n '#111827', // black\n '#1f2937', // very dark gray\n '#374151', // dark gray\n '#4b5563', // medium gray\n '#6b7280', // gray\n '#9ca3af', // light gray\n ]\n },\n {\n name: 'pastel',\n label: 'Pastel',\n colors: [\n '#93c5fd', // light blue\n '#86efac', // light green\n '#fde047', // light yellow\n '#fca5a5', // light red\n '#c4b5fd', // light purple\n '#fdba74', // light orange\n '#67e8f9', // light cyan\n '#bef264', // light lime\n ],\n gradient: [\n '#bfdbfe', // very light blue\n '#a7f3d0', // very light green\n '#fef08a', // very light yellow\n '#fecaca', // very light red\n '#ddd6fe', // very light purple\n '#fed7aa', // very light orange\n ]\n },\n {\n name: 'vibrant',\n label: 'Vibrant',\n colors: [\n '#0000ff', // pure blue\n '#00ff00', // pure green\n '#ffff00', // pure yellow\n '#ff0000', // pure red\n '#ff00ff', // pure magenta\n '#ff8000', // pure orange\n '#00ffff', // pure cyan\n '#8000ff', // pure violet\n ],\n gradient: [\n '#4000ff', // blue-violet\n '#0080ff', // blue\n '#00ffff', // cyan\n '#00ff80', // green\n '#80ff00', // lime\n '#ffff00', // yellow\n ]\n },\n {\n name: 'd3Category10',\n label: 'D3 Category 10',\n colors: [\n '#1f77b4', // blue\n '#ff7f0e', // orange\n '#2ca02c', // green\n '#d62728', // red\n '#9467bd', // purple\n '#8c564b', // brown\n '#e377c2', // pink\n '#7f7f7f', // gray\n '#bcbd22', // olive\n '#17becf', // cyan\n ],\n gradient: [\n '#1f77b4', // blue\n '#2ca02c', // green\n '#bcbd22', // olive\n '#ff7f0e', // orange\n '#d62728', // red\n '#9467bd', // purple\n ]\n },\n {\n name: 'd3Tableau10',\n label: 'D3 Tableau 10',\n colors: [\n '#4e79a7', // blue\n '#f28e2c', // orange\n '#e15759', // red\n '#76b7b2', // teal\n '#59a14f', // green\n '#edc949', // yellow\n '#af7aa1', // purple\n '#ff9da7', // pink\n '#9c755f', // brown\n '#bab0ab', // gray\n ],\n gradient: [\n '#4e79a7', // blue\n '#76b7b2', // teal\n '#59a14f', // green\n '#edc949', // yellow\n '#f28e2c', // orange\n '#e15759', // red\n ]\n },\n {\n name: 'colorBrewerSet1',\n label: 'ColorBrewer Set 1',\n colors: [\n '#e41a1c', // red\n '#377eb8', // blue\n '#4daf4a', // green\n '#984ea3', // purple\n '#ff7f00', // orange\n '#ffff33', // yellow\n '#a65628', // brown\n '#f781bf', // pink\n '#999999', // gray\n ],\n gradient: [\n '#377eb8', // blue\n '#4daf4a', // green\n '#ffff33', // yellow\n '#ff7f00', // orange\n '#e41a1c', // red\n '#984ea3', // purple\n ]\n },\n {\n name: 'colorBrewerSet2',\n label: 'ColorBrewer Set 2',\n colors: [\n '#66c2a5', // teal\n '#fc8d62', // orange\n '#8da0cb', // blue\n '#e78ac3', // pink\n '#a6d854', // lime\n '#ffd92f', // yellow\n '#e5c494', // tan\n '#b3b3b3', // gray\n ],\n gradient: [\n '#8da0cb', // blue\n '#66c2a5', // teal\n '#a6d854', // lime\n '#ffd92f', // yellow\n '#fc8d62', // orange\n '#e78ac3', // pink\n ]\n },\n {\n name: 'colorBrewerDark2',\n label: 'ColorBrewer Dark 2',\n colors: [\n '#1b9e77', // dark teal\n '#d95f02', // dark orange\n '#7570b3', // dark blue\n '#e7298a', // dark pink\n '#66a61e', // dark green\n '#e6ab02', // dark yellow\n '#a6761d', // dark brown\n '#666666', // dark gray\n ],\n gradient: [\n '#7570b3', // dark blue\n '#1b9e77', // dark teal\n '#66a61e', // dark green\n '#e6ab02', // dark yellow\n '#d95f02', // dark orange\n '#e7298a', // dark pink\n ]\n },\n {\n name: 'colorBrewerPaired',\n label: 'ColorBrewer Paired',\n colors: [\n '#a6cee3', // light blue\n '#1f78b4', // blue\n '#b2df8a', // light green\n '#33a02c', // green\n '#fb9a99', // light red\n '#e31a1c', // red\n '#fdbf6f', // light orange\n '#ff7f00', // orange\n '#cab2d6', // light purple\n '#6a3d9a', // purple\n '#ffff99', // light yellow\n '#b15928', // brown\n ],\n gradient: [\n '#1f78b4', // blue\n '#33a02c', // green\n '#ffff99', // light yellow\n '#ff7f00', // orange\n '#e31a1c', // red\n '#6a3d9a', // purple\n ]\n },\n {\n name: 'viridis',\n label: 'Viridis',\n colors: [\n '#440154', // dark purple\n '#482677', // purple\n '#3f4a8a', // blue-purple\n '#31678e', // blue\n '#26838f', // teal\n '#1f9d8a', // green-teal\n '#6cce5a', // green\n '#b6de2b', // yellow-green\n ],\n gradient: [\n '#440154', // dark purple\n '#482677', // purple\n '#3f4a8a', // blue-purple\n '#31678e', // blue\n '#26838f', // teal\n '#1f9d8a', // green-teal\n '#6cce5a', // green\n '#b6de2b', // yellow-green\n ]\n },\n {\n name: 'plasma',\n label: 'Plasma',\n colors: [\n '#0c0786', // dark blue\n '#5c01a6', // purple\n '#900da4', // magenta\n '#bf3984', // pink\n '#e16462', // coral\n '#f99b45', // orange\n '#fcce25', // yellow\n '#f0f921', // bright yellow\n ],\n gradient: [\n '#0c0786', // dark blue\n '#5c01a6', // purple\n '#900da4', // magenta\n '#bf3984', // pink\n '#e16462', // coral\n '#f99b45', // orange\n '#fcce25', // yellow\n '#f0f921', // bright yellow\n ]\n },\n {\n name: 'inferno',\n label: 'Inferno',\n colors: [\n '#000003', // black\n '#1f0c47', // dark blue\n '#550f6d', // purple\n '#88226a', // magenta\n '#a83655', // red\n '#cc4f39', // orange-red\n '#e6862a', // orange\n '#fec228', // yellow\n ],\n gradient: [\n '#000003', // black\n '#1f0c47', // dark blue\n '#550f6d', // purple\n '#88226a', // magenta\n '#a83655', // red\n '#cc4f39', // orange-red\n '#e6862a', // orange\n '#fec228', // yellow\n ]\n },\n {\n name: 'magma',\n label: 'Magma',\n colors: [\n '#000003', // black\n '#140b34', // dark purple\n '#3b0f6f', // purple\n '#641a80', // magenta\n '#8b2981', // pink\n '#b63679', // coral\n '#de4968', // red\n '#fd9f6c', // orange\n ],\n gradient: [\n '#000003', // black\n '#140b34', // dark purple\n '#3b0f6f', // purple\n '#641a80', // magenta\n '#8b2981', // pink\n '#b63679', // coral\n '#de4968', // red\n '#fd9f6c', // orange\n ]\n },\n {\n name: 'cividis',\n label: 'Cividis',\n colors: [\n '#00204c', // dark blue\n '#003f5c', // blue\n '#2c4b7a', // blue\n '#51576f', // blue-gray\n '#7f6874', // gray\n '#a8786e', // brown\n '#d2906d', // orange\n '#ffb570', // yellow\n ],\n gradient: [\n '#00204c', // dark blue\n '#003f5c', // blue\n '#2c4b7a', // blue\n '#51576f', // blue-gray\n '#7f6874', // gray\n '#a8786e', // brown\n '#d2906d', // orange\n '#ffb570', // yellow\n ]\n },\n {\n name: 'turbo',\n label: 'Turbo',\n colors: [\n '#30123b', // purple\n '#4454c4', // blue\n '#1dd3c0', // cyan\n '#42f465', // green\n '#b2df22', // lime\n '#faba39', // yellow\n '#f66c19', // orange\n '#c42e02', // red\n ],\n gradient: [\n '#30123b', // purple\n '#4454c4', // blue\n '#1dd3c0', // cyan\n '#42f465', // green\n '#b2df22', // lime\n '#faba39', // yellow\n '#f66c19', // orange\n '#c42e02', // red\n ]\n },\n {\n name: 'warm',\n label: 'Warm',\n colors: [\n '#8b0000', // dark red\n '#b22222', // red\n '#cd5c5c', // light red\n '#ff6347', // tomato\n '#ff8c00', // dark orange\n '#ffa500', // orange\n '#ffd700', // gold\n '#ffff00', // yellow\n ],\n gradient: [\n '#8b0000', // dark red\n '#b22222', // red\n '#ff6347', // tomato\n '#ff8c00', // dark orange\n '#ffa500', // orange\n '#ffd700', // gold\n ]\n },\n {\n name: 'cool',\n label: 'Cool',\n colors: [\n '#000080', // navy\n '#0000ff', // blue\n '#4169e1', // royal blue\n '#00bfff', // deep sky blue\n '#00ffff', // cyan\n '#40e0d0', // turquoise\n '#20b2aa', // light sea green\n '#008b8b', // dark cyan\n ],\n gradient: [\n '#000080', // navy\n '#0000ff', // blue\n '#4169e1', // royal blue\n '#00bfff', // deep sky blue\n '#00ffff', // cyan\n '#40e0d0', // turquoise\n ]\n },\n {\n name: 'earth',\n label: 'Earth',\n colors: [\n '#8b4513', // saddle brown\n '#a0522d', // sienna\n '#cd853f', // peru\n '#daa520', // goldenrod\n '#d2691e', // chocolate\n '#bc8f8f', // rosy brown\n '#f4a460', // sandy brown\n '#deb887', // burlywood\n ],\n gradient: [\n '#8b4513', // saddle brown\n '#a0522d', // sienna\n '#cd853f', // peru\n '#daa520', // goldenrod\n '#d2691e', // chocolate\n '#f4a460', // sandy brown\n ]\n },\n {\n name: 'autumn',\n label: 'Autumn',\n colors: [\n '#8b0000', // dark red\n '#a0522d', // sienna\n '#cd853f', // peru\n '#daa520', // goldenrod\n '#ff8c00', // dark orange\n '#ff4500', // orange red\n '#dc143c', // crimson\n '#b22222', // fire brick\n ],\n gradient: [\n '#8b0000', // dark red\n '#a0522d', // sienna\n '#cd853f', // peru\n '#daa520', // goldenrod\n '#ff8c00', // dark orange\n '#ff4500', // orange red\n ]\n },\n {\n name: 'spring',\n label: 'Spring',\n colors: [\n '#32cd32', // lime green\n '#98fb98', // pale green\n '#90ee90', // light green\n '#ffb6c1', // light pink\n '#ffc0cb', // pink\n '#ffffe0', // light yellow\n '#f0fff0', // honeydew\n '#e0ffff', // light cyan\n ],\n gradient: [\n '#32cd32', // lime green\n '#98fb98', // pale green\n '#ffffe0', // light yellow\n '#ffb6c1', // light pink\n '#ffc0cb', // pink\n '#e0ffff', // light cyan\n ]\n },\n {\n name: 'winter',\n label: 'Winter',\n colors: [\n '#191970', // midnight blue\n '#4682b4', // steel blue\n '#87ceeb', // sky blue\n '#b0e0e6', // powder blue\n '#e0ffff', // light cyan\n '#f0f8ff', // alice blue\n '#c0c0c0', // silver\n '#708090', // slate gray\n ],\n gradient: [\n '#191970', // midnight blue\n '#4682b4', // steel blue\n '#87ceeb', // sky blue\n '#b0e0e6', // powder blue\n '#e0ffff', // light cyan\n '#f0f8ff', // alice blue\n ]\n },\n {\n name: 'neon',\n label: 'Neon',\n colors: [\n '#ff0080', // neon pink\n '#00ff80', // neon green\n '#8000ff', // neon purple\n '#ff8000', // neon orange\n '#0080ff', // neon blue\n '#80ff00', // neon lime\n '#ff0040', // neon red\n '#40ff00', // bright green\n ],\n gradient: [\n '#8000ff', // neon purple\n '#0080ff', // neon blue\n '#00ff80', // neon green\n '#80ff00', // neon lime\n '#ff8000', // neon orange\n '#ff0080', // neon pink\n ]\n },\n {\n name: 'retro',\n label: 'Retro',\n colors: [\n '#ff69b4', // hot pink\n '#ffd700', // gold\n '#32cd32', // lime green\n '#00ced1', // dark turquoise\n '#ff6347', // tomato\n '#9370db', // medium purple\n '#ffa500', // orange\n '#20b2aa', // light sea green\n ],\n gradient: [\n '#9370db', // medium purple\n '#ff69b4', // hot pink\n '#ff6347', // tomato\n '#ffd700', // gold\n '#32cd32', // lime green\n '#00ced1', // dark turquoise\n ]\n },\n {\n name: 'corporate',\n label: 'Corporate',\n colors: [\n '#003366', // dark blue\n '#0066cc', // blue\n '#336699', // steel blue\n '#6699cc', // light blue\n '#4d4d4d', // dark gray\n '#808080', // gray\n '#b3b3b3', // light gray\n '#cccccc', // very light gray\n ],\n gradient: [\n '#003366', // dark blue\n '#0066cc', // blue\n '#336699', // steel blue\n '#6699cc', // light blue\n '#808080', // gray\n '#b3b3b3', // light gray\n ]\n },\n {\n name: 'material',\n label: 'Material Design',\n colors: [\n '#f44336', // red\n '#e91e63', // pink\n '#9c27b0', // purple\n '#673ab7', // deep purple\n '#3f51b5', // indigo\n '#2196f3', // blue\n '#03a9f4', // light blue\n '#00bcd4', // cyan\n ],\n gradient: [\n '#673ab7', // deep purple\n '#3f51b5', // indigo\n '#2196f3', // blue\n '#00bcd4', // cyan\n '#03a9f4', // light blue\n '#e91e63', // pink\n ]\n }\n]\n\n/**\n * Get a color palette by name, with fallback to default\n */\nexport function getColorPalette(paletteName?: string): ColorPalette {\n if (!paletteName) {\n return COLOR_PALETTES[0] // default palette\n }\n \n const palette = COLOR_PALETTES.find(p => p.name === paletteName)\n return palette || COLOR_PALETTES[0] // fallback to default\n}\n\n/**\n * Get just the series colors for a palette\n */\nexport function getSeriesColors(paletteName?: string): string[] {\n return getColorPalette(paletteName).colors\n}\n\n/**\n * Get just the gradient colors for a palette\n */\nexport function getGradientColors(paletteName?: string): string[] {\n return getColorPalette(paletteName).gradient\n}\n\n/**\n * Chart types that use series colors (discrete categories)\n */\nexport const SERIES_CHART_TYPES = [\n 'bar', 'line', 'area', 'pie', 'scatter', 'radar', 'radialBar', 'treeMap'\n] as const\n\n/**\n * Chart types that use gradient colors (continuous values)\n */\nexport const GRADIENT_CHART_TYPES = [\n 'bubble', 'activityGrid'\n] as const\n\n/**\n * Determine if a chart type uses gradient colors\n */\nexport function usesGradientColors(chartType: string): boolean {\n return GRADIENT_CHART_TYPES.includes(chartType as any)\n}","/**\n * FloatingEditToolbar - Vertical floating toolbar for dashboard editing\n *\n * Appears when the static edit bar scrolls out of view, providing quick access\n * to edit controls in a compact vertical format with icon-only buttons.\n *\n * Features:\n * - Icon-only buttons with tooltips\n * - Configurable left/right positioning\n * - Smooth slide-in/out animation\n * - Only visible on desktop (≥1200px)\n * - Compact palette dropdown that opens opposite to toolbar position\n */\n\nimport React, { useState, useRef, useEffect } from 'react'\nimport { createPortal } from 'react-dom'\nimport { getIcon } from '../icons'\nimport { COLOR_PALETTES } from '../utils/colorPalettes'\nimport type { DashboardLayoutMode } from '../types'\n\nconst EditIcon = getIcon('edit')\nconst CheckIcon = getIcon('check')\nconst GridIcon = getIcon('segment')\nconst RowsIcon = getIcon('table')\nconst AddIcon = getIcon('add')\nconst SwatchIcon = getIcon('swatch')\n\ninterface FloatingEditToolbarProps {\n /** Whether the static edit bar is visible (toolbar hidden when true) */\n isEditBarVisible: boolean\n /** Position of the floating toolbar */\n position: 'left' | 'right'\n /** Whether currently in edit mode */\n isEditMode: boolean\n /** Toggle edit mode on/off */\n onEditModeToggle: () => void\n /** Current layout mode */\n layoutMode: DashboardLayoutMode\n /** Change layout mode */\n onLayoutModeChange: (mode: DashboardLayoutMode) => void\n /** Available layout modes */\n allowedModes: DashboardLayoutMode[]\n /** Whether layout mode can be changed */\n canChangeLayoutMode: boolean\n /** Current color palette name */\n currentPalette: string\n /** Change color palette */\n onPaletteChange: (palette: string) => void\n /** Add new portlet */\n onAddPortlet: () => void\n}\n\nexport default function FloatingEditToolbar({\n isEditBarVisible,\n position,\n isEditMode,\n onEditModeToggle,\n layoutMode,\n onLayoutModeChange,\n allowedModes,\n canChangeLayoutMode,\n currentPalette,\n onPaletteChange,\n onAddPortlet\n}: FloatingEditToolbarProps) {\n const [isPaletteOpen, setIsPaletteOpen] = useState(false)\n const paletteRef = useRef<HTMLDivElement>(null)\n\n // Close palette dropdown on outside click\n useEffect(() => {\n if (!isPaletteOpen) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (paletteRef.current && !paletteRef.current.contains(e.target as Node)) {\n setIsPaletteOpen(false)\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [isPaletteOpen])\n\n // Close palette when toolbar hides\n useEffect(() => {\n if (isEditBarVisible) {\n setIsPaletteOpen(false)\n }\n }, [isEditBarVisible])\n\n // Position classes - fixed positioning with vertical centering\n const positionClasses = position === 'left'\n ? 'left-4'\n : 'right-4'\n\n // Animation: slide in from edge when edit bar not visible\n // When edit bar IS visible, slide out and hide\n const isHidden = isEditBarVisible\n const translateClasses = position === 'left'\n ? (isHidden ? '-translate-x-16 opacity-0 pointer-events-none' : 'translate-x-0 opacity-100')\n : (isHidden ? 'translate-x-16 opacity-0 pointer-events-none' : 'translate-x-0 opacity-100')\n\n // Use portal to render outside the grid container to avoid react-grid-layout issues\n const toolbarContent = (\n <div\n className={`fixed top-1/2 -translate-y-1/2 z-50 flex flex-col gap-1.5 p-2\n bg-dc-surface-tertiary border border-dc-border rounded-lg\n transition-all duration-300 ease-in-out\n ${positionClasses} ${translateClasses}`}\n style={{\n boxShadow: 'var(--dc-shadow-lg)'\n }}\n >\n {/* Edit Toggle */}\n <ToolbarButton\n icon={isEditMode ? CheckIcon : EditIcon}\n tooltip={isEditMode ? 'Finish Editing' : 'Edit Dashboard'}\n isActive={isEditMode}\n onClick={onEditModeToggle}\n />\n\n {/* Layout Mode Switcher - only in edit mode with multiple modes */}\n {isEditMode && allowedModes.length > 1 && (\n <>\n <div className=\"w-full h-px bg-dc-border my-0.5\" />\n <ToolbarButton\n icon={GridIcon}\n tooltip=\"Grid Layout\"\n isActive={layoutMode === 'grid'}\n disabled={!canChangeLayoutMode}\n onClick={() => onLayoutModeChange('grid')}\n />\n <ToolbarButton\n icon={RowsIcon}\n tooltip=\"Rows Layout\"\n isActive={layoutMode === 'rows'}\n disabled={!canChangeLayoutMode}\n onClick={() => onLayoutModeChange('rows')}\n />\n </>\n )}\n\n {/* Color Palette - only in edit mode */}\n {isEditMode && (\n <>\n <div className=\"w-full h-px bg-dc-border my-0.5\" />\n <div ref={paletteRef} className=\"relative\">\n <ToolbarButton\n icon={SwatchIcon}\n tooltip=\"Color Palette\"\n isActive={isPaletteOpen}\n onClick={() => setIsPaletteOpen(!isPaletteOpen)}\n />\n {isPaletteOpen && (\n <CompactPaletteDropdown\n position={position}\n currentPalette={currentPalette}\n onPaletteChange={(palette) => {\n onPaletteChange(palette)\n setIsPaletteOpen(false)\n }}\n />\n )}\n </div>\n </>\n )}\n\n {/* Add Portlet - only in edit mode */}\n {isEditMode && (\n <>\n <div className=\"w-full h-px bg-dc-border my-0.5\" />\n <ToolbarButton\n icon={AddIcon}\n tooltip=\"Add Portlet\"\n onClick={onAddPortlet}\n />\n </>\n )}\n </div>\n )\n\n // Render via portal to document.body to avoid react-grid-layout child iteration issues\n if (typeof document === 'undefined') {\n return null // SSR safety\n }\n\n return createPortal(toolbarContent, document.body)\n}\n\n// Internal ToolbarButton component\ninterface ToolbarButtonProps {\n icon: React.ComponentType<{ className?: string }>\n tooltip: string\n isActive?: boolean\n disabled?: boolean\n onClick: () => void\n}\n\nfunction ToolbarButton({ icon: Icon, tooltip, isActive, disabled, onClick }: ToolbarButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n title={tooltip}\n className={`p-2 rounded-md transition-colors focus:outline-hidden focus:ring-2 focus:ring-dc-accent\n ${disabled\n ? 'opacity-50 cursor-not-allowed bg-dc-surface-secondary'\n : isActive\n ? 'bg-dc-surface-secondary'\n : 'bg-dc-surface hover:bg-dc-surface-hover'\n }`}\n style={{\n color: disabled ? 'var(--dc-text-muted)' : isActive ? 'var(--dc-primary)' : 'var(--dc-text-secondary)',\n borderColor: isActive ? 'var(--dc-primary)' : 'transparent'\n }}\n >\n <Icon className=\"w-5 h-5\" />\n </button>\n )\n}\n\n// Compact palette dropdown for floating toolbar\ninterface CompactPaletteDropdownProps {\n position: 'left' | 'right'\n currentPalette: string\n onPaletteChange: (palette: string) => void\n}\n\nfunction CompactPaletteDropdown({ position, currentPalette, onPaletteChange }: CompactPaletteDropdownProps) {\n // Position dropdown opposite to toolbar position to avoid off-screen\n const positionClasses = position === 'left' ? 'left-full ml-2' : 'right-full mr-2'\n\n return (\n <div\n className={`absolute top-0 ${positionClasses} w-52 bg-dc-surface border border-dc-border rounded-md z-50 max-h-72 overflow-y-auto`}\n style={{\n boxShadow: 'var(--dc-shadow-lg)'\n }}\n >\n <div className=\"py-1\">\n {COLOR_PALETTES.slice().sort((a, b) => a.label.localeCompare(b.label)).map((palette) => (\n <button\n key={palette.name}\n type=\"button\"\n onClick={() => onPaletteChange(palette.name)}\n className={`w-full px-3 py-2 text-left text-sm hover:bg-dc-surface-hover transition-colors ${\n palette.name === currentPalette ? 'bg-dc-surface-secondary text-dc-primary' : 'text-dc-text-secondary'\n }`}\n >\n <div className=\"flex items-center gap-2\">\n {/* Compact color preview - 4 series colors */}\n <div className=\"flex gap-0.5 shrink-0\">\n {palette.colors.slice(0, 4).map((color, index) => (\n <div\n key={index}\n className=\"w-2.5 h-2.5 rounded-xs border border-dc-border\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n <span className=\"text-xs font-medium truncate text-dc-text\">{palette.label}</span>\n {/* Current indicator */}\n {palette.name === currentPalette && (\n <div className=\"ml-auto w-1.5 h-1.5 rounded-full shrink-0 bg-dc-primary\" />\n )}\n </div>\n </button>\n ))}\n </div>\n </div>\n )\n}\n","import React, { useEffect, useCallback } from 'react'\n\nexport interface ModalProps {\n isOpen: boolean\n onClose: () => void\n title?: string\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'full' | 'fullscreen' | 'fullscreen-mobile'\n closeOnBackdropClick?: boolean\n closeOnEscape?: boolean\n showCloseButton?: boolean\n className?: string\n children: React.ReactNode\n footer?: React.ReactNode\n noPadding?: boolean\n}\n\nconst Modal: React.FC<ModalProps> = ({\n isOpen,\n onClose,\n title,\n size = 'md',\n closeOnBackdropClick = true,\n closeOnEscape = true,\n showCloseButton = true,\n children,\n footer,\n noPadding = false\n}) => {\n // Handle ESC key press\n const handleEscapeKey = useCallback((event: KeyboardEvent) => {\n if (event.key === 'Escape' && closeOnEscape) {\n onClose()\n }\n }, [closeOnEscape, onClose])\n\n\n // Manage ESC key listener and body scroll\n useEffect(() => {\n if (isOpen) {\n // Add ESC key listener\n if (closeOnEscape) {\n document.addEventListener('keydown', handleEscapeKey)\n }\n\n // Prevent body scroll when modal is open\n document.body.style.overflow = 'hidden'\n } else {\n // Restore body scroll\n document.body.style.overflow = 'unset'\n }\n\n // Cleanup\n return () => {\n document.removeEventListener('keydown', handleEscapeKey)\n document.body.style.overflow = 'unset'\n }\n }, [isOpen, closeOnEscape, handleEscapeKey])\n\n\n if (!isOpen) return null\n\n const getSizeClasses = () => {\n switch (size) {\n case 'sm':\n return 'max-w-md'\n case 'md':\n return 'max-w-lg'\n case 'lg':\n return 'max-w-2xl'\n case 'xl':\n return 'max-w-6xl'\n case 'xxl':\n return 'max-w-[1400px]' // Good for retina/mac displays\n case 'full':\n return 'max-w-7xl'\n case 'fullscreen':\n return 'w-[90vw] h-[90vh] max-w-none'\n case 'fullscreen-mobile':\n return 'w-full h-full md:w-[min(90vw,1400px)] md:h-[90vh]'\n default:\n return 'max-w-lg'\n }\n }\n\n return (\n <div\n className={`fixed inset-0 z-50 backdrop-blur-md ${size === 'fullscreen-mobile' ? 'flex md:flex md:items-center md:justify-center' : 'flex items-center justify-center'}`}\n style={{ backgroundColor: 'var(--dc-overlay)' }}\n onClick={closeOnBackdropClick ? onClose : undefined}\n >\n <div\n className={`relative bg-dc-surface border border-dc-border ${size === 'fullscreen-mobile' ? 'rounded-none md:rounded-lg' : 'rounded-lg'} ${size === 'fullscreen' || size === 'fullscreen-mobile' ? '' : 'mx-4'} ${getSizeClasses()} ${size === 'fullscreen' || size === 'fullscreen-mobile' ? '' : 'max-h-[90vh]'} flex flex-col`}\n style={{ boxShadow: 'var(--dc-shadow-2xl)' }}\n onClick={(e) => e.stopPropagation()}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? 'modal-title' : undefined}\n >\n {/* Header */}\n {(title || showCloseButton) && (\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-dc-border\">\n {title && (\n <h2 id=\"modal-title\" className=\"text-xl font-semibold text-dc-text\">\n {title}\n </h2>\n )}\n {showCloseButton && (\n <button\n type=\"button\"\n onClick={onClose}\n className=\"text-dc-text-muted hover:text-dc-text-secondary transition-colors p-2 -mr-2\"\n aria-label=\"Close modal\"\n >\n <svg width=\"24\" height=\"24\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n )}\n\n {/* Content */}\n <div className={`flex-1 overflow-y-auto ${noPadding ? '' : 'px-6 py-4'}`}>\n {children}\n </div>\n\n {/* Footer */}\n {footer && (\n <div className=\"flex items-center justify-end space-x-3 px-6 py-4 border-t border-dc-border bg-dc-surface-secondary\">\n {React.Children.toArray(footer)}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default Modal","/**\n * ID Generation Utilities for AnalysisBuilder\n */\n\n/**\n * Generate a unique ID for items\n */\nexport function generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * Generate letter label for metrics (A, B, C, ..., AA, AB, ...)\n */\nexport function generateMetricLabel(index: number): string {\n let label = ''\n let n = index\n do {\n label = String.fromCharCode(65 + (n % 26)) + label\n n = Math.floor(n / 26) - 1\n } while (n >= 0)\n return label\n}\n","/**\n * Shared date range parsing utilities\n * Used by both server (DateTimeBuilder) and client (comparison feature)\n *\n * These utilities handle:\n * - Relative date range parsing (today, yesterday, last 7 days, this month, etc.)\n * - Prior period calculation for comparison features\n * - Date formatting for cube queries\n */\n\n/**\n * Parse relative date range expressions like \"today\", \"yesterday\", \"last 7 days\", \"this month\", etc.\n * Returns start/end dates in UTC\n *\n * Handles all 14 DATE_RANGE_OPTIONS from the client:\n * - today, yesterday\n * - last 7 days, last 14 days, last 30 days\n * - last N days/weeks/months/years (legacy patterns)\n * - this week, last week\n * - this month, last month\n * - this quarter, last quarter\n * - this year, last year\n * - last 12 months\n */\nexport function parseRelativeDateRange(dateRange: string): { start: Date; end: Date } | null {\n const now = new Date()\n const lowerRange = dateRange.toLowerCase().trim()\n\n // Extract UTC date components for consistent calculations\n const utcYear = now.getUTCFullYear()\n const utcMonth = now.getUTCMonth()\n const utcDate = now.getUTCDate()\n const utcDay = now.getUTCDay()\n\n // Handle \"today\"\n if (lowerRange === 'today') {\n const start = new Date(now)\n start.setUTCHours(0, 0, 0, 0)\n const end = new Date(now)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"yesterday\"\n if (lowerRange === 'yesterday') {\n const start = new Date(now)\n start.setUTCDate(utcDate - 1)\n start.setUTCHours(0, 0, 0, 0)\n const end = new Date(now)\n end.setUTCDate(utcDate - 1)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"this week\" (Monday to Sunday)\n if (lowerRange === 'this week') {\n const mondayOffset = utcDay === 0 ? -6 : 1 - utcDay // If Sunday, go back 6 days, otherwise go to Monday\n const start = new Date(now)\n start.setUTCDate(utcDate + mondayOffset)\n start.setUTCHours(0, 0, 0, 0)\n\n const end = new Date(start)\n end.setUTCDate(start.getUTCDate() + 6) // Sunday\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"this month\"\n if (lowerRange === 'this month') {\n const start = new Date(Date.UTC(utcYear, utcMonth, 1, 0, 0, 0, 0))\n const end = new Date(Date.UTC(utcYear, utcMonth + 1, 0, 23, 59, 59, 999))\n return { start, end }\n }\n\n // Handle \"this quarter\"\n if (lowerRange === 'this quarter') {\n const quarter = Math.floor(utcMonth / 3)\n const start = new Date(Date.UTC(utcYear, quarter * 3, 1, 0, 0, 0, 0))\n const end = new Date(Date.UTC(utcYear, quarter * 3 + 3, 0, 23, 59, 59, 999))\n return { start, end }\n }\n\n // Handle \"this year\"\n if (lowerRange === 'this year') {\n const start = new Date(Date.UTC(utcYear, 0, 1, 0, 0, 0, 0))\n const end = new Date(Date.UTC(utcYear, 11, 31, 23, 59, 59, 999))\n return { start, end }\n }\n\n // Handle \"last N days\" pattern\n const lastDaysMatch = lowerRange.match(/^last\\s+(\\d+)\\s+days?$/)\n if (lastDaysMatch) {\n const days = parseInt(lastDaysMatch[1], 10)\n const start = new Date(now)\n start.setUTCDate(utcDate - days + 1) // Include today in the count\n start.setUTCHours(0, 0, 0, 0)\n const end = new Date(now)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"last N weeks\" pattern\n const lastWeeksMatch = lowerRange.match(/^last\\s+(\\d+)\\s+weeks?$/)\n if (lastWeeksMatch) {\n const weeks = parseInt(lastWeeksMatch[1], 10)\n const days = weeks * 7\n const start = new Date(now)\n start.setUTCDate(utcDate - days + 1) // Include today in the count\n start.setUTCHours(0, 0, 0, 0)\n const end = new Date(now)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"last week\" (previous Monday to Sunday)\n if (lowerRange === 'last week') {\n const lastMondayOffset = utcDay === 0 ? -13 : -6 - utcDay // Go to previous Monday\n const start = new Date(now)\n start.setUTCDate(utcDate + lastMondayOffset)\n start.setUTCHours(0, 0, 0, 0)\n\n const end = new Date(start)\n end.setUTCDate(start.getUTCDate() + 6) // Previous Sunday\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"last month\"\n if (lowerRange === 'last month') {\n const start = new Date(Date.UTC(utcYear, utcMonth - 1, 1, 0, 0, 0, 0))\n const end = new Date(Date.UTC(utcYear, utcMonth, 0, 23, 59, 59, 999))\n return { start, end }\n }\n\n // Handle \"last quarter\"\n if (lowerRange === 'last quarter') {\n const currentQuarter = Math.floor(utcMonth / 3)\n const lastQuarter = currentQuarter === 0 ? 3 : currentQuarter - 1\n const year = currentQuarter === 0 ? utcYear - 1 : utcYear\n const start = new Date(Date.UTC(year, lastQuarter * 3, 1, 0, 0, 0, 0))\n const end = new Date(Date.UTC(year, lastQuarter * 3 + 3, 0, 23, 59, 59, 999))\n return { start, end }\n }\n\n // Handle \"last year\"\n if (lowerRange === 'last year') {\n const start = new Date(Date.UTC(utcYear - 1, 0, 1, 0, 0, 0, 0))\n const end = new Date(Date.UTC(utcYear - 1, 11, 31, 23, 59, 59, 999))\n return { start, end }\n }\n\n // Handle \"last 12 months\" (rolling 12 months)\n if (lowerRange === 'last 12 months') {\n const start = new Date(Date.UTC(utcYear, utcMonth - 11, 1, 0, 0, 0, 0))\n const end = new Date(now)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"last N months\" pattern (legacy support)\n const lastMonthsMatch = lowerRange.match(/^last\\s+(\\d+)\\s+months?$/)\n if (lastMonthsMatch) {\n const months = parseInt(lastMonthsMatch[1], 10)\n const start = new Date(Date.UTC(utcYear, utcMonth - months + 1, 1, 0, 0, 0, 0))\n const end = new Date(now)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n // Handle \"last N years\" pattern (legacy support)\n const lastYearsMatch = lowerRange.match(/^last\\s+(\\d+)\\s+years?$/)\n if (lastYearsMatch) {\n const years = parseInt(lastYearsMatch[1], 10)\n const start = new Date(Date.UTC(utcYear - years, 0, 1, 0, 0, 0, 0))\n const end = new Date(now)\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n\n return null\n}\n\n/**\n * Parse a date range (string or array) to start/end dates\n * Handles both relative date expressions and explicit date arrays\n */\nexport function parseDateRange(dateRange: string | string[]): { start: Date; end: Date } | null {\n if (Array.isArray(dateRange)) {\n if (dateRange.length < 2) return null\n const start = new Date(dateRange[0])\n const end = new Date(dateRange[1])\n if (isNaN(start.getTime()) || isNaN(end.getTime())) return null\n // Normalize end to end of day\n end.setUTCHours(23, 59, 59, 999)\n return { start, end }\n }\n return parseRelativeDateRange(dateRange)\n}\n\n/**\n * Format date as YYYY-MM-DD for cube queries\n */\nexport function formatDateForCube(date: Date): string {\n return date.toISOString().split('T')[0]\n}\n\n/**\n * Calculate the prior period (same length, immediately before the current period)\n *\n * Example:\n * Current: Jan 1-7 (7 days)\n * Prior: Dec 25-31 (7 days)\n */\nexport function calculatePriorPeriod(currentStart: Date, currentEnd: Date): { start: Date; end: Date } {\n // Calculate period length in days (inclusive of both start and end dates)\n const periodLengthMs = currentEnd.getTime() - currentStart.getTime()\n const periodLengthDays = Math.ceil(periodLengthMs / (1000 * 60 * 60 * 24))\n\n // Prior period ends the day before current period starts\n const priorEnd = new Date(currentStart)\n priorEnd.setUTCDate(priorEnd.getUTCDate() - 1)\n priorEnd.setUTCHours(23, 59, 59, 999)\n\n // Prior period starts (periodLengthDays - 1) days before priorEnd\n const priorStart = new Date(priorEnd)\n priorStart.setUTCDate(priorStart.getUTCDate() - periodLengthDays + 1)\n priorStart.setUTCHours(0, 0, 0, 0)\n\n return { start: priorStart, end: priorEnd }\n}\n","/**\n * Filter Manipulation Utilities for AnalysisBuilder\n *\n * Functions for searching, modifying, and removing filters from filter arrays.\n * These handle both simple filters and nested group filters (AND/OR).\n */\n\nimport type { Filter } from '../../../types'\nimport { parseDateRange, calculatePriorPeriod, formatDateForCube } from '../../../../shared/date-utils'\n\n/**\n * Find date filter for a specific time dimension field\n * Recursively searches filters (including nested and/or groups)\n * Handles both UI format ({type: 'and'/'or', filters: [...]}) and simple filters\n */\nexport function findDateFilterForField(\n filters: Filter[],\n field: string\n): { dateRange: string | string[] } | undefined {\n for (const filter of filters) {\n // Check for UI GroupFilter format: {type: 'and'/'or', filters: [...]}\n if ('type' in filter && 'filters' in filter) {\n const groupFilter = filter as { type: 'and' | 'or'; filters: Filter[] }\n const nested = findDateFilterForField(groupFilter.filters, field)\n if (nested) return nested\n } else if ('member' in filter) {\n // Simple filter with member, operator, dateRange\n const simple = filter as { member: string; operator?: string; dateRange?: string | string[] }\n if (simple.member === field && simple.operator === 'inDateRange' && simple.dateRange) {\n return { dateRange: simple.dateRange }\n }\n }\n }\n return undefined\n}\n\n/**\n * Build compareDateRange for a time dimension based on its date filter\n * When comparison is enabled, returns [[currentStart, currentEnd], [priorStart, priorEnd]]\n */\nexport function buildCompareDateRangeFromFilter(\n timeDimensionField: string,\n filters: Filter[]\n): [string, string][] | undefined {\n // Find the date filter for this time dimension\n const dateFilter = findDateFilterForField(filters, timeDimensionField)\n if (!dateFilter?.dateRange) return undefined\n\n // Parse the current range using shared utility\n const currentPeriod = parseDateRange(dateFilter.dateRange)\n if (!currentPeriod) return undefined\n\n // Calculate prior period using shared utility\n const priorPeriod = calculatePriorPeriod(currentPeriod.start, currentPeriod.end)\n\n return [\n [formatDateForCube(currentPeriod.start), formatDateForCube(currentPeriod.end)],\n [formatDateForCube(priorPeriod.start), formatDateForCube(priorPeriod.end)]\n ]\n}\n\n/**\n * Remove date filter for a specific field from filters array\n * Returns a new array with the filter removed (immutable)\n */\nexport function removeComparisonDateFilter(filters: Filter[], field: string): Filter[] {\n return filters.reduce<Filter[]>((acc, filter) => {\n // Check for UI GroupFilter format: {type: 'and'/'or', filters: [...]}\n if ('type' in filter && 'filters' in filter) {\n const groupFilter = filter as { type: 'and' | 'or'; filters: Filter[] }\n const cleanedSubFilters = removeComparisonDateFilter(groupFilter.filters, field)\n // Only keep the group if it still has filters\n if (cleanedSubFilters.length > 0) {\n acc.push({ type: groupFilter.type, filters: cleanedSubFilters } as Filter)\n }\n } else if ('member' in filter) {\n // Simple filter - skip if it's the date filter for this field\n const simple = filter as { member: string; operator?: string; dateRange?: string | string[] }\n if (!(simple.member === field && simple.operator === 'inDateRange')) {\n acc.push(filter)\n }\n } else {\n acc.push(filter)\n }\n return acc\n }, [])\n}\n","/**\n * Query Building Utilities for AnalysisBuilder\n *\n * Functions for constructing CubeQuery objects from builder state.\n */\n\nimport type { CubeQuery, Filter } from '../../../types'\nimport type { MetricItem, BreakdownItem } from '../types'\nimport { removeComparisonDateFilter, buildCompareDateRangeFromFilter } from './filterUtils'\n\n/**\n * Convert metrics and breakdowns to CubeQuery format\n * Handles comparison mode by building compareDateRange for time dimensions\n */\nexport function buildCubeQuery(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n filters: Filter[],\n order?: Record<string, 'asc' | 'desc'>,\n preserveComparisonFilters: boolean = false\n): CubeQuery {\n // Find time dimensions with comparison enabled\n const comparisonFields = breakdowns\n .filter((b) => b.isTimeDimension && b.enableComparison)\n .map((b) => b.field)\n\n // Remove date filters for comparison-enabled time dimensions\n // (compareDateRange will handle the date ranges instead)\n let filteredFilters = filters\n if (!preserveComparisonFilters) {\n for (const field of comparisonFields) {\n filteredFilters = removeComparisonDateFilter(filteredFilters, field)\n }\n }\n\n const query: CubeQuery = {\n measures: metrics.map((m) => m.field),\n dimensions: breakdowns.filter((b) => !b.isTimeDimension).map((b) => b.field),\n timeDimensions: breakdowns\n .filter((b) => b.isTimeDimension)\n .map((b) => {\n const td: {\n dimension: string\n granularity: string\n compareDateRange?: [string, string][]\n } = {\n dimension: b.field,\n granularity: b.granularity || 'day'\n }\n\n // If comparison is enabled, build compareDateRange from the ORIGINAL filter\n if (b.enableComparison) {\n const compareDateRange = buildCompareDateRangeFromFilter(b.field, filters)\n if (compareDateRange) {\n td.compareDateRange = compareDateRange\n }\n }\n\n return td\n }),\n filters: filteredFilters.length > 0 ? filteredFilters : undefined,\n order: order && Object.keys(order).length > 0 ? order : undefined\n }\n\n // Clean up empty arrays\n if (query.measures?.length === 0) delete query.measures\n if (query.dimensions?.length === 0) delete query.dimensions\n if (query.timeDimensions?.length === 0) delete query.timeDimensions\n\n return query\n}\n\n/**\n * Check if a query has any content\n */\nexport function hasQueryContent(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n filters: Filter[]\n): boolean {\n return metrics.length > 0 || breakdowns.length > 0 || filters.length > 0\n}\n","/**\n * State Persistence Utilities for AnalysisBuilder\n *\n * Functions for saving and loading builder state from localStorage.\n */\n\nimport type { Filter } from '../../../types'\nimport type { MetricItem, BreakdownItem, AnalysisBuilderState, AnalysisBuilderStorageState } from '../types'\n\n// Storage key for localStorage persistence\nexport const STORAGE_KEY = 'drizzle-cube-analysis-builder-state'\n\n/**\n * Create initial empty state for AnalysisBuilder\n *\n * Note: Only client-side configuration state is stored.\n * Server state (execution results, loading, errors) is managed by TanStack Query.\n */\nexport function createInitialState(): AnalysisBuilderState {\n return {\n metrics: [],\n breakdowns: [],\n filters: [],\n order: undefined,\n validationStatus: 'idle',\n validationError: null,\n }\n}\n\n/**\n * Load all state from localStorage once (to avoid repeated parsing)\n */\nexport function loadInitialStateFromStorage(\n disableLocalStorage: boolean\n): AnalysisBuilderStorageState | null {\n if (disableLocalStorage) return null\n\n try {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved) {\n return JSON.parse(saved) as AnalysisBuilderStorageState\n }\n } catch {\n // Ignore parse errors\n }\n return null\n}\n\n/**\n * Save state to localStorage\n */\nexport function saveStateToStorage(state: {\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n chartType: string\n chartConfig: object\n displayConfig: object\n activeView: string\n}): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(state))\n } catch {\n // Ignore errors\n }\n}\n\n/**\n * Load state from localStorage (legacy format for backward compatibility)\n */\nexport function loadStateFromStorage(): {\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n chartType: string\n chartConfig: object\n displayConfig: object\n activeView: string\n} | null {\n try {\n const stored = localStorage.getItem(STORAGE_KEY)\n if (stored) {\n return JSON.parse(stored)\n }\n } catch {\n // Ignore errors\n }\n return null\n}\n\n/**\n * Clear state from localStorage\n */\nexport function clearStateFromStorage(): void {\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Ignore errors\n }\n}\n","/**\n * Field Metadata Utilities for AnalysisBuilder\n *\n * Functions for working with field metadata from the schema.\n */\n\nimport type { FieldOption, FieldType } from '../types'\nimport type { MetaResponse, MetaField } from '../../../shared/types'\n\n/**\n * Get cube name from a field name (e.g., \"Employees.count\" -> \"Employees\")\n */\nexport function getCubeNameFromField(fieldName: string): string {\n return fieldName.split('.')[0]\n}\n\n/**\n * Get field short name from full name (e.g., \"Employees.count\" -> \"count\")\n */\nexport function getFieldShortName(fieldName: string): string {\n const parts = fieldName.split('.')\n return parts.length > 1 ? parts.slice(1).join('.') : fieldName\n}\n\n/**\n * Find field metadata from schema\n */\nexport function findFieldInSchema(\n fieldName: string,\n schema: MetaResponse | null\n): { field: MetaField; cubeName: string; fieldType: FieldType } | null {\n if (!schema) return null\n\n for (const cube of schema.cubes) {\n // Check measures\n const measure = cube.measures.find((m) => m.name === fieldName)\n if (measure) {\n return { field: measure, cubeName: cube.name, fieldType: 'measure' }\n }\n\n // Check dimensions\n const dimension = cube.dimensions.find((d) => d.name === fieldName)\n if (dimension) {\n return {\n field: dimension,\n cubeName: cube.name,\n fieldType: dimension.type === 'time' ? 'timeDimension' : 'dimension'\n }\n }\n }\n\n return null\n}\n\n/**\n * Get display title for a field\n */\nexport function getFieldTitle(fieldName: string, schema: MetaResponse | null): string {\n const found = findFieldInSchema(fieldName, schema)\n if (found) {\n return found.field.title || found.field.shortTitle || fieldName\n }\n return fieldName\n}\n\n/**\n * Determine field type from metadata\n */\nexport function getFieldType(field: MetaField): FieldType {\n if (field.type === 'time') return 'timeDimension'\n // Measures typically have aggregation types\n if (['count', 'countDistinct', 'sum', 'avg', 'min', 'max', 'runningTotal', 'countDistinctApprox'].includes(field.type)) {\n return 'measure'\n }\n return 'dimension'\n}\n\n/**\n * Convert schema to flat list of field options\n */\nexport function schemaToFieldOptions(\n schema: MetaResponse | null,\n mode: 'metrics' | 'breakdown' | 'filter'\n): FieldOption[] {\n if (!schema) return []\n\n const options: FieldOption[] = []\n\n for (const cube of schema.cubes) {\n if (mode === 'metrics') {\n // Add measures only\n for (const measure of cube.measures) {\n options.push({\n name: measure.name,\n title: measure.title || measure.shortTitle || measure.name,\n shortTitle: measure.shortTitle || measure.title || measure.name,\n type: measure.type,\n description: measure.description,\n cubeName: cube.name,\n fieldType: 'measure'\n })\n }\n } else if (mode === 'breakdown') {\n // Add dimensions only (both regular and time)\n for (const dimension of cube.dimensions) {\n const isTime = dimension.type === 'time'\n options.push({\n name: dimension.name,\n title: dimension.title || dimension.shortTitle || dimension.name,\n shortTitle: dimension.shortTitle || dimension.title || dimension.name,\n type: dimension.type,\n description: dimension.description,\n cubeName: cube.name,\n fieldType: isTime ? 'timeDimension' : 'dimension'\n })\n }\n } else {\n // 'filter' mode - add BOTH measures AND dimensions\n // Add measures first\n for (const measure of cube.measures) {\n options.push({\n name: measure.name,\n title: measure.title || measure.shortTitle || measure.name,\n shortTitle: measure.shortTitle || measure.title || measure.name,\n type: measure.type,\n description: measure.description,\n cubeName: cube.name,\n fieldType: 'measure'\n })\n }\n // Add dimensions (both regular and time)\n for (const dimension of cube.dimensions) {\n const isTime = dimension.type === 'time'\n options.push({\n name: dimension.name,\n title: dimension.title || dimension.shortTitle || dimension.name,\n shortTitle: dimension.shortTitle || dimension.title || dimension.name,\n type: dimension.type,\n description: dimension.description,\n cubeName: cube.name,\n fieldType: isTime ? 'timeDimension' : 'dimension'\n })\n }\n }\n }\n\n return options\n}\n\n/**\n * Filter field options by search term\n */\nexport function filterFieldOptions(\n options: FieldOption[],\n searchTerm: string,\n selectedCube?: string | null\n): FieldOption[] {\n let filtered = options\n\n // Filter by cube if selected\n if (selectedCube && selectedCube !== 'all') {\n filtered = filtered.filter((opt) => opt.cubeName === selectedCube)\n }\n\n // Filter by search term\n if (searchTerm.trim()) {\n const term = searchTerm.toLowerCase()\n filtered = filtered.filter(\n (opt) =>\n opt.name.toLowerCase().includes(term) ||\n opt.title.toLowerCase().includes(term) ||\n (opt.description?.toLowerCase().includes(term) ?? false)\n )\n }\n\n return filtered\n}\n\n/**\n * Group field options by cube\n */\nexport function groupFieldsByCube(options: FieldOption[]): Map<string, FieldOption[]> {\n const grouped = new Map<string, FieldOption[]>()\n\n for (const option of options) {\n const existing = grouped.get(option.cubeName) || []\n existing.push(option)\n grouped.set(option.cubeName, existing)\n }\n\n return grouped\n}\n\n/**\n * Get list of cube names from schema\n */\nexport function getCubeNames(schema: MetaResponse | null): string[] {\n if (!schema) return []\n return schema.cubes.map((cube) => cube.name)\n}\n\n/**\n * Get cube title by name\n */\nexport function getCubeTitle(cubeName: string, schema: MetaResponse | null): string {\n if (!schema) return cubeName\n const cube = schema.cubes.find((c) => c.name === cubeName)\n return cube?.title || cubeName\n}\n","/**\n * Recent Fields Storage Utilities for AnalysisBuilder\n *\n * Functions for tracking and retrieving recently used fields.\n */\n\nimport type { FieldOption, RecentFieldsStorage } from '../types'\nimport type { MetaResponse } from '../../../shared/types'\nimport { schemaToFieldOptions } from './fieldUtils'\n\nconst RECENT_FIELDS_KEY = 'drizzle-cube-recent-fields'\nconst MAX_RECENT_FIELDS = 10\n\n/**\n * Get recent fields from localStorage\n */\nexport function getRecentFields(): RecentFieldsStorage {\n try {\n const stored = localStorage.getItem(RECENT_FIELDS_KEY)\n if (stored) {\n return JSON.parse(stored)\n }\n } catch {\n // Ignore errors\n }\n return { metrics: [], breakdowns: [] }\n}\n\n/**\n * Add a field to recent fields\n */\nexport function addRecentField(fieldName: string, mode: 'metrics' | 'breakdowns'): void {\n try {\n const recent = getRecentFields()\n const list = recent[mode]\n\n // Remove if already exists\n const filtered = list.filter((f) => f !== fieldName)\n\n // Add to front\n filtered.unshift(fieldName)\n\n // Limit size\n recent[mode] = filtered.slice(0, MAX_RECENT_FIELDS)\n\n localStorage.setItem(RECENT_FIELDS_KEY, JSON.stringify(recent))\n } catch {\n // Ignore errors\n }\n}\n\n/**\n * Get recent field options from schema\n */\nexport function getRecentFieldOptions(\n schema: MetaResponse | null,\n mode: 'metrics' | 'breakdown' | 'filter',\n recentFieldNames: string[]\n): FieldOption[] {\n if (!schema || recentFieldNames.length === 0) return []\n\n const allOptions = schemaToFieldOptions(schema, mode)\n const recentOptions: FieldOption[] = []\n\n for (const fieldName of recentFieldNames) {\n const option = allOptions.find((opt) => opt.name === fieldName)\n if (option) {\n recentOptions.push(option)\n }\n }\n\n return recentOptions\n}\n","/**\n * Smart Chart Defaulting System\n *\n * Provides intelligent chart type selection and configuration based on\n * the user's current metrics and breakdowns selection.\n */\n\nimport type { ChartType, ChartAxisConfig } from '../types'\nimport type { MetricItem, BreakdownItem } from '../components/AnalysisBuilder/types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Result of smart chart defaults calculation\n */\nexport interface SmartChartDefaults {\n /** The recommended chart type */\n chartType: ChartType\n /** The auto-configured chart axis settings */\n chartConfig: ChartAxisConfig\n}\n\n/**\n * Availability status for a chart type\n */\nexport interface ChartAvailability {\n /** Whether the chart type can be used with current selections */\n available: boolean\n /** Reason why the chart is unavailable (for tooltip) */\n reason?: string\n}\n\n/**\n * Map of chart type availability statuses\n */\nexport type ChartAvailabilityMap = Record<ChartType, ChartAvailability>\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if a breakdown is a time dimension\n */\nfunction isTimeDimension(breakdown: BreakdownItem): boolean {\n return breakdown.isTimeDimension\n}\n\n/**\n * Get the first time dimension from breakdowns, if any\n */\nfunction getFirstTimeDimension(breakdowns: BreakdownItem[]): BreakdownItem | undefined {\n return breakdowns.find(isTimeDimension)\n}\n\n/**\n * Get the first non-time dimension from breakdowns, if any\n */\nfunction getFirstDimension(breakdowns: BreakdownItem[]): BreakdownItem | undefined {\n return breakdowns.find((b) => !b.isTimeDimension)\n}\n\n/**\n * Get all non-time dimensions\n */\nfunction getDimensions(breakdowns: BreakdownItem[]): BreakdownItem[] {\n return breakdowns.filter((b) => !b.isTimeDimension)\n}\n\n/**\n * Get all time dimensions\n */\nfunction getTimeDimensions(breakdowns: BreakdownItem[]): BreakdownItem[] {\n return breakdowns.filter(isTimeDimension)\n}\n\n// ============================================================================\n// Chart Availability\n// ============================================================================\n\n/**\n * Check if a specific chart type is available given current selections\n */\nexport function getChartAvailability(\n chartType: ChartType,\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAvailability {\n const measureCount = metrics.length\n const dimensionCount = getDimensions(breakdowns).length\n const timeDimensionCount = getTimeDimensions(breakdowns).length\n const totalBreakdowns = breakdowns.length\n\n switch (chartType) {\n // Always available charts\n case 'table':\n case 'markdown':\n return { available: true }\n\n // Measure-only charts (KPI Number, KPI Text)\n case 'kpiNumber':\n case 'kpiText':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n return { available: true }\n\n // Bar chart - needs dimension for categories + measure for values\n case 'bar':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires at least 1 breakdown for categories' }\n }\n return { available: true }\n\n // KPI Delta - needs dimension for ordering + measure for values\n case 'kpiDelta':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires at least 1 breakdown for ordering' }\n }\n return { available: true }\n\n // Line and area charts - need dimension/time + measure\n case 'line':\n case 'area':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires a breakdown (dimension or time)' }\n }\n return { available: true }\n\n // Pie chart - needs dimension (not time) + measure\n case 'pie':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires 1 dimension (not time dimension)' }\n }\n return { available: true }\n\n // Scatter - needs measure + any breakdown\n case 'scatter':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n // Scatter can work with just measures (x and y from different measures)\n // or with dimension + measure\n if (measureCount < 2 && totalBreakdowns < 1) {\n return { available: false, reason: 'Requires 2 measures or 1 measure + 1 breakdown' }\n }\n return { available: true }\n\n // Bubble - needs 2+ measures and 1+ breakdown (dimension or time dimension for series)\n case 'bubble':\n if (measureCount < 2) {\n return { available: false, reason: 'Requires at least 2 measures' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires at least 1 breakdown for series grouping' }\n }\n return { available: true }\n\n // Radar - needs dimension + measure\n case 'radar':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Radial Bar - needs dimension + measure\n case 'radialBar':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Treemap - needs dimension + measure\n case 'treemap':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Activity Grid - needs time dimension + measure\n case 'activityGrid':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (timeDimensionCount < 1) {\n return { available: false, reason: 'Requires a time dimension' }\n }\n return { available: true }\n\n default:\n // Unknown chart type - assume available\n return { available: true }\n }\n}\n\n/**\n * Get availability for all chart types\n */\nexport function getAllChartAvailability(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAvailabilityMap {\n // Chart types in alphabetical order (matching ChartTypeSelector display)\n const chartTypes: ChartType[] = [\n 'activityGrid',\n 'area',\n 'bar',\n 'bubble',\n 'kpiDelta',\n 'kpiNumber',\n 'kpiText',\n 'line',\n 'markdown',\n 'pie',\n 'radar',\n 'radialBar',\n 'scatter',\n 'table',\n 'treemap'\n ]\n\n const availability: Partial<ChartAvailabilityMap> = {}\n for (const chartType of chartTypes) {\n availability[chartType] = getChartAvailability(chartType, metrics, breakdowns)\n }\n\n return availability as ChartAvailabilityMap\n}\n\n// ============================================================================\n// Smart Chart Type Selection\n// ============================================================================\n\n/**\n * Select the best chart type based on current metrics and breakdowns\n *\n * Priority order:\n * 1. If current chart type is still valid, keep it (preserve user intent)\n * 2. If current chart becomes invalid, switch to best alternative:\n * - Has time dimension → line\n * - Has dimension + measure → bar\n * - Has measures only → bar (or kpiNumber if single measure + no breakdowns)\n * - No fields → keep current\n */\nexport function selectBestChartType(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n currentChartType: ChartType\n): ChartType {\n // Check if current chart type is still valid\n const currentAvailability = getChartAvailability(currentChartType, metrics, breakdowns)\n if (currentAvailability.available) {\n return currentChartType\n }\n\n // No fields selected - keep current\n if (metrics.length === 0 && breakdowns.length === 0) {\n return currentChartType\n }\n\n const hasTimeDimension = getTimeDimensions(breakdowns).length > 0\n const hasDimension = getDimensions(breakdowns).length > 0\n const hasMeasure = metrics.length > 0\n\n // Priority selection logic\n if (hasTimeDimension && hasMeasure) {\n // Time series data → line chart\n return 'line'\n }\n\n if (hasDimension && hasMeasure) {\n // Categorical data with measures → bar chart\n return 'bar'\n }\n\n if (hasMeasure && !hasDimension && !hasTimeDimension) {\n // Measures only, no breakdowns → KPI number (works with just measures)\n return 'kpiNumber'\n }\n\n // Fallback to table as most versatile (works with any combination)\n return 'table'\n}\n\n// ============================================================================\n// Smart Chart Config Defaults\n// ============================================================================\n\n/**\n * Get smart default chart configuration based on chart type and selections\n */\nexport function getSmartChartDefaults(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n currentChartType: ChartType\n): SmartChartDefaults {\n // First, determine the best chart type\n const chartType = selectBestChartType(metrics, breakdowns, currentChartType)\n\n // Then, auto-configure the chart axes based on chart type\n const chartConfig = buildChartConfig(chartType, metrics, breakdowns)\n\n return { chartType, chartConfig }\n}\n\n/**\n * Build optimal chart configuration for a given chart type\n */\nfunction buildChartConfig(\n chartType: ChartType,\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAxisConfig {\n const timeDimension = getFirstTimeDimension(breakdowns)\n const dimension = getFirstDimension(breakdowns)\n const dimensions = getDimensions(breakdowns)\n const allBreakdowns = breakdowns\n\n switch (chartType) {\n case 'line':\n case 'area':\n // Line/Area: xAxis = first time dimension (prefer) or dimension\n // yAxis = all measures, series = optional second dimension\n return {\n xAxis: timeDimension\n ? [timeDimension.field]\n : dimension\n ? [dimension.field]\n : [],\n yAxis: metrics.map((m) => m.field),\n series:\n dimensions.length > 1\n ? [dimensions[1].field]\n : dimension && timeDimension\n ? [dimension.field]\n : []\n }\n\n case 'bar':\n // Bar: xAxis = first dimension (prefer non-time), yAxis = all measures\n return {\n xAxis: dimension\n ? [dimension.field]\n : timeDimension\n ? [timeDimension.field]\n : [],\n yAxis: metrics.map((m) => m.field),\n series:\n dimensions.length > 1\n ? [dimensions[1].field]\n : timeDimension && dimension\n ? [timeDimension.field]\n : []\n }\n\n case 'pie':\n // Pie: xAxis = first dimension (exactly 1), yAxis = first measure (exactly 1)\n return {\n xAxis: dimension ? [dimension.field] : [],\n yAxis: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'scatter':\n // Scatter: xAxis = first dimension or measure, yAxis = first/second measure\n if (metrics.length >= 2) {\n return {\n xAxis: [metrics[0].field],\n yAxis: [metrics[1].field],\n series: dimension ? [dimension.field] : []\n }\n }\n return {\n xAxis: allBreakdowns.length > 0 ? [allBreakdowns[0].field] : [],\n yAxis: metrics.length > 0 ? [metrics[0].field] : [],\n series: dimensions.length > 1 ? [dimensions[1].field] : []\n }\n\n case 'bubble':\n // Bubble: xAxis = first measure, yAxis = second measure, sizeField = third measure (or second if only 2)\n // series = first breakdown (dimension or time dimension) for grouping/coloring\n return {\n xAxis: metrics.length > 0 ? [metrics[0].field] : [],\n yAxis: metrics.length > 1 ? [metrics[1].field] : [],\n sizeField: metrics.length > 2 ? metrics[2].field : metrics.length > 1 ? metrics[1].field : undefined,\n series: dimension ? [dimension.field] : timeDimension ? [timeDimension.field] : []\n }\n\n case 'radar':\n case 'radialBar':\n case 'treemap':\n // These all use dimension for categories and measure for values\n return {\n xAxis: dimension ? [dimension.field] : [],\n yAxis: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'activityGrid':\n // Activity Grid: dateField = time dimension, valueField = measure\n return {\n dateField: timeDimension ? [timeDimension.field] : [],\n valueField: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'kpiNumber':\n case 'kpiDelta':\n case 'kpiText':\n // KPI charts: just need the measure\n return {\n yAxis: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'table':\n // Table: include all fields\n return {\n xAxis: [\n ...breakdowns.map((b) => b.field),\n ...metrics.map((m) => m.field)\n ]\n }\n\n case 'markdown':\n // Markdown doesn't need chart config\n return {}\n\n default:\n // Default fallback - x = first breakdown, y = all measures\n return {\n xAxis: allBreakdowns.length > 0 ? [allBreakdowns[0].field] : [],\n yAxis: metrics.map((m) => m.field)\n }\n }\n}\n\n// ============================================================================\n// Update Logic for AnalysisBuilder\n// ============================================================================\n\n/**\n * Determine if chart type should be auto-switched based on selections change\n *\n * Returns the new chart type if a switch is recommended, or null if no change needed.\n *\n * @param metrics - Current metrics selection\n * @param breakdowns - Current breakdowns selection\n * @param currentChartType - Current chart type\n * @param userManuallySelected - Whether user manually selected the current chart type\n */\nexport function shouldAutoSwitchChartType(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n currentChartType: ChartType,\n userManuallySelected: boolean\n): ChartType | null {\n // If user manually selected this chart type, only switch if it becomes invalid\n if (userManuallySelected) {\n const availability = getChartAvailability(currentChartType, metrics, breakdowns)\n if (availability.available) {\n return null // Keep user's choice\n }\n }\n\n // Check if a better chart type should be used\n const recommendedType = selectBestChartType(metrics, breakdowns, currentChartType)\n\n // Only suggest switch if recommended type is different\n if (recommendedType !== currentChartType) {\n return recommendedType\n }\n\n return null\n}\n\n/**\n * Check if a chart config field references valid fields from metrics/breakdowns\n */\nfunction isValidConfigField(\n fieldValue: string | string[] | undefined,\n validFields: Set<string>\n): boolean {\n if (!fieldValue) return false\n if (Array.isArray(fieldValue)) {\n return fieldValue.length > 0 && fieldValue.every((f) => validFields.has(f))\n }\n return validFields.has(fieldValue)\n}\n\n/**\n * Merge existing chart config with smart defaults\n * Only fills in missing or invalid fields, preserves valid existing config\n */\nexport function mergeChartConfigWithDefaults(\n existingConfig: ChartAxisConfig,\n smartDefaults: ChartAxisConfig,\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAxisConfig {\n // Build set of valid field names\n const validFields = new Set<string>([\n ...metrics.map((m) => m.field),\n ...breakdowns.map((b) => b.field)\n ])\n\n const result: ChartAxisConfig = {}\n\n // For each key in smart defaults, use existing value if valid, otherwise use default\n const allKeys = new Set([\n ...Object.keys(existingConfig),\n ...Object.keys(smartDefaults)\n ]) as Set<keyof ChartAxisConfig>\n\n for (const key of allKeys) {\n const existingValue = existingConfig[key]\n const defaultValue = smartDefaults[key]\n\n // Check if existing value is valid\n if (isValidConfigField(existingValue as string | string[] | undefined, validFields)) {\n // Keep existing valid config\n result[key] = existingValue as any\n } else if (defaultValue !== undefined) {\n // Use smart default\n result[key] = defaultValue as any\n }\n // If neither exists or is valid, leave undefined\n }\n\n return result\n}\n","/**\n * AnalysisBuilder Zustand Store (Instance-based)\n *\n * Centralized state management for AnalysisBuilder, consolidating:\n * - Query state (multi-query support with per-query metrics, breakdowns, filters)\n * - Chart configuration (type, axis config, display config)\n * - UI state (tabs, views, modals)\n * - AI state\n *\n * KEY ARCHITECTURE: Instance-based stores\n * - Each AnalysisBuilder component gets its own store instance\n * - Standalone mode: Uses localStorage persistence\n * - Modal/portlet editing mode: No persistence, initializes from props\n *\n * Uses Zustand's createStore (factory) instead of create (singleton).\n * Store is provided via React Context.\n */\n\nimport { createContext, useContext, useRef, type ReactNode } from 'react'\nimport { createStore, useStore, type StoreApi } from 'zustand'\nimport { devtools, persist, subscribeWithSelector } from 'zustand/middleware'\nimport type {\n Filter,\n SimpleFilter,\n ChartType,\n ChartAxisConfig,\n ChartDisplayConfig,\n CubeQuery,\n QueryMergeStrategy,\n MultiQueryConfig,\n FunnelBindingKey,\n FunnelConfig,\n} from '../types'\nimport type {\n AnalysisBuilderState,\n MetricItem,\n BreakdownItem,\n QueryPanelTab,\n AIState,\n} from '../components/AnalysisBuilder/types'\nimport {\n generateId,\n generateMetricLabel,\n createInitialState,\n buildCubeQuery,\n STORAGE_KEY,\n} from '../components/AnalysisBuilder/utils'\nimport { buildFunnelConfigFromQueries } from '../utils/funnelExecution'\nimport { findDateFilterForField } from '../components/AnalysisBuilder/utils'\nimport { convertDateRangeTypeToValue } from '../shared/utils'\nimport { getSmartChartDefaults } from '../shared/chartDefaults'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Field modal mode for field search\n */\nexport type FieldModalMode = 'metrics' | 'breakdown'\n\n/**\n * Complete store state interface\n */\nexport interface AnalysisBuilderStoreState {\n // =========================================================================\n // Query State (Multi-query support)\n // =========================================================================\n /** Array of query states (one per tab) */\n queryStates: AnalysisBuilderState[]\n /** Index of the currently active query tab */\n activeQueryIndex: number\n /** Strategy for merging multi-query results */\n mergeStrategy: QueryMergeStrategy\n\n // =========================================================================\n // Chart Configuration\n // =========================================================================\n /** Current chart type */\n chartType: ChartType\n /** Chart axis configuration */\n chartConfig: ChartAxisConfig\n /** Chart display configuration */\n displayConfig: ChartDisplayConfig\n /** Whether user manually selected chart type (disables auto-switch) */\n userManuallySelectedChart: boolean\n /** Current color palette name */\n localPaletteName: string\n\n // =========================================================================\n // UI State\n // =========================================================================\n /** Active tab in query panel */\n activeTab: QueryPanelTab\n /** Active view (table or chart) */\n activeView: 'table' | 'chart'\n /** Display limit for table */\n displayLimit: number\n /** Whether field search modal is open */\n showFieldModal: boolean\n /** Current mode for field search modal */\n fieldModalMode: FieldModalMode\n\n // =========================================================================\n // AI State\n // =========================================================================\n /** AI panel state */\n aiState: AIState\n\n // =========================================================================\n // Funnel State (when mergeStrategy === 'funnel')\n // =========================================================================\n /** Binding key dimension that links funnel steps together */\n funnelBindingKey: FunnelBindingKey | null\n /** Time window constraint for each step (ISO 8601 duration) */\n stepTimeToConvert: (string | null)[]\n}\n\n/**\n * Store actions interface\n */\nexport interface AnalysisBuilderStoreActions {\n // =========================================================================\n // Query State Actions\n // =========================================================================\n /** Set all query states */\n setQueryStates: (states: AnalysisBuilderState[]) => void\n /** Update a specific query state by index */\n updateQueryState: (\n index: number,\n updater: (state: AnalysisBuilderState) => AnalysisBuilderState\n ) => void\n /** Set active query index */\n setActiveQueryIndex: (index: number) => void\n /** Set merge strategy */\n setMergeStrategy: (strategy: QueryMergeStrategy) => void\n\n // =========================================================================\n // Metrics Actions\n // =========================================================================\n /** Open field modal in metrics mode */\n openMetricsModal: () => void\n /** Add a metric to current query */\n addMetric: (field: string, label?: string) => void\n /** Remove a metric from current query */\n removeMetric: (id: string) => void\n /** Toggle a metric (add if not present, remove if present) */\n toggleMetric: (fieldName: string) => void\n /** Reorder metrics */\n reorderMetrics: (fromIndex: number, toIndex: number) => void\n\n // =========================================================================\n // Breakdowns Actions\n // =========================================================================\n /** Open field modal in breakdown mode */\n openBreakdownsModal: () => void\n /** Add a breakdown to current query */\n addBreakdown: (field: string, isTimeDimension: boolean, granularity?: string) => void\n /** Remove a breakdown from current query */\n removeBreakdown: (id: string) => void\n /** Toggle a breakdown (add if not present, remove if present) */\n toggleBreakdown: (\n fieldName: string,\n isTimeDimension: boolean,\n granularity?: string\n ) => void\n /** Change granularity for a time dimension breakdown */\n setBreakdownGranularity: (id: string, granularity: string) => void\n /** Toggle comparison mode for a time dimension breakdown */\n toggleBreakdownComparison: (id: string) => void\n /** Reorder breakdowns */\n reorderBreakdowns: (fromIndex: number, toIndex: number) => void\n\n // =========================================================================\n // Filters Actions\n // =========================================================================\n /** Set filters for current query */\n setFilters: (filters: Filter[]) => void\n /** Drop a field to create a filter */\n dropFieldToFilter: (field: string) => void\n /** Set sort order for a field */\n setOrder: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n\n // =========================================================================\n // Multi-Query Actions\n // =========================================================================\n /** Add a new query tab */\n addQuery: () => void\n /** Remove a query tab */\n removeQuery: (index: number) => void\n\n // =========================================================================\n // Chart Actions\n // =========================================================================\n /** Set chart type */\n setChartType: (type: ChartType) => void\n /** Set chart type with manual selection flag */\n setChartTypeManual: (type: ChartType) => void\n /** Set chart config */\n setChartConfig: (config: ChartAxisConfig) => void\n /** Set display config */\n setDisplayConfig: (config: ChartDisplayConfig) => void\n /** Set color palette name */\n setLocalPaletteName: (name: string) => void\n /** Set user manually selected chart flag */\n setUserManuallySelectedChart: (value: boolean) => void\n\n // =========================================================================\n // UI Actions\n // =========================================================================\n /** Set active tab */\n setActiveTab: (tab: QueryPanelTab) => void\n /** Set active view */\n setActiveView: (view: 'table' | 'chart') => void\n /** Set display limit */\n setDisplayLimit: (limit: number) => void\n /** Close field modal */\n closeFieldModal: () => void\n\n // =========================================================================\n // AI Actions\n // =========================================================================\n /** Open AI panel */\n openAI: () => void\n /** Close AI panel */\n closeAI: () => void\n /** Set AI prompt */\n setAIPrompt: (prompt: string) => void\n /** Set AI generating state */\n setAIGenerating: (generating: boolean) => void\n /** Set AI error */\n setAIError: (error: string | null) => void\n /** Set AI has generated query */\n setAIHasGeneratedQuery: (hasQuery: boolean) => void\n /** Save previous state for AI undo */\n saveAIPreviousState: () => void\n /** Restore previous state (AI cancel/undo) */\n restoreAIPreviousState: () => void\n\n // =========================================================================\n // Funnel Actions (when mergeStrategy === 'funnel')\n // =========================================================================\n /** Set the funnel binding key */\n setFunnelBindingKey: (bindingKey: FunnelBindingKey | null) => void\n /** Set time window for a specific step */\n setStepTimeToConvert: (stepIndex: number, duration: string | null) => void\n /** Build FunnelConfig from current state */\n buildFunnelConfig: () => FunnelConfig | null\n /** Check if in funnel mode */\n isFunnelMode: () => boolean\n\n // =========================================================================\n // Utility Actions\n // =========================================================================\n /** Clear the current query */\n clearQuery: () => void\n /** Load state from URL share */\n loadFromShare: (sharedState: SharedState) => void\n /** Get current state (helper accessor) */\n getCurrentState: () => AnalysisBuilderState\n /** Get merge keys (computed from Q1 breakdowns) */\n getMergeKeys: () => string[] | undefined\n /** Check if in multi-query mode */\n isMultiQueryMode: () => boolean\n /** Build current CubeQuery */\n buildCurrentQuery: () => CubeQuery\n /** Build all queries */\n buildAllQueries: () => CubeQuery[]\n /** Build MultiQueryConfig */\n buildMultiQueryConfig: () => MultiQueryConfig | null\n /** Reset store to initial state */\n reset: () => void\n}\n\n/**\n * Shared state from URL\n */\nexport interface SharedState {\n query: CubeQuery | MultiQueryConfig\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n activeView?: 'table' | 'chart'\n}\n\n/**\n * Combined store type\n */\nexport type AnalysisBuilderStore = AnalysisBuilderStoreState &\n AnalysisBuilderStoreActions\n\n/**\n * Options for creating a store instance\n */\nexport interface CreateStoreOptions {\n /** Initial query configuration */\n initialQuery?: CubeQuery | MultiQueryConfig\n /** Initial chart configuration */\n initialChartConfig?: {\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n }\n /** Disable localStorage persistence */\n disableLocalStorage?: boolean\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialQueryState = createInitialState()\n\nconst initialAIState: AIState = {\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null,\n}\n\nconst createDefaultState = (): AnalysisBuilderStoreState => ({\n // Query state\n queryStates: [initialQueryState],\n activeQueryIndex: 0,\n mergeStrategy: 'concat',\n\n // Chart configuration\n chartType: 'line',\n chartConfig: {},\n displayConfig: { showLegend: true, showGrid: true, showTooltip: true },\n userManuallySelectedChart: false,\n localPaletteName: 'default',\n\n // UI state\n activeTab: 'query',\n activeView: 'chart',\n displayLimit: 100,\n showFieldModal: false,\n fieldModalMode: 'metrics',\n\n // AI state\n aiState: initialAIState,\n\n // Funnel state\n funnelBindingKey: null,\n stepTimeToConvert: [],\n})\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Convert CubeQuery to AnalysisBuilderState\n */\nfunction queryToState(query: CubeQuery): AnalysisBuilderState {\n const baseFilters = query.filters ? [...query.filters] : []\n\n const timeDimensions = query.timeDimensions || []\n const breakdowns = [\n ...(query.dimensions || []).map((field) => ({\n id: generateId(),\n field,\n isTimeDimension: false,\n })),\n ...timeDimensions.map((td) => ({\n id: generateId(),\n field: td.dimension,\n granularity: td.granularity,\n isTimeDimension: true,\n enableComparison: Boolean(td.compareDateRange && td.compareDateRange.length > 0),\n })),\n ]\n\n let filters = baseFilters\n\n // Restore date filters for comparison-enabled time dimensions when missing.\n for (const td of timeDimensions) {\n if (!td.compareDateRange || td.compareDateRange.length === 0) continue\n\n const hasDateFilter = filters.some(\n (filter) =>\n 'member' in filter &&\n (filter as SimpleFilter).member === td.dimension &&\n (filter as SimpleFilter).operator === 'inDateRange'\n )\n\n const firstRange = td.compareDateRange[0]\n const dateRange =\n Array.isArray(firstRange) || typeof firstRange === 'string'\n ? firstRange\n : undefined\n\n if (!dateRange) continue\n\n if (!hasDateFilter) {\n filters = [\n ...filters,\n {\n member: td.dimension,\n operator: 'inDateRange',\n values: [],\n dateRange,\n } as SimpleFilter,\n ]\n continue\n }\n\n filters = filters.map((filter) => {\n if (\n 'member' in filter &&\n (filter as SimpleFilter).member === td.dimension &&\n (filter as SimpleFilter).operator === 'inDateRange' &&\n !(filter as SimpleFilter).dateRange\n ) {\n return { ...(filter as SimpleFilter), dateRange }\n }\n return filter\n })\n }\n\n return {\n ...createInitialState(),\n metrics: (query.measures || []).map((field, index) => ({\n id: generateId(),\n field,\n label: generateMetricLabel(index),\n })),\n breakdowns,\n filters,\n order: query.order,\n }\n}\n\n/**\n * Check if config is MultiQueryConfig\n */\nfunction isMultiQueryConfig(config: CubeQuery | MultiQueryConfig): config is MultiQueryConfig {\n return 'queries' in config && Array.isArray(config.queries)\n}\n\n/**\n * Build initial state from options\n */\nfunction buildInitialState(options: CreateStoreOptions): AnalysisBuilderStoreState {\n const defaultState = createDefaultState()\n\n // If no initial query, return default state (localStorage will hydrate if enabled)\n if (!options.initialQuery) {\n // Apply initial chart config if provided (for cases like empty portlet with chart defaults)\n if (options.initialChartConfig) {\n return {\n ...defaultState,\n chartType: options.initialChartConfig.chartType || defaultState.chartType,\n chartConfig: options.initialChartConfig.chartConfig || defaultState.chartConfig,\n displayConfig: options.initialChartConfig.displayConfig || defaultState.displayConfig,\n userManuallySelectedChart: !!options.initialChartConfig.chartType,\n }\n }\n return defaultState\n }\n\n // Initialize from provided query\n const query = options.initialQuery\n let newQueryStates: AnalysisBuilderState[]\n let newMergeStrategy = defaultState.mergeStrategy\n\n if (isMultiQueryConfig(query)) {\n newQueryStates = query.queries.map(queryToState)\n if (query.mergeStrategy) {\n newMergeStrategy = query.mergeStrategy\n }\n } else {\n newQueryStates = [queryToState(query)]\n }\n\n return {\n ...defaultState,\n queryStates: newQueryStates,\n activeQueryIndex: 0,\n mergeStrategy: newMergeStrategy,\n chartType: options.initialChartConfig?.chartType || defaultState.chartType,\n chartConfig: options.initialChartConfig?.chartConfig || defaultState.chartConfig,\n displayConfig: options.initialChartConfig?.displayConfig || defaultState.displayConfig,\n userManuallySelectedChart: !!options.initialChartConfig?.chartType,\n }\n}\n\n// ============================================================================\n// Store Factory\n// ============================================================================\n\n/**\n * Create store actions (shared between persisted and non-persisted stores)\n */\nfunction createStoreActions(\n set: (partial: Partial<AnalysisBuilderStore> | ((state: AnalysisBuilderStore) => Partial<AnalysisBuilderStore>)) => void,\n get: () => AnalysisBuilderStore,\n initialState: AnalysisBuilderStoreState\n): AnalysisBuilderStoreActions {\n return {\n // =================================================================\n // Query State Actions\n // =================================================================\n\n setQueryStates: (states) => set({ queryStates: states }),\n\n updateQueryState: (index, updater) =>\n set((state) => {\n const newStates = [...state.queryStates]\n newStates[index] = updater(newStates[index] || createInitialState())\n return { queryStates: newStates }\n }),\n\n setActiveQueryIndex: (index) => set({ activeQueryIndex: index }),\n\n setMergeStrategy: (strategy) =>\n set((state) => {\n // Auto-switch to funnel chart when entering funnel mode\n if (strategy === 'funnel' && state.chartType !== 'funnel') {\n return {\n mergeStrategy: strategy,\n chartType: 'funnel',\n userManuallySelectedChart: false,\n }\n }\n // Auto-switch away from funnel chart when leaving funnel mode\n if (strategy !== 'funnel' && state.chartType === 'funnel') {\n return {\n mergeStrategy: strategy,\n chartType: 'line',\n userManuallySelectedChart: false,\n }\n }\n return { mergeStrategy: strategy }\n }),\n\n // =================================================================\n // Metrics Actions\n // =================================================================\n\n openMetricsModal: () =>\n set({ showFieldModal: true, fieldModalMode: 'metrics' }),\n\n addMetric: (field, label) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const newMetric: MetricItem = {\n id: generateId(),\n field,\n label: label || generateMetricLabel(currentState.metrics.length),\n }\n newStates[index] = {\n ...currentState,\n metrics: [...currentState.metrics, newMetric],\n }\n return { queryStates: newStates }\n }),\n\n removeMetric: (id) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const fieldToRemove = currentState.metrics.find((m) => m.id === id)?.field\n const newMetrics = currentState.metrics.filter((m) => m.id !== id)\n\n // Clean up sort order for removed field\n let newOrder = currentState.order\n if (fieldToRemove && newOrder && newOrder[fieldToRemove]) {\n newOrder = { ...newOrder }\n delete newOrder[fieldToRemove]\n if (Object.keys(newOrder).length === 0) {\n newOrder = undefined\n }\n }\n\n newStates[index] = {\n ...currentState,\n metrics: newMetrics,\n order: newOrder,\n }\n return { queryStates: newStates }\n }),\n\n toggleMetric: (fieldName) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const existingIndex = currentState.metrics.findIndex(\n (m) => m.field === fieldName\n )\n\n if (existingIndex >= 0) {\n // Remove existing\n newStates[index] = {\n ...currentState,\n metrics: currentState.metrics.filter((_, i) => i !== existingIndex),\n }\n } else {\n // Add new\n const newMetric: MetricItem = {\n id: generateId(),\n field: fieldName,\n label: generateMetricLabel(currentState.metrics.length),\n }\n newStates[index] = {\n ...currentState,\n metrics: [...currentState.metrics, newMetric],\n }\n }\n return { queryStates: newStates }\n }),\n\n reorderMetrics: (fromIndex, toIndex) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const newMetrics = [...currentState.metrics]\n const [movedItem] = newMetrics.splice(fromIndex, 1)\n newMetrics.splice(toIndex, 0, movedItem)\n newStates[index] = {\n ...currentState,\n metrics: newMetrics,\n }\n return { queryStates: newStates }\n }),\n\n // =================================================================\n // Breakdowns Actions\n // =================================================================\n\n openBreakdownsModal: () =>\n set({ showFieldModal: true, fieldModalMode: 'breakdown' }),\n\n addBreakdown: (field, isTimeDimension, granularity) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n\n // Check if we already have a time dimension (only allow one)\n if (isTimeDimension) {\n const hasExisting = currentState.breakdowns.some((b) => b.isTimeDimension)\n if (hasExisting) return state\n }\n\n const newBreakdown: BreakdownItem = {\n id: generateId(),\n field,\n isTimeDimension,\n granularity: isTimeDimension ? granularity || 'month' : undefined,\n }\n newStates[index] = {\n ...currentState,\n breakdowns: [...currentState.breakdowns, newBreakdown],\n }\n return { queryStates: newStates }\n }),\n\n removeBreakdown: (id) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const fieldToRemove = currentState.breakdowns.find((b) => b.id === id)?.field\n const newBreakdowns = currentState.breakdowns.filter((b) => b.id !== id)\n\n // Clean up sort order for removed field\n let newOrder = currentState.order\n if (fieldToRemove && newOrder && newOrder[fieldToRemove]) {\n newOrder = { ...newOrder }\n delete newOrder[fieldToRemove]\n if (Object.keys(newOrder).length === 0) {\n newOrder = undefined\n }\n }\n\n newStates[index] = {\n ...currentState,\n breakdowns: newBreakdowns,\n order: newOrder,\n }\n return { queryStates: newStates }\n }),\n\n toggleBreakdown: (fieldName, isTimeDimension, granularity) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const existingIndex = currentState.breakdowns.findIndex(\n (b) => b.field === fieldName\n )\n\n if (existingIndex >= 0) {\n // Remove existing\n newStates[index] = {\n ...currentState,\n breakdowns: currentState.breakdowns.filter((_, i) => i !== existingIndex),\n }\n } else {\n // Check if we already have a time dimension\n if (isTimeDimension) {\n const hasExisting = currentState.breakdowns.some((b) => b.isTimeDimension)\n if (hasExisting) return state\n }\n\n const newBreakdown: BreakdownItem = {\n id: generateId(),\n field: fieldName,\n isTimeDimension,\n granularity: isTimeDimension ? granularity || 'month' : undefined,\n }\n newStates[index] = {\n ...currentState,\n breakdowns: [...currentState.breakdowns, newBreakdown],\n }\n }\n return { queryStates: newStates }\n }),\n\n setBreakdownGranularity: (id, granularity) =>\n set((state) => {\n const { mergeStrategy, activeQueryIndex, queryStates } = state\n const newStates = [...queryStates]\n\n // In merge mode, granularity changes update Q1 (source of truth)\n if (mergeStrategy === 'merge' && activeQueryIndex > 0) {\n newStates[0] = {\n ...newStates[0],\n breakdowns: newStates[0].breakdowns.map((b) =>\n b.id === id ? { ...b, granularity } : b\n ),\n }\n } else {\n newStates[activeQueryIndex] = {\n ...newStates[activeQueryIndex],\n breakdowns: newStates[activeQueryIndex].breakdowns.map((b) =>\n b.id === id ? { ...b, granularity } : b\n ),\n }\n }\n return { queryStates: newStates }\n }),\n\n toggleBreakdownComparison: (id) =>\n set((state) => {\n const { mergeStrategy, activeQueryIndex, queryStates, chartType } = state\n const newStates = [...queryStates]\n\n // Get source breakdowns based on mode\n const sourceIndex = mergeStrategy === 'merge' && activeQueryIndex > 0 ? 0 : activeQueryIndex\n const sourceState = newStates[sourceIndex]\n const targetBreakdown = sourceState.breakdowns.find((b) => b.id === id)\n const isEnabling = targetBreakdown && !targetBreakdown.enableComparison\n\n let newChartType = chartType\n let newChartConfig = state.chartConfig\n\n // If enabling comparison, auto-add date filter and switch to line chart\n if (isEnabling && targetBreakdown) {\n const hasDateFilter = findDateFilterForField(\n sourceState.filters,\n targetBreakdown.field\n )\n\n if (!hasDateFilter) {\n const newFilter: Filter = {\n member: targetBreakdown.field,\n operator: 'inDateRange',\n values: [],\n dateRange: convertDateRangeTypeToValue('last_30_days'),\n } as Filter\n newStates[sourceIndex] = {\n ...sourceState,\n filters: [...sourceState.filters, newFilter],\n }\n }\n\n // Switch to line chart if not already\n if (chartType !== 'line') {\n newChartType = 'line'\n const { chartConfig: smartConfig } = getSmartChartDefaults(\n sourceState.metrics,\n sourceState.breakdowns,\n 'line'\n )\n newChartConfig = smartConfig\n }\n }\n\n // Update breakdowns with comparison toggle\n const updatedBreakdowns = newStates[sourceIndex].breakdowns.map((b) => {\n if (b.id === id) {\n return { ...b, enableComparison: !b.enableComparison }\n }\n // Clear comparison from other time dimensions\n if (b.isTimeDimension && b.enableComparison) {\n return { ...b, enableComparison: false }\n }\n return b\n })\n\n newStates[sourceIndex] = {\n ...newStates[sourceIndex],\n breakdowns: updatedBreakdowns,\n }\n\n return {\n queryStates: newStates,\n chartType: newChartType,\n chartConfig: newChartConfig,\n }\n }),\n\n reorderBreakdowns: (fromIndex, toIndex) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const newBreakdowns = [...currentState.breakdowns]\n const [movedItem] = newBreakdowns.splice(fromIndex, 1)\n newBreakdowns.splice(toIndex, 0, movedItem)\n newStates[index] = {\n ...currentState,\n breakdowns: newBreakdowns,\n }\n return { queryStates: newStates }\n }),\n\n // =================================================================\n // Filters Actions\n // =================================================================\n\n setFilters: (filters) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n newStates[index] = {\n ...newStates[index],\n filters,\n }\n return { queryStates: newStates }\n }),\n\n dropFieldToFilter: (field) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const existingFilters = currentState.filters || []\n\n // Check if we already have a filter for this field\n const hasFilter = existingFilters.some(\n (f) => 'member' in f && f.member === field\n )\n if (hasFilter) return state\n\n const newFilter: Filter = {\n member: field,\n operator: 'set',\n values: [],\n }\n\n let updatedFilters: Filter[]\n if (existingFilters.length === 0) {\n updatedFilters = [newFilter]\n } else if (existingFilters.length === 1 && 'type' in existingFilters[0]) {\n const group = existingFilters[0] as { type: 'and' | 'or'; filters: Filter[] }\n updatedFilters = [{ ...group, filters: [...group.filters, newFilter] }]\n } else {\n updatedFilters = [{ type: 'and' as const, filters: [...existingFilters, newFilter] }]\n }\n\n newStates[index] = {\n ...currentState,\n filters: updatedFilters,\n }\n return { queryStates: newStates }\n }),\n\n setOrder: (fieldName, direction) =>\n set((state) => {\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n const currentState = newStates[index] || createInitialState()\n const newOrder = { ...(currentState.order || {}) }\n\n if (direction === null) {\n delete newOrder[fieldName]\n } else {\n newOrder[fieldName] = direction\n }\n\n newStates[index] = {\n ...currentState,\n order: Object.keys(newOrder).length > 0 ? newOrder : undefined,\n }\n return { queryStates: newStates }\n }),\n\n // =================================================================\n // Multi-Query Actions\n // =================================================================\n\n addQuery: () =>\n set((state) => {\n const currentState = state.queryStates[state.activeQueryIndex] || createInitialState()\n const newState: AnalysisBuilderState = {\n ...createInitialState(),\n metrics: [...currentState.metrics],\n breakdowns: [...currentState.breakdowns],\n filters: [...currentState.filters],\n }\n return {\n queryStates: [...state.queryStates, newState],\n activeQueryIndex: state.queryStates.length,\n }\n }),\n\n removeQuery: (index) =>\n set((state) => {\n if (state.queryStates.length <= 1) return state\n const newStates = state.queryStates.filter((_, i) => i !== index)\n let newActiveIndex = state.activeQueryIndex\n if (index === state.activeQueryIndex) {\n newActiveIndex = Math.max(0, state.activeQueryIndex - 1)\n } else if (index < state.activeQueryIndex) {\n newActiveIndex = state.activeQueryIndex - 1\n }\n return { queryStates: newStates, activeQueryIndex: newActiveIndex }\n }),\n\n // =================================================================\n // Chart Actions\n // =================================================================\n\n setChartType: (type) => set({ chartType: type }),\n\n setChartTypeManual: (type) =>\n set((state) => {\n const currentState = state.queryStates[state.activeQueryIndex]\n\n // If switching away from line, clear comparison\n if (type !== 'line' && currentState) {\n const hasComparison = currentState.breakdowns.some(\n (b) => b.isTimeDimension && b.enableComparison\n )\n if (hasComparison) {\n const newStates = [...state.queryStates]\n newStates[state.activeQueryIndex] = {\n ...currentState,\n breakdowns: currentState.breakdowns.map((b) =>\n b.isTimeDimension && b.enableComparison\n ? { ...b, enableComparison: false }\n : b\n ),\n }\n\n const { chartConfig } = getSmartChartDefaults(\n currentState.metrics,\n currentState.breakdowns,\n type\n )\n\n return {\n queryStates: newStates,\n chartType: type,\n chartConfig,\n userManuallySelectedChart: true,\n activeView: 'chart',\n }\n }\n }\n\n const { chartConfig } = getSmartChartDefaults(\n currentState?.metrics || [],\n currentState?.breakdowns || [],\n type\n )\n\n return {\n chartType: type,\n chartConfig,\n userManuallySelectedChart: true,\n activeView: 'chart',\n }\n }),\n\n setChartConfig: (config) => set({ chartConfig: config, activeView: 'chart' }),\n\n setDisplayConfig: (config) => set({ displayConfig: config, activeView: 'chart' }),\n\n setLocalPaletteName: (name) => set({ localPaletteName: name }),\n\n setUserManuallySelectedChart: (value) => set({ userManuallySelectedChart: value }),\n\n // =================================================================\n // UI Actions\n // =================================================================\n\n setActiveTab: (tab) => set({ activeTab: tab }),\n\n setActiveView: (view) => set({ activeView: view }),\n\n setDisplayLimit: (limit) => set({ displayLimit: limit }),\n\n closeFieldModal: () => set({ showFieldModal: false }),\n\n // =================================================================\n // AI Actions\n // =================================================================\n\n openAI: () =>\n set((state) => ({\n aiState: { ...state.aiState, isOpen: true },\n })),\n\n closeAI: () =>\n set((state) => ({\n aiState: { ...state.aiState, isOpen: false },\n })),\n\n setAIPrompt: (prompt) =>\n set((state) => ({\n aiState: { ...state.aiState, userPrompt: prompt },\n })),\n\n setAIGenerating: (generating) =>\n set((state) => ({\n aiState: { ...state.aiState, isGenerating: generating },\n })),\n\n setAIError: (error) =>\n set((state) => ({\n aiState: { ...state.aiState, error },\n })),\n\n setAIHasGeneratedQuery: (hasQuery) =>\n set((state) => ({\n aiState: { ...state.aiState, hasGeneratedQuery: hasQuery },\n })),\n\n saveAIPreviousState: () =>\n set((state) => {\n const currentState = state.queryStates[state.activeQueryIndex]\n return {\n aiState: {\n ...state.aiState,\n previousState: currentState\n ? {\n metrics: [...currentState.metrics],\n breakdowns: [...currentState.breakdowns],\n filters: [...currentState.filters],\n chartType: state.chartType,\n chartConfig: { ...state.chartConfig },\n displayConfig: { ...state.displayConfig },\n }\n : null,\n },\n }\n }),\n\n restoreAIPreviousState: () =>\n set((state) => {\n const prev = state.aiState.previousState\n if (!prev) return state\n\n const index = state.activeQueryIndex\n const newStates = [...state.queryStates]\n newStates[index] = {\n ...(newStates[index] || createInitialState()),\n metrics: prev.metrics,\n breakdowns: prev.breakdowns,\n filters: prev.filters,\n }\n\n return {\n queryStates: newStates,\n chartType: prev.chartType,\n chartConfig: prev.chartConfig,\n displayConfig: prev.displayConfig,\n aiState: { ...initialAIState },\n }\n }),\n\n // =================================================================\n // Funnel Actions\n // =================================================================\n\n setFunnelBindingKey: (bindingKey) => set({ funnelBindingKey: bindingKey }),\n\n setStepTimeToConvert: (stepIndex, duration) =>\n set((state) => {\n const newTimeToConvert = [...state.stepTimeToConvert]\n // Ensure array is large enough\n while (newTimeToConvert.length <= stepIndex) {\n newTimeToConvert.push(null)\n }\n newTimeToConvert[stepIndex] = duration\n return { stepTimeToConvert: newTimeToConvert }\n }),\n\n buildFunnelConfig: () => {\n const state = get()\n if (state.mergeStrategy !== 'funnel') return null\n if (!state.funnelBindingKey) return null\n if (state.queryStates.length < 2) return null\n\n // Build queries for each step\n const queries = state.queryStates.map((qs) =>\n buildCubeQuery(qs.metrics, qs.breakdowns, qs.filters, qs.order)\n )\n\n // Generate step labels\n const stepLabels = state.queryStates.map((_, i) => `Step ${i + 1}`)\n\n return buildFunnelConfigFromQueries(\n queries,\n state.funnelBindingKey,\n stepLabels,\n state.stepTimeToConvert\n )\n },\n\n isFunnelMode: () => get().mergeStrategy === 'funnel',\n\n // =================================================================\n // Utility Actions\n // =================================================================\n\n clearQuery: () =>\n set((state) => {\n const newStates = [...state.queryStates]\n newStates[state.activeQueryIndex] = createInitialState()\n return {\n queryStates: newStates,\n chartType: 'line',\n chartConfig: {},\n displayConfig: { showLegend: true, showGrid: true, showTooltip: true },\n userManuallySelectedChart: false,\n }\n }),\n\n loadFromShare: (sharedState) =>\n set((state) => {\n const { query } = sharedState\n let newQueryStates: AnalysisBuilderState[]\n let newMergeStrategy = state.mergeStrategy\n\n if (isMultiQueryConfig(query)) {\n newQueryStates = query.queries.map(queryToState)\n if (query.mergeStrategy) {\n newMergeStrategy = query.mergeStrategy\n }\n } else {\n newQueryStates = [queryToState(query)]\n }\n\n return {\n queryStates: newQueryStates,\n activeQueryIndex: 0,\n mergeStrategy: newMergeStrategy,\n chartType: sharedState.chartType || state.chartType,\n chartConfig: sharedState.chartConfig || state.chartConfig,\n displayConfig: sharedState.displayConfig || state.displayConfig,\n activeView: sharedState.activeView || state.activeView,\n userManuallySelectedChart: !!sharedState.chartType,\n }\n }),\n\n getCurrentState: () => {\n const state = get()\n return state.queryStates[state.activeQueryIndex] || createInitialState()\n },\n\n getMergeKeys: () => {\n const state = get()\n if (state.mergeStrategy !== 'merge' || state.queryStates.length === 0) {\n return undefined\n }\n const q1Breakdowns = state.queryStates[0].breakdowns\n if (q1Breakdowns.length === 0) return undefined\n return q1Breakdowns.map((b) => b.field)\n },\n\n isMultiQueryMode: () => {\n const state = get()\n if (state.queryStates.length <= 1) return false\n const queriesWithContent = state.queryStates.filter(\n (qs) => qs.metrics.length > 0 || qs.breakdowns.length > 0\n )\n return queriesWithContent.length > 1\n },\n\n buildCurrentQuery: () => {\n const state = get()\n const current = state.queryStates[state.activeQueryIndex] || createInitialState()\n return buildCubeQuery(\n current.metrics,\n current.breakdowns,\n current.filters,\n current.order\n )\n },\n\n buildAllQueries: () => {\n const state = get()\n // In merge mode, Q2+ use Q1's breakdowns (dimensions are shared/locked)\n const q1Breakdowns = state.queryStates[0]?.breakdowns || []\n\n return state.queryStates.map((qs, index) => {\n // In merge mode, Q2+ inherit Q1's breakdowns\n const breakdowns = state.mergeStrategy === 'merge' && index > 0\n ? q1Breakdowns\n : qs.breakdowns\n\n return buildCubeQuery(qs.metrics, breakdowns, qs.filters, qs.order)\n })\n },\n\n buildMultiQueryConfig: () => {\n const state = get()\n if (!get().isMultiQueryMode()) return null\n\n const allQueries = get().buildAllQueries()\n const validQueries = allQueries.filter(\n (q) =>\n (q.measures && q.measures.length > 0) ||\n (q.dimensions && q.dimensions.length > 0) ||\n (q.timeDimensions && q.timeDimensions.length > 0)\n )\n\n if (validQueries.length < 2) return null\n\n return {\n queries: validQueries,\n mergeStrategy: state.mergeStrategy,\n mergeKeys: get().getMergeKeys(),\n queryLabels: validQueries.map((_, i) => `Q${i + 1}`),\n }\n },\n\n reset: () => set(initialState),\n }\n}\n\n/**\n * Create a new store instance with optional persistence\n */\nexport function createAnalysisBuilderStore(options: CreateStoreOptions = {}) {\n const initialState = buildInitialState(options)\n\n // Create store with or without persistence\n if (options.disableLocalStorage) {\n // No persistence - for modal/portlet editing\n return createStore<AnalysisBuilderStore>()(\n devtools(\n subscribeWithSelector((set, get) => ({\n ...initialState,\n ...createStoreActions(set, get, initialState),\n })),\n { name: 'AnalysisBuilderStore (no-persist)' }\n )\n )\n }\n\n // With persistence - for standalone mode\n return createStore<AnalysisBuilderStore>()(\n devtools(\n subscribeWithSelector(\n persist(\n (set, get) => ({\n ...initialState,\n ...createStoreActions(set, get, initialState),\n }),\n {\n name: STORAGE_KEY,\n partialize: (state) => ({\n // Only persist these fields\n queryStates: state.queryStates,\n activeQueryIndex: state.queryStates.length > 1 ? state.activeQueryIndex : undefined,\n mergeStrategy: state.queryStates.length > 1 ? state.mergeStrategy : undefined,\n // Funnel binding key (only persist when in funnel mode)\n funnelBindingKey: state.mergeStrategy === 'funnel' ? state.funnelBindingKey : undefined,\n chartType: state.chartType,\n chartConfig: state.chartConfig,\n displayConfig: state.displayConfig,\n activeView: state.activeView,\n }),\n }\n )\n ),\n { name: 'AnalysisBuilderStore' }\n )\n )\n}\n\n// ============================================================================\n// React Context & Provider\n// ============================================================================\n\n/**\n * Context for the store instance\n */\nconst AnalysisBuilderStoreContext = createContext<StoreApi<AnalysisBuilderStore> | null>(null)\n\n/**\n * Provider props\n */\nexport interface AnalysisBuilderStoreProviderProps {\n children: ReactNode\n /** Initial query configuration */\n initialQuery?: CubeQuery | MultiQueryConfig\n /** Initial chart configuration */\n initialChartConfig?: {\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n }\n /** Disable localStorage persistence */\n disableLocalStorage?: boolean\n}\n\n/**\n * Provider component that creates a store instance per AnalysisBuilder\n */\nexport function AnalysisBuilderStoreProvider({\n children,\n initialQuery,\n initialChartConfig,\n disableLocalStorage,\n}: AnalysisBuilderStoreProviderProps) {\n // Create store instance once per provider mount\n const storeRef = useRef<StoreApi<AnalysisBuilderStore> | null>(null)\n\n if (!storeRef.current) {\n storeRef.current = createAnalysisBuilderStore({\n initialQuery,\n initialChartConfig,\n disableLocalStorage,\n })\n }\n\n return (\n <AnalysisBuilderStoreContext.Provider value={storeRef.current}>\n {children}\n </AnalysisBuilderStoreContext.Provider>\n )\n}\n\n/**\n * Hook to access the store from context\n * @throws Error if used outside of provider\n */\nexport function useAnalysisBuilderStore<T>(selector: (state: AnalysisBuilderStore) => T): T {\n const store = useContext(AnalysisBuilderStoreContext)\n if (!store) {\n throw new Error('useAnalysisBuilderStore must be used within AnalysisBuilderStoreProvider')\n }\n return useStore(store, selector)\n}\n\n/**\n * Hook to get the raw store API (for actions that need direct access)\n */\nexport function useAnalysisBuilderStoreApi(): StoreApi<AnalysisBuilderStore> {\n const store = useContext(AnalysisBuilderStoreContext)\n if (!store) {\n throw new Error('useAnalysisBuilderStoreApi must be used within AnalysisBuilderStoreProvider')\n }\n return store\n}\n\n// ============================================================================\n// Selectors (for optimized re-renders)\n// ============================================================================\n\n/**\n * Select current query state\n */\nexport const selectCurrentState = (state: AnalysisBuilderStore) =>\n state.queryStates[state.activeQueryIndex] || createInitialState()\n\n/**\n * Select current metrics\n */\nexport const selectMetrics = (state: AnalysisBuilderStore) =>\n selectCurrentState(state).metrics\n\n/**\n * Select current breakdowns\n */\nexport const selectBreakdowns = (state: AnalysisBuilderStore) =>\n selectCurrentState(state).breakdowns\n\n/**\n * Select current filters\n */\nexport const selectFilters = (state: AnalysisBuilderStore) =>\n selectCurrentState(state).filters\n\n/**\n * Select chart configuration\n */\nexport const selectChartConfig = (state: AnalysisBuilderStore) => ({\n chartType: state.chartType,\n chartConfig: state.chartConfig,\n displayConfig: state.displayConfig,\n})\n\n/**\n * Select UI state\n */\nexport const selectUIState = (state: AnalysisBuilderStore) => ({\n activeTab: state.activeTab,\n activeView: state.activeView,\n displayLimit: state.displayLimit,\n showFieldModal: state.showFieldModal,\n fieldModalMode: state.fieldModalMode,\n})\n\n/**\n * Select multi-query state\n */\nexport const selectMultiQueryState = (state: AnalysisBuilderStore) => ({\n queryStates: state.queryStates,\n activeQueryIndex: state.activeQueryIndex,\n mergeStrategy: state.mergeStrategy,\n isMultiQueryMode: state.queryStates.length > 1,\n})\n\n/**\n * Select funnel state\n */\nexport const selectFunnelState = (state: AnalysisBuilderStore) => ({\n funnelBindingKey: state.funnelBindingKey,\n stepTimeToConvert: state.stepTimeToConvert,\n isFunnelMode: state.mergeStrategy === 'funnel',\n})\n","/**\n * Multi-Query Validation Utilities\n *\n * Pure functions for validating multi-query configurations.\n * These help detect issues like measure collisions and granularity mismatches.\n */\n\nimport type { CubeQuery, QueryMergeStrategy } from '../types'\n\n// TimeDimension type extracted from CubeQuery\ntype TimeDimension = NonNullable<CubeQuery['timeDimensions']>[number]\n\n/**\n * Validation error for multi-query configuration\n */\nexport interface MultiQueryValidationError {\n type: 'missing_time_dimension' | 'granularity_mismatch' | 'missing_merge_key'\n queryIndex: number\n message: string\n details?: {\n field?: string\n expectedGranularity?: string\n actualGranularity?: string\n }\n}\n\n/**\n * Validation warning for multi-query configuration\n */\nexport interface MultiQueryValidationWarning {\n type: 'measure_collision' | 'asymmetric_date_range'\n queryIndices: number[]\n message: string\n affectedMeasures?: string[]\n}\n\n/**\n * Result of multi-query validation\n */\nexport interface MultiQueryValidationResult {\n isValid: boolean\n errors: MultiQueryValidationError[]\n warnings: MultiQueryValidationWarning[]\n}\n\n/**\n * Extract time dimension info from a query\n */\nexport function extractTimeDimensions(query: CubeQuery): TimeDimension[] {\n return query.timeDimensions || []\n}\n\n/**\n * Validate that all queries have matching time dimension granularities\n * Only relevant for 'merge' strategy where data needs to align\n */\nexport function validateTimeDimensionAlignment(queries: CubeQuery[]): MultiQueryValidationError[] {\n const errors: MultiQueryValidationError[] = []\n\n if (queries.length < 2) return errors\n\n // Get time dimensions from first query as reference\n const q1TimeDims = extractTimeDimensions(queries[0])\n if (q1TimeDims.length === 0) return errors // No time dimensions to validate\n\n // Check each subsequent query\n for (let i = 1; i < queries.length; i++) {\n const qTimeDims = extractTimeDimensions(queries[i])\n\n // Check if query has time dimensions\n if (qTimeDims.length === 0 && q1TimeDims.length > 0) {\n errors.push({\n type: 'missing_time_dimension',\n queryIndex: i,\n message: `Query ${i + 1} is missing time dimension \"${q1TimeDims[0].dimension}\"`,\n details: { field: q1TimeDims[0].dimension }\n })\n continue\n }\n\n // Check granularity matches\n for (const refTimeDim of q1TimeDims) {\n const matchingDim = qTimeDims.find(td => td.dimension === refTimeDim.dimension)\n if (matchingDim && matchingDim.granularity !== refTimeDim.granularity) {\n errors.push({\n type: 'granularity_mismatch',\n queryIndex: i,\n message: `Query ${i + 1} uses \"${matchingDim.granularity}\" granularity but Query 1 uses \"${refTimeDim.granularity}\"`,\n details: {\n field: refTimeDim.dimension,\n expectedGranularity: refTimeDim.granularity,\n actualGranularity: matchingDim.granularity\n }\n })\n }\n }\n }\n\n return errors\n}\n\n/**\n * Validate that merge keys exist in all queries\n */\nexport function validateMergeKeys(queries: CubeQuery[], mergeKeys: string[]): MultiQueryValidationError[] {\n const errors: MultiQueryValidationError[] = []\n\n if (queries.length < 2 || mergeKeys.length === 0) return errors\n\n for (let i = 0; i < queries.length; i++) {\n const query = queries[i]\n const allFields = new Set([\n ...(query.dimensions || []),\n ...(query.timeDimensions?.map(td => td.dimension) || [])\n ])\n\n for (const key of mergeKeys) {\n if (!allFields.has(key)) {\n errors.push({\n type: 'missing_merge_key',\n queryIndex: i,\n message: `Query ${i + 1} is missing merge dimension \"${key}\"`,\n details: { field: key }\n })\n }\n }\n }\n\n return errors\n}\n\n/**\n * Detect when the same measure appears in multiple queries\n * This is a warning since the first value wins in merge mode\n */\nexport function detectMeasureCollisions(queries: CubeQuery[]): MultiQueryValidationWarning[] {\n const warnings: MultiQueryValidationWarning[] = []\n\n if (queries.length < 2) return warnings\n\n // Count occurrences of each measure\n const measureCounts = new Map<string, number[]>()\n\n queries.forEach((query, index) => {\n query.measures?.forEach(measure => {\n if (!measureCounts.has(measure)) {\n measureCounts.set(measure, [])\n }\n measureCounts.get(measure)!.push(index)\n })\n })\n\n // Find collisions\n const collisions: string[] = []\n const collisionIndices = new Set<number>()\n\n measureCounts.forEach((indices, measure) => {\n if (indices.length > 1) {\n collisions.push(measure)\n indices.forEach(i => collisionIndices.add(i))\n }\n })\n\n if (collisions.length > 0) {\n warnings.push({\n type: 'measure_collision',\n queryIndices: Array.from(collisionIndices).sort(),\n message: `Measure${collisions.length > 1 ? 's' : ''} \"${collisions.join('\", \"')}\" appear${collisions.length === 1 ? 's' : ''} in multiple queries - first value will be used`,\n affectedMeasures: collisions\n })\n }\n\n return warnings\n}\n\n/**\n * Check if queries have different date ranges\n */\nexport function detectAsymmetricDateRanges(queries: CubeQuery[]): MultiQueryValidationWarning[] {\n const warnings: MultiQueryValidationWarning[] = []\n\n if (queries.length < 2) return warnings\n\n // Get date ranges from each query's time dimensions\n const dateRanges = queries.map(q => {\n const timeDim = q.timeDimensions?.[0]\n return timeDim?.dateRange\n })\n\n // Check if any are different\n const uniqueRanges = new Set(dateRanges.map(r => JSON.stringify(r)))\n if (uniqueRanges.size > 1) {\n warnings.push({\n type: 'asymmetric_date_range',\n queryIndices: queries.map((_, i) => i),\n message: 'Queries have different date ranges - some data points may be missing in merged results'\n })\n }\n\n return warnings\n}\n\n/**\n * Validate a multi-query configuration\n * For 'merge' strategy: strict validation (errors block execution)\n * For 'concat' and 'funnel' strategies: only warnings\n */\nexport function validateMultiQueryConfig(\n queries: CubeQuery[],\n mergeStrategy: QueryMergeStrategy,\n mergeKeys: string[] = []\n): MultiQueryValidationResult {\n const errors: MultiQueryValidationError[] = []\n const warnings: MultiQueryValidationWarning[] = []\n\n if (queries.length < 2) {\n return { isValid: true, errors, warnings }\n }\n\n // Always detect measure collisions (warning)\n warnings.push(...detectMeasureCollisions(queries))\n\n // Always detect asymmetric date ranges (warning)\n warnings.push(...detectAsymmetricDateRanges(queries))\n\n // For merge strategy, validate alignment\n if (mergeStrategy === 'merge') {\n errors.push(...validateTimeDimensionAlignment(queries))\n if (mergeKeys.length > 0) {\n errors.push(...validateMergeKeys(queries, mergeKeys))\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings\n }\n}\n\n/**\n * Check if a multi-query configuration is valid for execution\n */\nexport function isMultiQueryValid(queries: CubeQuery[]): boolean {\n return queries.filter(q =>\n (q.measures?.length || 0) +\n (q.dimensions?.length || 0) +\n (q.timeDimensions?.length || 0) > 0\n ).length >= 2\n}\n\n/**\n * Get human-readable validation summary\n */\nexport function getValidationSummary(result: MultiQueryValidationResult): string {\n if (result.isValid && result.warnings.length === 0) {\n return 'Configuration is valid'\n }\n\n const parts: string[] = []\n\n if (result.errors.length > 0) {\n parts.push(`${result.errors.length} error${result.errors.length > 1 ? 's' : ''}`)\n }\n\n if (result.warnings.length > 0) {\n parts.push(`${result.warnings.length} warning${result.warnings.length > 1 ? 's' : ''}`)\n }\n\n return parts.join(', ')\n}\n","/**\n * useAnalysisQueryBuilder\n *\n * Builds and validates queries from Zustand store state.\n * Handles single-query and multi-query modes.\n */\n\nimport { useMemo } from 'react'\nimport { useAnalysisBuilderStore } from '../stores/analysisBuilderStore'\nimport { validateMultiQueryConfig, type MultiQueryValidationResult } from '../utils/multiQueryValidation'\nimport { buildCubeQuery } from '../components/AnalysisBuilder/utils'\nimport type { CubeQuery, MultiQueryConfig, QueryMergeStrategy } from '../types'\nimport type { AnalysisBuilderState } from '../components/AnalysisBuilder/types'\n\nexport interface UseAnalysisQueryBuilderResult {\n /** Current query state (active query) */\n queryState: AnalysisBuilderState\n /** All query states (for multi-query mode) */\n queryStates: AnalysisBuilderState[]\n /** Active query index */\n activeQueryIndex: number\n /** Merge strategy for multi-query */\n mergeStrategy: QueryMergeStrategy\n /** Whether in multi-query mode */\n isMultiQueryMode: boolean\n /** Merge keys (computed from Q1 breakdowns) */\n mergeKeys: string[] | undefined\n /** Current query as CubeQuery */\n currentQuery: CubeQuery\n /** All queries as CubeQuery[] */\n allQueries: CubeQuery[]\n /** MultiQueryConfig (if in multi-query mode) */\n multiQueryConfig: MultiQueryConfig | null\n /** Multi-query validation result */\n multiQueryValidation: MultiQueryValidationResult | null\n /** Whether current query is valid */\n isValidQuery: boolean | undefined\n\n // Actions\n setActiveQueryIndex: (index: number) => void\n setMergeStrategy: (strategy: QueryMergeStrategy) => void\n addQuery: () => void\n removeQuery: (index: number) => void\n}\n\nexport function useAnalysisQueryBuilder(): UseAnalysisQueryBuilderResult {\n // Store state\n const queryStates = useAnalysisBuilderStore((state) => state.queryStates)\n const activeQueryIndex = useAnalysisBuilderStore((state) => state.activeQueryIndex)\n const mergeStrategy = useAnalysisBuilderStore((state) => state.mergeStrategy)\n\n // Store actions\n const setActiveQueryIndex = useAnalysisBuilderStore((state) => state.setActiveQueryIndex)\n const setMergeStrategy = useAnalysisBuilderStore((state) => state.setMergeStrategy)\n const addQuery = useAnalysisBuilderStore((state) => state.addQuery)\n const removeQuery = useAnalysisBuilderStore((state) => state.removeQuery)\n\n // Store getters\n const getCurrentState = useAnalysisBuilderStore((state) => state.getCurrentState)\n const getMergeKeys = useAnalysisBuilderStore((state) => state.getMergeKeys)\n const isMultiQueryModeGetter = useAnalysisBuilderStore((state) => state.isMultiQueryMode)\n // Derived state\n const queryState = getCurrentState()\n const isMultiQueryMode = isMultiQueryModeGetter()\n const mergeKeys = getMergeKeys()\n\n // Build current query from active state\n const currentQuery = useMemo(() => {\n const current = queryStates[activeQueryIndex] || queryState\n return buildCubeQuery(current.metrics, current.breakdowns, current.filters, current.order)\n }, [queryStates, activeQueryIndex, queryState])\n\n // Build all queries (respect merge mode for shared breakdowns)\n const allQueries = useMemo(() => {\n const q1Breakdowns = queryStates[0]?.breakdowns || []\n return queryStates.map((qs, index) => {\n const breakdowns = mergeStrategy === 'merge' && index > 0 ? q1Breakdowns : qs.breakdowns\n return buildCubeQuery(qs.metrics, breakdowns, qs.filters, qs.order)\n })\n }, [queryStates, mergeStrategy])\n\n // Build multi-query config from queries\n const multiQueryConfig = useMemo(() => {\n if (queryStates.length <= 1) return null\n\n const validQueries = allQueries.filter(\n (q) =>\n (q.measures && q.measures.length > 0) ||\n (q.dimensions && q.dimensions.length > 0) ||\n (q.timeDimensions && q.timeDimensions.length > 0)\n )\n\n if (validQueries.length < 2) return null\n\n return {\n queries: validQueries,\n mergeStrategy,\n mergeKeys,\n queryLabels: validQueries.map((_, i) => `Q${i + 1}`),\n }\n }, [allQueries, queryStates.length, mergeStrategy, mergeKeys])\n\n // Validate multi-query configuration\n const multiQueryValidation = useMemo((): MultiQueryValidationResult | null => {\n if (!isMultiQueryMode) return null\n return validateMultiQueryConfig(allQueries, mergeStrategy, mergeKeys || [])\n }, [isMultiQueryMode, allQueries, mergeStrategy, mergeKeys])\n\n // Check if query is valid\n const isValidQuery = useMemo(() => {\n return (\n (currentQuery.measures && currentQuery.measures.length > 0) ||\n (currentQuery.dimensions && currentQuery.dimensions.length > 0) ||\n (currentQuery.timeDimensions && currentQuery.timeDimensions.length > 0)\n )\n }, [currentQuery])\n\n return {\n queryState,\n queryStates,\n activeQueryIndex,\n mergeStrategy,\n isMultiQueryMode,\n mergeKeys,\n currentQuery,\n allQueries,\n multiQueryConfig,\n multiQueryValidation,\n isValidQuery,\n\n // Actions\n setActiveQueryIndex,\n setMergeStrategy,\n addQuery,\n removeQuery,\n }\n}\n","/**\n * useAnalysisCombinedFields\n *\n * Computes combined metrics and breakdowns from all queries in multi-query mode.\n * In single-query mode, returns the current query's metrics and breakdowns.\n */\n\nimport { useMemo } from 'react'\nimport type { AnalysisBuilderState, MetricItem, BreakdownItem } from '../components/AnalysisBuilder/types'\nimport type { QueryMergeStrategy } from '../types'\n\nexport interface UseAnalysisCombinedFieldsOptions {\n queryState: AnalysisBuilderState\n queryStates: AnalysisBuilderState[]\n isMultiQueryMode: boolean\n mergeStrategy: QueryMergeStrategy\n activeQueryIndex: number\n}\n\nexport interface UseAnalysisCombinedFieldsResult {\n /** Combined metrics from all queries (for chart config) */\n combinedMetrics: MetricItem[]\n /** Combined breakdowns from all queries (for chart config) */\n combinedBreakdowns: BreakdownItem[]\n /** Effective breakdowns for display (Q1's in merge mode, otherwise current query's) */\n effectiveBreakdowns: BreakdownItem[]\n}\n\nexport function useAnalysisCombinedFields(\n options: UseAnalysisCombinedFieldsOptions\n): UseAnalysisCombinedFieldsResult {\n const { queryState, queryStates, isMultiQueryMode, mergeStrategy, activeQueryIndex } = options\n\n // Combined metrics from all queries\n const combinedMetrics = useMemo(() => {\n if (!isMultiQueryMode) return queryState.metrics\n const seen = new Set<string>()\n const combined: MetricItem[] = []\n for (let qIndex = 0; qIndex < queryStates.length; qIndex++) {\n const qs = queryStates[qIndex]\n for (const metric of qs.metrics) {\n const key = `Q${qIndex + 1}:${metric.field}`\n if (!seen.has(key)) {\n seen.add(key)\n combined.push({\n ...metric,\n label: `${metric.label} (Q${qIndex + 1})`,\n })\n }\n }\n }\n return combined\n }, [isMultiQueryMode, queryStates, queryState.metrics])\n\n // Combined breakdowns from all queries\n const combinedBreakdowns = useMemo(() => {\n if (!isMultiQueryMode) return queryState.breakdowns\n const seen = new Set<string>()\n const combined: BreakdownItem[] = []\n for (const qs of queryStates) {\n for (const breakdown of qs.breakdowns) {\n if (!seen.has(breakdown.field)) {\n seen.add(breakdown.field)\n combined.push(breakdown)\n }\n }\n }\n return combined\n }, [isMultiQueryMode, queryStates, queryState.breakdowns])\n\n // Effective breakdowns for the current view\n // In merge mode, Q2+ should visually show Q1's breakdowns since they're shared\n const effectiveBreakdowns = useMemo(() => {\n if (mergeStrategy === 'merge' && activeQueryIndex > 0) {\n // Show Q1's breakdowns for Q2+ in merge mode\n return queryStates[0]?.breakdowns || []\n }\n return queryState.breakdowns\n }, [mergeStrategy, activeQueryIndex, queryStates, queryState.breakdowns])\n\n return {\n combinedMetrics,\n combinedBreakdowns,\n effectiveBreakdowns,\n }\n}\n","/**\n * useAnalysisQueryExecution\n *\n * Coordinates TanStack Query execution for single, multi-query, and funnel modes.\n * Provides unified loading states, results, and refetch functionality.\n */\n\nimport { useMemo, useCallback } from 'react'\nimport {\n useCubeLoadQuery,\n useMultiCubeLoadQuery,\n useFunnelQuery,\n useDryRunQueries,\n type DebugDataEntry,\n} from './queries'\nimport type { CubeQuery, MultiQueryConfig, FunnelBindingKey, QueryMergeStrategy } from '../types'\nimport type { ExecutionStatus } from '../components/AnalysisBuilder/types'\nimport { buildFunnelConfigFromQueries } from '../utils/funnelExecution'\n\nexport interface UseAnalysisQueryExecutionOptions {\n /** Current query (for single-query mode) */\n currentQuery: CubeQuery\n /** All queries (for dry-run and multi-query) */\n allQueries: CubeQuery[]\n /** Multi-query config (null if single-query mode) */\n multiQueryConfig: MultiQueryConfig | null\n /** Whether in multi-query mode */\n isMultiQueryMode: boolean\n /** Whether current query is valid */\n isValidQuery: boolean\n /** Initial data (skip first fetch) */\n initialData?: unknown[]\n /** Merge strategy (for detecting funnel mode) */\n mergeStrategy?: QueryMergeStrategy\n /** Funnel binding key (required for funnel mode) */\n funnelBindingKey?: FunnelBindingKey | null\n}\n\nexport interface UseAnalysisQueryExecutionResult {\n /** Query execution status */\n executionStatus: ExecutionStatus\n /** Query results (merged for multi-query) */\n executionResults: unknown[] | null\n /** Per-query results (for table view in multi-query mode) */\n perQueryResults: (unknown[] | null)[] | null\n /** Whether query is loading */\n isLoading: boolean\n /** Whether query is fetching (includes refetch) */\n isFetching: boolean\n /** Query error */\n error: Error | null\n /** Debug data per query */\n debugDataPerQuery: DebugDataEntry[]\n /** Whether query has been debounced (for smart defaults trigger) */\n hasDebounced: boolean\n /** Refetch function */\n refetch: () => void\n /**\n * In funnel mode, these are the actually executed queries with:\n * - Binding key dimension auto-added\n * - IN filter applied for steps 2+\n * Use these for debug display instead of the original queries.\n */\n funnelExecutedQueries: CubeQuery[] | null\n}\n\nexport function useAnalysisQueryExecution(\n options: UseAnalysisQueryExecutionOptions\n): UseAnalysisQueryExecutionResult {\n const {\n currentQuery,\n allQueries,\n multiQueryConfig,\n isMultiQueryMode,\n isValidQuery,\n initialData,\n mergeStrategy,\n funnelBindingKey,\n } = options\n\n // Determine if we're in funnel mode\n const isFunnelMode = mergeStrategy === 'funnel' && isMultiQueryMode\n\n // Build funnel config when in funnel mode\n const funnelConfig = useMemo(() => {\n if (!isFunnelMode || !funnelBindingKey || allQueries.length < 2) return null\n return buildFunnelConfigFromQueries(allQueries, funnelBindingKey)\n }, [isFunnelMode, funnelBindingKey, allQueries])\n\n // Single query execution\n const singleQueryResult = useCubeLoadQuery(currentQuery, {\n skip: !isValidQuery || isMultiQueryMode,\n debounceMs: 300,\n })\n\n // Multi-query execution (skip in funnel mode)\n const multiQueryResult = useMultiCubeLoadQuery(multiQueryConfig, {\n skip: !multiQueryConfig || !isMultiQueryMode || isFunnelMode,\n debounceMs: 300,\n })\n\n // Funnel query execution\n const funnelQueryResult = useFunnelQuery(funnelConfig, {\n skip: !isFunnelMode || !funnelConfig,\n debounceMs: 300,\n })\n\n // Dry-run queries for debug data\n const dryRunResult = useDryRunQueries({\n queries: isMultiQueryMode ? allQueries : [currentQuery],\n isMultiQueryMode,\n skip: !isValidQuery,\n })\n\n // Unify results based on mode\n const isLoading = isFunnelMode\n ? funnelQueryResult.isExecuting || funnelQueryResult.isDebouncing\n : isMultiQueryMode\n ? multiQueryResult.isLoading\n : singleQueryResult.isLoading\n const isFetching = isFunnelMode\n ? funnelQueryResult.isExecuting\n : isMultiQueryMode\n ? multiQueryResult.isFetching\n : singleQueryResult.isFetching\n const error = isFunnelMode\n ? funnelQueryResult.error\n : isMultiQueryMode\n ? multiQueryResult.error\n : singleQueryResult.error\n\n // Has debounced (for smart defaults trigger)\n const hasDebounced = Boolean(\n singleQueryResult.debouncedQuery ||\n multiQueryResult.debouncedConfig ||\n !funnelQueryResult.isDebouncing // Funnel has debounced when not debouncing\n )\n\n // Unified refetch function\n const refetch = useCallback(() => {\n if (isFunnelMode) {\n funnelQueryResult.execute()\n } else if (isMultiQueryMode) {\n multiQueryResult.refetch()\n } else {\n singleQueryResult.refetch()\n }\n }, [isFunnelMode, isMultiQueryMode, funnelQueryResult, multiQueryResult, singleQueryResult])\n\n // Execution status\n const executionStatus: ExecutionStatus = useMemo(() => {\n const hasResults = isFunnelMode\n ? funnelQueryResult.chartData\n : isMultiQueryMode\n ? multiQueryResult.data\n : singleQueryResult.rawData\n if (initialData && initialData.length > 0 && !hasResults) return 'success'\n if (!isValidQuery) return 'idle'\n if (isLoading && !hasResults) return 'loading'\n if (isFetching && hasResults) return 'refreshing'\n if (error) return 'error'\n if (hasResults) return 'success'\n return 'idle'\n }, [isValidQuery, isLoading, isFetching, error, singleQueryResult.rawData, multiQueryResult.data, funnelQueryResult.chartData, initialData, isMultiQueryMode, isFunnelMode])\n\n // Execution results\n const executionResults = useMemo(() => {\n // Funnel mode returns chart data directly\n if (isFunnelMode && funnelQueryResult.chartData) {\n return funnelQueryResult.chartData as unknown[]\n }\n if (isMultiQueryMode && multiQueryResult.data) {\n return multiQueryResult.data as unknown[]\n }\n if (singleQueryResult.rawData) {\n return singleQueryResult.rawData\n }\n if (initialData && initialData.length > 0) {\n return initialData\n }\n return null\n }, [singleQueryResult.rawData, multiQueryResult.data, funnelQueryResult.chartData, initialData, isMultiQueryMode, isFunnelMode])\n\n // Per-query results for table view (or per-step for funnel)\n const perQueryResults = useMemo(() => {\n // In funnel mode, return step results as per-query data\n if (isFunnelMode && funnelQueryResult.stepResults) {\n return funnelQueryResult.stepResults.map((step) => step.data)\n }\n if (!isMultiQueryMode || !multiQueryResult.perQueryData) return null\n return multiQueryResult.perQueryData\n }, [isMultiQueryMode, isFunnelMode, multiQueryResult.perQueryData, funnelQueryResult.stepResults])\n\n // In funnel mode, provide the executed queries for debug display\n const funnelExecutedQueries = isFunnelMode && funnelQueryResult.executedQueries?.length > 0\n ? funnelQueryResult.executedQueries\n : null\n\n return {\n executionStatus,\n executionResults,\n perQueryResults,\n isLoading,\n isFetching,\n error,\n debugDataPerQuery: dryRunResult.debugDataPerQuery,\n hasDebounced,\n refetch,\n funnelExecutedQueries,\n }\n}\n","/**\n * useAnalysisChartDefaults\n *\n * Manages chart configuration, availability, and smart defaulting.\n * Handles color palette resolution and chart type auto-switching.\n */\n\nimport { useMemo, useEffect, useRef } from 'react'\nimport { useAnalysisBuilderStore } from '../stores/analysisBuilderStore'\nimport { getAllChartAvailability, getSmartChartDefaults, shouldAutoSwitchChartType } from '../shared/chartDefaults'\nimport { getColorPalette, type ColorPalette } from '../utils/colorPalettes'\nimport type { ChartType, ChartAxisConfig, ChartDisplayConfig } from '../types'\nimport type { MetricItem, BreakdownItem } from '../components/AnalysisBuilder/types'\nimport type { ChartAvailabilityMap } from '../shared/chartDefaults'\n\nexport interface UseAnalysisChartDefaultsOptions {\n /** External color palette (overrides local) */\n externalColorPalette?: string[] | ColorPalette\n /** Combined metrics from all queries */\n combinedMetrics: MetricItem[]\n /** Combined breakdowns from all queries */\n combinedBreakdowns: BreakdownItem[]\n /** Whether query has been debounced (triggers smart defaults) */\n hasDebounced: boolean\n}\n\nexport interface UseAnalysisChartDefaultsResult {\n /** Current chart type */\n chartType: ChartType\n /** Chart axis configuration */\n chartConfig: ChartAxisConfig\n /** Chart display configuration */\n displayConfig: ChartDisplayConfig\n /** Effective color palette */\n colorPalette: ColorPalette\n /** Local palette name (when not using external) */\n localPaletteName: string\n /** Chart availability map */\n chartAvailability: ChartAvailabilityMap\n /** User manually selected chart */\n userManuallySelectedChart: boolean\n\n // Actions\n setChartType: (type: ChartType) => void\n setChartConfig: (config: ChartAxisConfig) => void\n setDisplayConfig: (config: ChartDisplayConfig) => void\n setLocalPaletteName: (name: string) => void\n}\n\nexport function useAnalysisChartDefaults(\n options: UseAnalysisChartDefaultsOptions\n): UseAnalysisChartDefaultsResult {\n const { externalColorPalette, combinedMetrics, combinedBreakdowns, hasDebounced } = options\n\n // Store state\n const chartType = useAnalysisBuilderStore((state) => state.chartType)\n const chartConfig = useAnalysisBuilderStore((state) => state.chartConfig)\n const displayConfig = useAnalysisBuilderStore((state) => state.displayConfig)\n const userManuallySelectedChart = useAnalysisBuilderStore((state) => state.userManuallySelectedChart)\n const localPaletteName = useAnalysisBuilderStore((state) => state.localPaletteName)\n\n // Store actions\n const setChartType = useAnalysisBuilderStore((state) => state.setChartType)\n const setChartTypeManual = useAnalysisBuilderStore((state) => state.setChartTypeManual)\n const setChartConfig = useAnalysisBuilderStore((state) => state.setChartConfig)\n const setDisplayConfig = useAnalysisBuilderStore((state) => state.setDisplayConfig)\n const setLocalPaletteName = useAnalysisBuilderStore((state) => state.setLocalPaletteName)\n const setUserManuallySelectedChart = useAnalysisBuilderStore((state) => state.setUserManuallySelectedChart)\n\n // Chart availability\n const chartAvailability = useMemo(\n () => getAllChartAvailability(combinedMetrics, combinedBreakdowns),\n [combinedMetrics, combinedBreakdowns]\n )\n\n // Effective color palette\n const colorPalette = useMemo((): ColorPalette => {\n if (externalColorPalette) {\n if (Array.isArray(externalColorPalette) && typeof externalColorPalette[0] === 'string') {\n return {\n name: 'custom',\n label: 'Custom',\n colors: externalColorPalette as string[],\n gradient: externalColorPalette as string[],\n }\n }\n return externalColorPalette as ColorPalette\n }\n return getColorPalette(localPaletteName)\n }, [externalColorPalette, localPaletteName])\n\n // Smart chart defaulting\n const prevMetricsBreakdownsRef = useRef<string>('')\n\n useEffect(() => {\n if (!hasDebounced) return\n if (combinedMetrics.length === 0 && combinedBreakdowns.length === 0) return\n\n const currentKey = JSON.stringify({\n metrics: combinedMetrics.map((m) => m.field),\n breakdowns: combinedBreakdowns.map((b) => ({ field: b.field, isTime: b.isTimeDimension })),\n })\n\n if (currentKey === prevMetricsBreakdownsRef.current) return\n prevMetricsBreakdownsRef.current = currentKey\n\n const newChartType = shouldAutoSwitchChartType(\n combinedMetrics,\n combinedBreakdowns,\n chartType,\n userManuallySelectedChart\n )\n\n if (newChartType) {\n const { chartConfig: newConfig } = getSmartChartDefaults(\n combinedMetrics,\n combinedBreakdowns,\n newChartType\n )\n setChartType(newChartType)\n setChartConfig(newConfig)\n setUserManuallySelectedChart(false)\n } else if (combinedMetrics.length > 0 || combinedBreakdowns.length > 0) {\n // Apply smart defaults only if chart config is empty\n const isChartConfigEmpty =\n !chartConfig.xAxis?.length &&\n !chartConfig.yAxis?.length &&\n !chartConfig.series?.length\n if (isChartConfigEmpty) {\n const { chartConfig: smartDefaults } = getSmartChartDefaults(\n combinedMetrics,\n combinedBreakdowns,\n chartType\n )\n setChartConfig(smartDefaults)\n }\n }\n }, [\n hasDebounced,\n combinedMetrics,\n combinedBreakdowns,\n chartType,\n userManuallySelectedChart,\n chartConfig,\n setChartType,\n setChartConfig,\n setUserManuallySelectedChart,\n ])\n\n return {\n chartType,\n chartConfig,\n displayConfig,\n colorPalette,\n localPaletteName,\n chartAvailability,\n userManuallySelectedChart,\n\n // Actions - use manual setter for user interactions\n setChartType: setChartTypeManual,\n setChartConfig,\n setDisplayConfig,\n setLocalPaletteName,\n }\n}\n","/**\n * useAnalysisUIState\n *\n * Manages UI-only state for AnalysisBuilder:\n * - Active tab selection\n * - View toggle (table/chart)\n * - Field modal state\n * - Display limit\n * - Active table index for multi-query\n */\n\nimport { useState } from 'react'\nimport { useAnalysisBuilderStore, type FieldModalMode } from '../stores/analysisBuilderStore'\nimport type { QueryPanelTab } from '../components/AnalysisBuilder/types'\n\nexport interface UseAnalysisUIStateResult {\n /** Active tab in query panel */\n activeTab: QueryPanelTab\n /** Active view (table or chart) */\n activeView: 'table' | 'chart'\n /** Display limit for table */\n displayLimit: number\n /** Whether field modal is open */\n showFieldModal: boolean\n /** Field modal mode */\n fieldModalMode: FieldModalMode\n /** Active table index for multi-query */\n activeTableIndex: number\n /** User manually selected chart */\n userManuallySelectedChart: boolean\n\n // Actions\n setActiveTab: (tab: QueryPanelTab) => void\n setActiveView: (view: 'table' | 'chart') => void\n setDisplayLimit: (limit: number) => void\n closeFieldModal: () => void\n setActiveTableIndex: (index: number) => void\n}\n\nexport function useAnalysisUIState(): UseAnalysisUIStateResult {\n // Store state\n const activeTab = useAnalysisBuilderStore((state) => state.activeTab)\n const activeView = useAnalysisBuilderStore((state) => state.activeView)\n const displayLimit = useAnalysisBuilderStore((state) => state.displayLimit)\n const showFieldModal = useAnalysisBuilderStore((state) => state.showFieldModal)\n const fieldModalMode = useAnalysisBuilderStore((state) => state.fieldModalMode)\n const userManuallySelectedChart = useAnalysisBuilderStore((state) => state.userManuallySelectedChart)\n\n // Store actions\n const setActiveTab = useAnalysisBuilderStore((state) => state.setActiveTab)\n const setActiveView = useAnalysisBuilderStore((state) => state.setActiveView)\n const setDisplayLimit = useAnalysisBuilderStore((state) => state.setDisplayLimit)\n const closeFieldModal = useAnalysisBuilderStore((state) => state.closeFieldModal)\n\n // Local state for table index (not persisted)\n const [activeTableIndex, setActiveTableIndex] = useState(0)\n\n return {\n // State\n activeTab,\n activeView,\n displayLimit,\n showFieldModal,\n fieldModalMode,\n activeTableIndex,\n userManuallySelectedChart,\n\n // Actions\n setActiveTab,\n setActiveView,\n setDisplayLimit,\n closeFieldModal,\n setActiveTableIndex,\n }\n}\n","// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>\n// This work is free. You can redistribute it and/or modify it\n// under the terms of the WTFPL, Version 2\n// For more information see LICENSE.txt or http://www.wtfpl.net/\n//\n// For more information, the home page:\n// http://pieroxy.net/blog/pages/lz-string/testing.html\n//\n// LZ-based compression algorithm, version 1.4.5\nvar LZString = (function() {\n\n// private property\nvar f = String.fromCharCode;\nvar keyStrBase64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\nvar keyStrUriSafe = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$\";\nvar baseReverseDic = {};\n\nfunction getBaseValue(alphabet, character) {\n if (!baseReverseDic[alphabet]) {\n baseReverseDic[alphabet] = {};\n for (var i=0 ; i<alphabet.length ; i++) {\n baseReverseDic[alphabet][alphabet.charAt(i)] = i;\n }\n }\n return baseReverseDic[alphabet][character];\n}\n\nvar LZString = {\n compressToBase64 : function (input) {\n if (input == null) return \"\";\n var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});\n switch (res.length % 4) { // To produce valid Base64\n default: // When could this happen ?\n case 0 : return res;\n case 1 : return res+\"===\";\n case 2 : return res+\"==\";\n case 3 : return res+\"=\";\n }\n },\n\n decompressFromBase64 : function (input) {\n if (input == null) return \"\";\n if (input == \"\") return null;\n return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });\n },\n\n compressToUTF16 : function (input) {\n if (input == null) return \"\";\n return LZString._compress(input, 15, function(a){return f(a+32);}) + \" \";\n },\n\n decompressFromUTF16: function (compressed) {\n if (compressed == null) return \"\";\n if (compressed == \"\") return null;\n return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });\n },\n\n //compress into uint8array (UCS-2 big endian format)\n compressToUint8Array: function (uncompressed) {\n var compressed = LZString.compress(uncompressed);\n var buf=new Uint8Array(compressed.length*2); // 2 bytes per character\n\n for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {\n var current_value = compressed.charCodeAt(i);\n buf[i*2] = current_value >>> 8;\n buf[i*2+1] = current_value % 256;\n }\n return buf;\n },\n\n //decompress from uint8array (UCS-2 big endian format)\n decompressFromUint8Array:function (compressed) {\n if (compressed===null || compressed===undefined){\n return LZString.decompress(compressed);\n } else {\n var buf=new Array(compressed.length/2); // 2 bytes per character\n for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {\n buf[i]=compressed[i*2]*256+compressed[i*2+1];\n }\n\n var result = [];\n buf.forEach(function (c) {\n result.push(f(c));\n });\n return LZString.decompress(result.join(''));\n\n }\n\n },\n\n\n //compress into a string that is already URI encoded\n compressToEncodedURIComponent: function (input) {\n if (input == null) return \"\";\n return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});\n },\n\n //decompress from an output of compressToEncodedURIComponent\n decompressFromEncodedURIComponent:function (input) {\n if (input == null) return \"\";\n if (input == \"\") return null;\n input = input.replace(/ /g, \"+\");\n return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });\n },\n\n compress: function (uncompressed) {\n return LZString._compress(uncompressed, 16, function(a){return f(a);});\n },\n _compress: function (uncompressed, bitsPerChar, getCharFromInt) {\n if (uncompressed == null) return \"\";\n var i, value,\n context_dictionary= {},\n context_dictionaryToCreate= {},\n context_c=\"\",\n context_wc=\"\",\n context_w=\"\",\n context_enlargeIn= 2, // Compensate for the first entry which should not count\n context_dictSize= 3,\n context_numBits= 2,\n context_data=[],\n context_data_val=0,\n context_data_position=0,\n ii;\n\n for (ii = 0; ii < uncompressed.length; ii += 1) {\n context_c = uncompressed.charAt(ii);\n if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {\n context_dictionary[context_c] = context_dictSize++;\n context_dictionaryToCreate[context_c] = true;\n }\n\n context_wc = context_w + context_c;\n if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {\n context_w = context_wc;\n } else {\n if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {\n if (context_w.charCodeAt(0)<256) {\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n }\n value = context_w.charCodeAt(0);\n for (i=0 ; i<8 ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n } else {\n value = 1;\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1) | value;\n if (context_data_position ==bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = 0;\n }\n value = context_w.charCodeAt(0);\n for (i=0 ; i<16 ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n }\n context_enlargeIn--;\n if (context_enlargeIn == 0) {\n context_enlargeIn = Math.pow(2, context_numBits);\n context_numBits++;\n }\n delete context_dictionaryToCreate[context_w];\n } else {\n value = context_dictionary[context_w];\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n\n\n }\n context_enlargeIn--;\n if (context_enlargeIn == 0) {\n context_enlargeIn = Math.pow(2, context_numBits);\n context_numBits++;\n }\n // Add wc to the dictionary.\n context_dictionary[context_wc] = context_dictSize++;\n context_w = String(context_c);\n }\n }\n\n // Output the code for w.\n if (context_w !== \"\") {\n if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {\n if (context_w.charCodeAt(0)<256) {\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n }\n value = context_w.charCodeAt(0);\n for (i=0 ; i<8 ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n } else {\n value = 1;\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1) | value;\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = 0;\n }\n value = context_w.charCodeAt(0);\n for (i=0 ; i<16 ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n }\n context_enlargeIn--;\n if (context_enlargeIn == 0) {\n context_enlargeIn = Math.pow(2, context_numBits);\n context_numBits++;\n }\n delete context_dictionaryToCreate[context_w];\n } else {\n value = context_dictionary[context_w];\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n\n\n }\n context_enlargeIn--;\n if (context_enlargeIn == 0) {\n context_enlargeIn = Math.pow(2, context_numBits);\n context_numBits++;\n }\n }\n\n // Mark the end of the stream\n value = 2;\n for (i=0 ; i<context_numBits ; i++) {\n context_data_val = (context_data_val << 1) | (value&1);\n if (context_data_position == bitsPerChar-1) {\n context_data_position = 0;\n context_data.push(getCharFromInt(context_data_val));\n context_data_val = 0;\n } else {\n context_data_position++;\n }\n value = value >> 1;\n }\n\n // Flush the last char\n while (true) {\n context_data_val = (context_data_val << 1);\n if (context_data_position == bitsPerChar-1) {\n context_data.push(getCharFromInt(context_data_val));\n break;\n }\n else context_data_position++;\n }\n return context_data.join('');\n },\n\n decompress: function (compressed) {\n if (compressed == null) return \"\";\n if (compressed == \"\") return null;\n return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });\n },\n\n _decompress: function (length, resetValue, getNextValue) {\n var dictionary = [],\n next,\n enlargeIn = 4,\n dictSize = 4,\n numBits = 3,\n entry = \"\",\n result = [],\n i,\n w,\n bits, resb, maxpower, power,\n c,\n data = {val:getNextValue(0), position:resetValue, index:1};\n\n for (i = 0; i < 3; i += 1) {\n dictionary[i] = i;\n }\n\n bits = 0;\n maxpower = Math.pow(2,2);\n power=1;\n while (power!=maxpower) {\n resb = data.val & data.position;\n data.position >>= 1;\n if (data.position == 0) {\n data.position = resetValue;\n data.val = getNextValue(data.index++);\n }\n bits |= (resb>0 ? 1 : 0) * power;\n power <<= 1;\n }\n\n switch (next = bits) {\n case 0:\n bits = 0;\n maxpower = Math.pow(2,8);\n power=1;\n while (power!=maxpower) {\n resb = data.val & data.position;\n data.position >>= 1;\n if (data.position == 0) {\n data.position = resetValue;\n data.val = getNextValue(data.index++);\n }\n bits |= (resb>0 ? 1 : 0) * power;\n power <<= 1;\n }\n c = f(bits);\n break;\n case 1:\n bits = 0;\n maxpower = Math.pow(2,16);\n power=1;\n while (power!=maxpower) {\n resb = data.val & data.position;\n data.position >>= 1;\n if (data.position == 0) {\n data.position = resetValue;\n data.val = getNextValue(data.index++);\n }\n bits |= (resb>0 ? 1 : 0) * power;\n power <<= 1;\n }\n c = f(bits);\n break;\n case 2:\n return \"\";\n }\n dictionary[3] = c;\n w = c;\n result.push(c);\n while (true) {\n if (data.index > length) {\n return \"\";\n }\n\n bits = 0;\n maxpower = Math.pow(2,numBits);\n power=1;\n while (power!=maxpower) {\n resb = data.val & data.position;\n data.position >>= 1;\n if (data.position == 0) {\n data.position = resetValue;\n data.val = getNextValue(data.index++);\n }\n bits |= (resb>0 ? 1 : 0) * power;\n power <<= 1;\n }\n\n switch (c = bits) {\n case 0:\n bits = 0;\n maxpower = Math.pow(2,8);\n power=1;\n while (power!=maxpower) {\n resb = data.val & data.position;\n data.position >>= 1;\n if (data.position == 0) {\n data.position = resetValue;\n data.val = getNextValue(data.index++);\n }\n bits |= (resb>0 ? 1 : 0) * power;\n power <<= 1;\n }\n\n dictionary[dictSize++] = f(bits);\n c = dictSize-1;\n enlargeIn--;\n break;\n case 1:\n bits = 0;\n maxpower = Math.pow(2,16);\n power=1;\n while (power!=maxpower) {\n resb = data.val & data.position;\n data.position >>= 1;\n if (data.position == 0) {\n data.position = resetValue;\n data.val = getNextValue(data.index++);\n }\n bits |= (resb>0 ? 1 : 0) * power;\n power <<= 1;\n }\n dictionary[dictSize++] = f(bits);\n c = dictSize-1;\n enlargeIn--;\n break;\n case 2:\n return result.join('');\n }\n\n if (enlargeIn == 0) {\n enlargeIn = Math.pow(2, numBits);\n numBits++;\n }\n\n if (dictionary[c]) {\n entry = dictionary[c];\n } else {\n if (c === dictSize) {\n entry = w + w.charAt(0);\n } else {\n return null;\n }\n }\n result.push(entry);\n\n // Add w+entry[0] to the dictionary.\n dictionary[dictSize++] = w + entry.charAt(0);\n enlargeIn--;\n\n w = entry;\n\n if (enlargeIn == 0) {\n enlargeIn = Math.pow(2, numBits);\n numBits++;\n }\n\n }\n }\n};\n return LZString;\n})();\n\nif (typeof define === 'function' && define.amd) {\n define(function () { return LZString; });\n} else if( typeof module !== 'undefined' && module != null ) {\n module.exports = LZString\n} else if( typeof angular !== 'undefined' && angular != null ) {\n angular.module('LZString', [])\n .factory('LZString', function () {\n return LZString;\n });\n}\n","/**\n * Share utilities for QueryBuilder\n *\n * Handles compression, encoding, and URL generation for sharing analysis state.\n * Uses LZ-String for compression which produces URL-safe output.\n */\n\nimport { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string'\nimport type { CubeQuery, ChartType, ChartAxisConfig, ChartDisplayConfig, MultiQueryConfig } from '../types'\n\n/**\n * State that can be shared via URL\n * Query is required (can be single CubeQuery or MultiQueryConfig), chart config is optional (may be dropped if too large)\n */\nexport interface ShareableState {\n query: CubeQuery | MultiQueryConfig\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n activeView?: 'table' | 'chart'\n}\n\n/**\n * Result of compression with fallback\n */\nexport interface CompressionResult {\n encoded: string | null\n queryOnly: boolean\n}\n\n// Max safe URL hash length (conservative for browser compatibility)\nconst MAX_HASH_LENGTH = 1800\nconst SHARE_PREFIX = 'share='\n\n/**\n * Compress state to URL-safe encoded string\n */\nexport function compressAndEncode(state: ShareableState): string {\n const json = JSON.stringify(state)\n return compressToEncodedURIComponent(json)\n}\n\n/**\n * Decompress URL-safe encoded string back to state\n * Returns null if decompression or parsing fails\n */\nexport function decodeAndDecompress(encoded: string): ShareableState | null {\n try {\n const json = decompressFromEncodedURIComponent(encoded)\n if (!json) return null\n\n const state = JSON.parse(json) as ShareableState\n\n // Validate required field\n if (!state.query || typeof state.query !== 'object') {\n return null\n }\n\n return state\n } catch {\n return null\n }\n}\n\n/**\n * Check if compressed state fits within URL length limit\n */\nexport function isShareableSize(state: ShareableState): { ok: boolean; size: number; maxSize: number } {\n const encoded = compressAndEncode(state)\n return {\n ok: encoded.length <= MAX_HASH_LENGTH,\n size: encoded.length,\n maxSize: MAX_HASH_LENGTH\n }\n}\n\n/**\n * Compress state with automatic fallback\n * If full state is too large, tries with query only\n * Returns null encoded if even query-only is too large\n */\nexport function compressWithFallback(state: ShareableState): CompressionResult {\n // Try full state first\n const fullEncoded = compressAndEncode(state)\n if (fullEncoded.length <= MAX_HASH_LENGTH) {\n return { encoded: fullEncoded, queryOnly: false }\n }\n\n // Fall back to query only\n const queryOnlyState: ShareableState = { query: state.query }\n const queryOnlyEncoded = compressAndEncode(queryOnlyState)\n\n if (queryOnlyEncoded.length <= MAX_HASH_LENGTH) {\n return { encoded: queryOnlyEncoded, queryOnly: true }\n }\n\n // Even query-only is too large\n return { encoded: null, queryOnly: true }\n}\n\n/**\n * Generate full share URL with compressed state in hash\n */\nexport function generateShareUrl(state: ShareableState): string | null {\n const { encoded } = compressWithFallback(state)\n if (!encoded) return null\n\n return `${window.location.origin}${window.location.pathname}#${SHARE_PREFIX}${encoded}`\n}\n\n/**\n * Parse share hash from current URL\n * Returns encoded string if #share= is present, null otherwise\n */\nexport function parseShareHash(): string | null {\n if (typeof window === 'undefined') return null\n\n const hash = window.location.hash\n if (!hash || !hash.startsWith(`#${SHARE_PREFIX}`)) {\n return null\n }\n\n return hash.slice(SHARE_PREFIX.length + 1) // +1 for the #\n}\n\n/**\n * Clear share hash from URL without page reload\n */\nexport function clearShareHash(): void {\n if (typeof window === 'undefined') return\n\n const url = new URL(window.location.href)\n url.hash = ''\n window.history.replaceState(null, '', url.toString())\n}\n\n/**\n * Get the maximum allowed hash length\n */\nexport function getMaxHashLength(): number {\n return MAX_HASH_LENGTH\n}\n","/**\n * useAnalysisInitialization\n *\n * Handles initialization side effects:\n * - URL share loading on mount\n * - Callback forwarding (onQueryChange, onChartConfigChange)\n */\n\nimport { useEffect, useRef } from 'react'\nimport { useAnalysisBuilderStore, type SharedState } from '../stores/analysisBuilderStore'\nimport { parseShareHash, decodeAndDecompress, clearShareHash } from '../utils/shareUtils'\nimport type { CubeQuery, ChartType, ChartAxisConfig, ChartDisplayConfig } from '../types'\n\nexport interface UseAnalysisInitializationOptions {\n /** Current query */\n currentQuery: CubeQuery\n /** Whether query is valid */\n isValidQuery: boolean\n /** Chart type */\n chartType: ChartType\n /** Chart config */\n chartConfig: ChartAxisConfig\n /** Display config */\n displayConfig: ChartDisplayConfig\n /** Callback when query changes */\n onQueryChange?: (query: CubeQuery) => void\n /** Callback when chart config changes */\n onChartConfigChange?: (config: {\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n }) => void\n}\n\n/**\n * Handles initialization effects - no return value (side-effect only hook)\n */\nexport function useAnalysisInitialization(options: UseAnalysisInitializationOptions): void {\n const {\n currentQuery,\n isValidQuery,\n chartType,\n chartConfig,\n displayConfig,\n onQueryChange,\n onChartConfigChange,\n } = options\n\n // Get store action for loading from share\n const loadFromShare = useAnalysisBuilderStore((state) => state.loadFromShare)\n\n // URL share loading (on mount only)\n const hasInitializedShareRef = useRef(false)\n\n useEffect(() => {\n if (hasInitializedShareRef.current) return\n hasInitializedShareRef.current = true\n\n const encoded = parseShareHash()\n if (!encoded) return\n\n const sharedState = decodeAndDecompress(encoded) as SharedState | null\n if (!sharedState || !sharedState.query) return\n\n loadFromShare(sharedState)\n clearShareHash()\n }, [loadFromShare])\n\n // Query change callback\n useEffect(() => {\n if (onQueryChange && isValidQuery) {\n onQueryChange(currentQuery)\n }\n }, [currentQuery, isValidQuery, onQueryChange])\n\n // Chart config change callback\n useEffect(() => {\n if (onChartConfigChange) {\n onChartConfigChange({\n chartType,\n chartConfig,\n displayConfig,\n })\n }\n }, [chartType, chartConfig, displayConfig, onChartConfigChange])\n}\n","/**\n * useAnalysisBuilder - Master Coordination Hook\n *\n * The single hook that provides everything AnalysisBuilder needs.\n * Orchestrates sub-hooks for modular, maintainable code:\n *\n * - useAnalysisQueryBuilder: Query state, building, validation\n * - useAnalysisCombinedFields: Multi-query field merging\n * - useAnalysisQueryExecution: TanStack Query data fetching\n * - useAnalysisChartDefaults: Chart configuration and smart defaults\n * - useAnalysisUIState: UI state (tabs, modals, view toggle)\n * - useAnalysisInitialization: Side effects (URL loading, callbacks)\n *\n * IMPORTANT: This hook must be used within AnalysisBuilderStoreProvider\n */\n\nimport { useCallback, useRef } from 'react'\nimport { useCubeFeatures } from '../providers/CubeProvider'\nimport {\n useAnalysisBuilderStore,\n useAnalysisBuilderStoreApi,\n} from '../stores/analysisBuilderStore'\n\n// Sub-hooks\nimport { useAnalysisQueryBuilder } from './useAnalysisQueryBuilder'\nimport { useAnalysisCombinedFields } from './useAnalysisCombinedFields'\nimport { useAnalysisQueryExecution } from './useAnalysisQueryExecution'\nimport { useAnalysisChartDefaults } from './useAnalysisChartDefaults'\nimport { useAnalysisUIState } from './useAnalysisUIState'\nimport { useAnalysisInitialization } from './useAnalysisInitialization'\n\nimport type { ColorPalette } from '../utils/colorPalettes'\nimport type {\n CubeQuery,\n MultiQueryConfig,\n ChartType,\n ChartAxisConfig,\n ChartDisplayConfig,\n Filter,\n QueryMergeStrategy,\n FunnelBindingKey,\n} from '../types'\nimport type {\n AnalysisBuilderState,\n MetricItem,\n BreakdownItem,\n ExecutionStatus,\n QueryPanelTab,\n} from '../components/AnalysisBuilder/types'\nimport type { ChartAvailabilityMap } from '../shared/chartDefaults'\nimport type { DebugDataEntry } from './queries'\nimport type { MultiQueryValidationResult } from '../utils/multiQueryValidation'\nimport type { MetaField } from '../shared/types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseAnalysisBuilderOptions {\n /** External color palette (overrides local) */\n externalColorPalette?: string[] | ColorPalette\n /** Initial data (skip first fetch) */\n initialData?: unknown[]\n /** Callback when query changes */\n onQueryChange?: (query: CubeQuery) => void\n /** Callback when chart config changes */\n onChartConfigChange?: (config: {\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n }) => void\n}\n\nexport interface UseAnalysisBuilderResult {\n // Query State\n queryState: AnalysisBuilderState\n queryStates: AnalysisBuilderState[]\n activeQueryIndex: number\n mergeStrategy: QueryMergeStrategy\n isMultiQueryMode: boolean\n mergeKeys: string[] | undefined\n currentQuery: CubeQuery\n allQueries: CubeQuery[]\n multiQueryConfig: MultiQueryConfig | null\n multiQueryValidation: MultiQueryValidationResult | null\n\n // Funnel State\n funnelBindingKey: FunnelBindingKey | null\n\n // Data Fetching\n executionStatus: ExecutionStatus\n executionResults: unknown[] | null\n perQueryResults: (unknown[] | null)[] | null\n isLoading: boolean\n isFetching: boolean\n error: Error | null\n isValidQuery: boolean\n debugDataPerQuery: DebugDataEntry[]\n /** In funnel mode, the actually executed queries with binding key dimension and IN filters */\n funnelExecutedQueries: CubeQuery[] | null\n\n // Chart Configuration\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n colorPalette: ColorPalette\n localPaletteName: string\n chartAvailability: ChartAvailabilityMap\n combinedMetrics: MetricItem[]\n combinedBreakdowns: BreakdownItem[]\n effectiveBreakdowns: BreakdownItem[]\n\n // UI State\n activeTab: QueryPanelTab\n activeView: 'table' | 'chart'\n displayLimit: number\n showFieldModal: boolean\n fieldModalMode: 'metrics' | 'breakdown'\n activeTableIndex: number\n userManuallySelectedChart: boolean\n\n // AI State\n aiState: {\n isOpen: boolean\n userPrompt: string\n isGenerating: boolean\n error: string | null\n hasGeneratedQuery: boolean\n }\n\n // Share State\n shareButtonState: 'idle' | 'copied' | 'copied-no-chart'\n canShare: boolean\n\n // Actions\n actions: {\n setActiveQueryIndex: (index: number) => void\n setMergeStrategy: (strategy: QueryMergeStrategy) => void\n openMetricsModal: () => void\n addMetric: (field: string, label?: string) => void\n removeMetric: (id: string) => void\n toggleMetric: (fieldName: string) => void\n reorderMetrics: (fromIndex: number, toIndex: number) => void\n openBreakdownsModal: () => void\n addBreakdown: (field: string, isTimeDimension: boolean, granularity?: string) => void\n removeBreakdown: (id: string) => void\n toggleBreakdown: (fieldName: string, isTimeDimension: boolean, granularity?: string) => void\n setBreakdownGranularity: (id: string, granularity: string) => void\n toggleBreakdownComparison: (id: string) => void\n reorderBreakdowns: (fromIndex: number, toIndex: number) => void\n setFilters: (filters: Filter[]) => void\n dropFieldToFilter: (field: string) => void\n setOrder: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n addQuery: () => void\n removeQuery: (index: number) => void\n setFunnelBindingKey: (bindingKey: FunnelBindingKey | null) => void\n setChartType: (type: ChartType) => void\n setChartConfig: (config: ChartAxisConfig) => void\n setDisplayConfig: (config: ChartDisplayConfig) => void\n setLocalPaletteName: (name: string) => void\n setActiveTab: (tab: QueryPanelTab) => void\n setActiveView: (view: 'table' | 'chart') => void\n setDisplayLimit: (limit: number) => void\n closeFieldModal: () => void\n setActiveTableIndex: (index: number) => void\n openAI: () => void\n closeAI: () => void\n setAIPrompt: (prompt: string) => void\n generateAI: () => Promise<void>\n acceptAI: () => void\n cancelAI: () => void\n share: () => Promise<void>\n clearQuery: () => void\n refetch: () => void\n handleFieldSelected: (\n field: MetaField,\n fieldType: 'measure' | 'dimension' | 'timeDimension',\n cubeName: string,\n keepOpen?: boolean\n ) => void\n }\n\n // Refs (for imperative access)\n getQueryConfig: () => CubeQuery | MultiQueryConfig\n getChartConfig: () => {\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n }\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\nexport function useAnalysisBuilder(\n options: UseAnalysisBuilderOptions = {}\n): UseAnalysisBuilderResult {\n const { initialData, externalColorPalette, onQueryChange, onChartConfigChange } = options\n\n // Get context\n const { features } = useCubeFeatures()\n\n // Get store API for direct access\n const storeApi = useAnalysisBuilderStoreApi()\n\n // =========================================================================\n // Sub-Hooks Orchestration\n // =========================================================================\n\n // 1. Query Builder (query state, building, validation)\n const queryBuilder = useAnalysisQueryBuilder()\n\n // 2. Combined Fields (multi-query field merging)\n const combinedFields = useAnalysisCombinedFields({\n queryState: queryBuilder.queryState,\n queryStates: queryBuilder.queryStates,\n isMultiQueryMode: queryBuilder.isMultiQueryMode,\n mergeStrategy: queryBuilder.mergeStrategy,\n activeQueryIndex: queryBuilder.activeQueryIndex,\n })\n\n // Get funnel binding key from store for funnel mode\n const funnelBindingKey = useAnalysisBuilderStore((s) => s.funnelBindingKey)\n\n // 3. Query Execution (TanStack Query integration)\n const queryExecution = useAnalysisQueryExecution({\n currentQuery: queryBuilder.currentQuery,\n allQueries: queryBuilder.allQueries,\n multiQueryConfig: queryBuilder.multiQueryConfig,\n isMultiQueryMode: queryBuilder.isMultiQueryMode,\n isValidQuery: queryBuilder.isValidQuery ?? false,\n initialData,\n mergeStrategy: queryBuilder.mergeStrategy,\n funnelBindingKey,\n })\n\n // 4. Chart Defaults (chart config, availability, smart defaults)\n const chartDefaults = useAnalysisChartDefaults({\n externalColorPalette,\n combinedMetrics: combinedFields.combinedMetrics,\n combinedBreakdowns: combinedFields.combinedBreakdowns,\n hasDebounced: queryExecution.hasDebounced,\n })\n\n // 5. UI State (tabs, modals, view toggle)\n const uiState = useAnalysisUIState()\n\n // 6. Initialization (URL loading, callbacks - side effects only)\n useAnalysisInitialization({\n currentQuery: queryBuilder.currentQuery,\n isValidQuery: queryBuilder.isValidQuery ?? false,\n chartType: chartDefaults.chartType,\n chartConfig: chartDefaults.chartConfig,\n displayConfig: chartDefaults.displayConfig,\n onQueryChange,\n onChartConfigChange,\n })\n\n // =========================================================================\n // Store Actions (not covered by sub-hooks)\n // =========================================================================\n\n // Metric actions\n const openMetricsModal = useAnalysisBuilderStore((state) => state.openMetricsModal)\n const addMetric = useAnalysisBuilderStore((state) => state.addMetric)\n const removeMetric = useAnalysisBuilderStore((state) => state.removeMetric)\n const toggleMetric = useAnalysisBuilderStore((state) => state.toggleMetric)\n const reorderMetrics = useAnalysisBuilderStore((state) => state.reorderMetrics)\n\n // Breakdown actions\n const openBreakdownsModal = useAnalysisBuilderStore((state) => state.openBreakdownsModal)\n const addBreakdown = useAnalysisBuilderStore((state) => state.addBreakdown)\n const removeBreakdown = useAnalysisBuilderStore((state) => state.removeBreakdown)\n const toggleBreakdown = useAnalysisBuilderStore((state) => state.toggleBreakdown)\n const setBreakdownGranularity = useAnalysisBuilderStore((state) => state.setBreakdownGranularity)\n const toggleBreakdownComparison = useAnalysisBuilderStore((state) => state.toggleBreakdownComparison)\n const reorderBreakdowns = useAnalysisBuilderStore((state) => state.reorderBreakdowns)\n\n // Filter actions\n const setFilters = useAnalysisBuilderStore((state) => state.setFilters)\n const dropFieldToFilter = useAnalysisBuilderStore((state) => state.dropFieldToFilter)\n const setOrder = useAnalysisBuilderStore((state) => state.setOrder)\n\n // Utility actions\n const clearQuery = useAnalysisBuilderStore((state) => state.clearQuery)\n\n // Funnel actions\n const setFunnelBindingKey = useAnalysisBuilderStore((state) => state.setFunnelBindingKey)\n\n // AI state and actions\n const aiState = useAnalysisBuilderStore((state) => state.aiState)\n const openAI = useAnalysisBuilderStore((state) => state.openAI)\n const closeAI = useAnalysisBuilderStore((state) => state.closeAI)\n const setAIPrompt = useAnalysisBuilderStore((state) => state.setAIPrompt)\n const setAIGenerating = useAnalysisBuilderStore((state) => state.setAIGenerating)\n const setAIError = useAnalysisBuilderStore((state) => state.setAIError)\n const setAIHasGeneratedQuery = useAnalysisBuilderStore((state) => state.setAIHasGeneratedQuery)\n const saveAIPreviousState = useAnalysisBuilderStore((state) => state.saveAIPreviousState)\n const restoreAIPreviousState = useAnalysisBuilderStore((state) => state.restoreAIPreviousState)\n\n // =========================================================================\n // Share State\n // =========================================================================\n\n const shareButtonStateRef = useRef<'idle' | 'copied' | 'copied-no-chart'>('idle')\n const canShare = queryBuilder.isValidQuery ?? false\n\n // =========================================================================\n // Action Callbacks\n // =========================================================================\n\n const handleFieldSelected = useCallback(\n (\n field: MetaField,\n fieldType: 'measure' | 'dimension' | 'timeDimension',\n _cubeName: string,\n keepOpen?: boolean\n ) => {\n if (uiState.fieldModalMode === 'metrics' && fieldType === 'measure') {\n toggleMetric(field.name)\n } else if (uiState.fieldModalMode === 'breakdown') {\n toggleBreakdown(field.name, fieldType === 'timeDimension')\n }\n if (!keepOpen) {\n uiState.closeFieldModal()\n }\n },\n [uiState, toggleMetric, toggleBreakdown]\n )\n\n const generateAI = useCallback(async () => {\n if (!features?.aiEndpoint) return\n saveAIPreviousState()\n setAIGenerating(true)\n setAIError(null)\n\n try {\n // AI generation logic would go here\n await new Promise((resolve) => setTimeout(resolve, 1000))\n setAIHasGeneratedQuery(true)\n } catch (err) {\n setAIError(err instanceof Error ? err.message : 'Failed to generate query')\n } finally {\n setAIGenerating(false)\n }\n }, [features?.aiEndpoint, saveAIPreviousState, setAIGenerating, setAIError, setAIHasGeneratedQuery])\n\n const acceptAI = useCallback(() => {\n closeAI()\n setAIHasGeneratedQuery(false)\n }, [closeAI, setAIHasGeneratedQuery])\n\n const cancelAI = useCallback(() => {\n restoreAIPreviousState()\n closeAI()\n }, [restoreAIPreviousState, closeAI])\n\n const share = useCallback(async () => {\n shareButtonStateRef.current = 'copied'\n setTimeout(() => {\n shareButtonStateRef.current = 'idle'\n }, 2000)\n }, [])\n\n // =========================================================================\n // Ref API Functions\n // =========================================================================\n\n const getQueryConfig = useCallback(() => {\n const state = storeApi.getState()\n if (state.queryStates.length > 1) {\n return {\n queries: state.buildAllQueries(),\n mergeStrategy: state.mergeStrategy,\n mergeKeys: state.getMergeKeys(),\n queryLabels: state.queryStates.map((_, i) => `Q${i + 1}`),\n }\n }\n return state.buildCurrentQuery()\n }, [storeApi])\n\n const getChartConfig = useCallback(\n () => ({\n chartType: chartDefaults.chartType,\n chartConfig: chartDefaults.chartConfig,\n displayConfig: chartDefaults.displayConfig,\n }),\n [chartDefaults.chartType, chartDefaults.chartConfig, chartDefaults.displayConfig]\n )\n\n // =========================================================================\n // Return Value\n // =========================================================================\n\n return {\n // Query state (from queryBuilder)\n queryState: queryBuilder.queryState,\n queryStates: queryBuilder.queryStates,\n activeQueryIndex: queryBuilder.activeQueryIndex,\n mergeStrategy: queryBuilder.mergeStrategy,\n isMultiQueryMode: queryBuilder.isMultiQueryMode,\n mergeKeys: queryBuilder.mergeKeys,\n currentQuery: queryBuilder.currentQuery,\n allQueries: queryBuilder.allQueries,\n multiQueryConfig: queryBuilder.multiQueryConfig,\n multiQueryValidation: queryBuilder.multiQueryValidation,\n\n // Funnel state\n funnelBindingKey,\n\n // Data fetching (from queryExecution)\n executionStatus: queryExecution.executionStatus,\n executionResults: queryExecution.executionResults,\n perQueryResults: queryExecution.perQueryResults,\n isLoading: queryExecution.isLoading,\n isFetching: queryExecution.isFetching,\n error: queryExecution.error,\n isValidQuery: queryBuilder.isValidQuery ?? false,\n debugDataPerQuery: queryExecution.debugDataPerQuery,\n funnelExecutedQueries: queryExecution.funnelExecutedQueries,\n\n // Chart configuration (from chartDefaults)\n chartType: chartDefaults.chartType,\n chartConfig: chartDefaults.chartConfig,\n displayConfig: chartDefaults.displayConfig,\n colorPalette: chartDefaults.colorPalette,\n localPaletteName: chartDefaults.localPaletteName,\n chartAvailability: chartDefaults.chartAvailability,\n combinedMetrics: combinedFields.combinedMetrics,\n combinedBreakdowns: combinedFields.combinedBreakdowns,\n effectiveBreakdowns: combinedFields.effectiveBreakdowns,\n\n // UI state (from uiState)\n activeTab: uiState.activeTab,\n activeView: uiState.activeView,\n displayLimit: uiState.displayLimit,\n showFieldModal: uiState.showFieldModal,\n fieldModalMode: uiState.fieldModalMode,\n activeTableIndex: uiState.activeTableIndex,\n userManuallySelectedChart: uiState.userManuallySelectedChart,\n\n // AI state\n aiState: {\n isOpen: aiState.isOpen,\n userPrompt: aiState.userPrompt,\n isGenerating: aiState.isGenerating,\n error: aiState.error,\n hasGeneratedQuery: aiState.hasGeneratedQuery,\n },\n\n // Share state\n shareButtonState: shareButtonStateRef.current,\n canShare,\n\n // Actions\n actions: {\n // Query state (from queryBuilder)\n setActiveQueryIndex: queryBuilder.setActiveQueryIndex,\n setMergeStrategy: queryBuilder.setMergeStrategy,\n\n // Metrics\n openMetricsModal,\n addMetric,\n removeMetric,\n toggleMetric,\n reorderMetrics,\n\n // Breakdowns\n openBreakdownsModal,\n addBreakdown,\n removeBreakdown,\n toggleBreakdown,\n setBreakdownGranularity,\n toggleBreakdownComparison,\n reorderBreakdowns,\n\n // Filters\n setFilters,\n dropFieldToFilter,\n setOrder,\n\n // Multi-query (from queryBuilder)\n addQuery: queryBuilder.addQuery,\n removeQuery: queryBuilder.removeQuery,\n\n // Funnel\n setFunnelBindingKey,\n\n // Chart (from chartDefaults)\n setChartType: chartDefaults.setChartType,\n setChartConfig: chartDefaults.setChartConfig,\n setDisplayConfig: chartDefaults.setDisplayConfig,\n setLocalPaletteName: chartDefaults.setLocalPaletteName,\n\n // UI (from uiState)\n setActiveTab: uiState.setActiveTab,\n setActiveView: uiState.setActiveView,\n setDisplayLimit: uiState.setDisplayLimit,\n closeFieldModal: uiState.closeFieldModal,\n setActiveTableIndex: uiState.setActiveTableIndex,\n\n // AI\n openAI,\n closeAI,\n setAIPrompt,\n generateAI,\n acceptAI,\n cancelAI,\n\n // Share\n share,\n\n // Utility\n clearQuery,\n refetch: queryExecution.refetch,\n handleFieldSelected,\n },\n\n // Refs\n getQueryConfig,\n getChartConfig,\n }\n}\n","/**\n * Utility functions for AI Assistant\n */\n\nimport type { \n AIQueryRequest,\n AIQueryResponse,\n AIConfig\n} from './types'\nimport { \n AI_STORAGE_KEY,\n DEFAULT_AI_CONFIG\n} from './constants'\n\n/**\n * Send a user prompt to AI proxy (server builds system prompt)\n */\nexport async function sendGeminiMessage(\n apiKey: string,\n userPrompt: string,\n endpoint: string = '/api/ai/generate'\n): Promise<AIQueryResponse> {\n const requestBody: AIQueryRequest = {\n text: userPrompt // Send only the user's prompt, server handles system prompt\n }\n\n // Only add API key header if provided (allow empty string for server key)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json'\n }\n \n if (apiKey && apiKey.trim()) {\n headers['X-API-Key'] = apiKey\n }\n\n console.log('🤖 Client: Sending user prompt to AI proxy')\n console.log(' URL:', endpoint)\n console.log(' Headers:', headers)\n console.log(' User prompt length:', userPrompt.length)\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody)\n })\n\n console.log('📥 Client: Proxy response')\n console.log(' Status:', response.status)\n console.log(' Status Text:', response.statusText)\n\n if (!response.ok) {\n let errorMessage = `Failed to generate content: ${response.status} ${response.statusText}`\n \n try {\n // Try to parse JSON error response first\n const errorData = await response.json()\n console.error('❌ Client: Proxy error:', errorData)\n \n // Handle rate limit errors specially\n if (response.status === 429 && errorData.error === 'Daily quota exceeded') {\n throw new Error(\n `${errorData.message}\\n\\n${errorData.suggestion || 'Add your own Gemini API key for unlimited access.'}`\n )\n }\n \n // Handle other structured errors\n if (errorData.error) {\n errorMessage = errorData.message || errorData.error\n if (errorData.suggestion) {\n errorMessage += `\\n\\n💡 ${errorData.suggestion}`\n }\n }\n } catch {\n // Fallback to text if JSON parsing fails\n try {\n const errorText = await response.text()\n console.error('❌ Client: Proxy text error:', errorText)\n errorMessage = errorText || errorMessage\n } catch {\n console.error('❌ Client: Could not parse error response')\n }\n }\n \n throw new Error(errorMessage)\n }\n\n const data = await response.json()\n console.log('✅ Client: Successfully generated content')\n return data\n}\n\n// Removed: buildSystemPrompt and formatCubeSchemaForPrompt \n// These functions are now handled server-side for better security\n\n/**\n * Save AI configuration to localStorage\n */\nexport function saveAIConfig(config: AIConfig): void {\n try {\n localStorage.setItem(AI_STORAGE_KEY, JSON.stringify(config))\n } catch (error) {\n console.warn('Failed to save AI config to localStorage:', error)\n }\n}\n\n/**\n * Load AI configuration from localStorage\n */\nexport function loadAIConfig(): AIConfig {\n try {\n const saved = localStorage.getItem(AI_STORAGE_KEY)\n if (saved) {\n const parsed = JSON.parse(saved)\n return { ...DEFAULT_AI_CONFIG, ...parsed }\n }\n } catch (error) {\n console.warn('Failed to load AI config from localStorage:', error)\n }\n return { ...DEFAULT_AI_CONFIG }\n}\n\n/**\n * Extract query text from simplified AI response and clean up formatting\n */\nexport function extractTextFromResponse(response: AIQueryResponse): string {\n const rawText = response.query || ''\n\n // Clean up common markdown formatting that might appear\n return rawText\n .replace(/```json\\s*/g, '') // Remove ```json\n .replace(/```\\s*/g, '') // Remove ```\n .replace(/^\\s*```.*\\n/gm, '') // Remove any remaining code block markers\n .trim()\n}","/**\n * Hook for AI query generation in AnalysisBuilder\n *\n * Manages:\n * - AI panel state (open/close, prompt, generating, error)\n * - State snapshots for undo functionality\n * - AI query generation and application\n */\n\nimport { useState, useCallback } from 'react'\nimport type { AnalysisBuilderState, AIState } from '../components/AnalysisBuilder/types'\nimport type { CubeQuery, ChartType, ChartAxisConfig, ChartDisplayConfig } from '../types'\nimport { sendGeminiMessage, extractTextFromResponse } from '../components/AIAssistant/utils'\nimport { generateId, generateMetricLabel } from '../components/AnalysisBuilder/utils'\n\ninterface UseAnalysisAIOptions {\n /** Current state for snapshotting */\n state: AnalysisBuilderState\n /** Set state function for applying AI-generated queries */\n setState: (updater: (prev: AnalysisBuilderState) => AnalysisBuilderState) => void\n /** Current chart type */\n chartType: ChartType\n /** Set chart type */\n setChartType: (type: ChartType) => void\n /** Current chart config */\n chartConfig: ChartAxisConfig\n /** Set chart config */\n setChartConfig: (config: ChartAxisConfig) => void\n /** Current display config */\n displayConfig: ChartDisplayConfig\n /** Set display config */\n setDisplayConfig: (config: ChartDisplayConfig) => void\n /** Set whether user manually selected chart */\n setUserManuallySelectedChart: (value: boolean) => void\n /** Set active view */\n setActiveView: (view: 'table' | 'chart') => void\n /** AI endpoint URL */\n aiEndpoint?: string\n}\n\ninterface UseAnalysisAIResult {\n /** Current AI state */\n aiState: AIState\n /** Open the AI panel */\n handleOpenAI: () => void\n /** Close the AI panel */\n handleCloseAI: () => void\n /** Update the AI prompt */\n handleAIPromptChange: (prompt: string) => void\n /** Generate query from AI */\n handleGenerateAI: () => Promise<void>\n /** Accept the AI-generated query */\n handleAcceptAI: () => void\n /** Cancel and restore previous state */\n handleCancelAI: () => void\n}\n\nexport function useAnalysisAI({\n state,\n setState,\n chartType,\n setChartType,\n chartConfig,\n setChartConfig,\n displayConfig,\n setDisplayConfig,\n setUserManuallySelectedChart,\n setActiveView,\n aiEndpoint = '/api/ai'\n}: UseAnalysisAIOptions): UseAnalysisAIResult {\n // AI state\n const [aiState, setAIState] = useState<AIState>({\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null\n })\n\n /**\n * Open the AI panel and snapshot current state for undo\n */\n const handleOpenAI = useCallback(() => {\n setAIState({\n isOpen: true,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: {\n metrics: [...state.metrics],\n breakdowns: [...state.breakdowns],\n filters: [...state.filters],\n chartType,\n chartConfig: { ...chartConfig },\n displayConfig: { ...displayConfig }\n }\n })\n }, [state.metrics, state.breakdowns, state.filters, chartType, chartConfig, displayConfig])\n\n /**\n * Close the AI panel\n */\n const handleCloseAI = useCallback(() => {\n setAIState(prev => ({\n ...prev,\n isOpen: false,\n userPrompt: '',\n error: null,\n hasGeneratedQuery: false\n }))\n }, [])\n\n /**\n * Update the AI prompt\n */\n const handleAIPromptChange = useCallback((prompt: string) => {\n setAIState(prev => ({ ...prev, userPrompt: prompt }))\n }, [])\n\n /**\n * Generate query from AI and apply to builder\n */\n const handleGenerateAI = useCallback(async () => {\n if (!aiState.userPrompt.trim()) return\n\n setAIState(prev => ({ ...prev, isGenerating: true, error: null }))\n\n try {\n const response = await sendGeminiMessage(\n '', // API key not needed for server-side AI\n aiState.userPrompt,\n aiEndpoint\n )\n\n const responseText = extractTextFromResponse(response)\n const parsed = JSON.parse(responseText) as {\n query?: CubeQuery\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n } | CubeQuery\n\n // Support both new format (with query/chartType/chartConfig) and legacy format (just query)\n const query = ('query' in parsed && parsed.query) ? parsed.query : parsed as CubeQuery\n const aiChartType = ('chartType' in parsed) ? parsed.chartType : undefined\n const aiChartConfig = ('chartConfig' in parsed) ? parsed.chartConfig : undefined\n\n // Load query into builder state\n setState(prev => ({\n ...prev,\n metrics: (query.measures || []).map((field, index) => ({\n id: generateId(),\n field,\n label: generateMetricLabel(index)\n })),\n breakdowns: [\n ...(query.dimensions || []).map((field) => ({\n id: generateId(),\n field,\n isTimeDimension: false\n })),\n ...(query.timeDimensions || []).map((td) => ({\n id: generateId(),\n field: td.dimension,\n granularity: td.granularity,\n isTimeDimension: true\n }))\n ],\n filters: query.filters || []\n }))\n\n // Apply chart type if provided by AI\n if (aiChartType) {\n setChartType(aiChartType)\n setUserManuallySelectedChart(true) // Prevent auto-switching\n }\n\n // Apply chart config if provided by AI\n if (aiChartConfig) {\n setChartConfig(aiChartConfig)\n }\n\n // Switch to chart view so user can see the visualization\n setActiveView('chart')\n\n setAIState(prev => ({\n ...prev,\n isGenerating: false,\n hasGeneratedQuery: true\n }))\n } catch (error) {\n setAIState(prev => ({\n ...prev,\n isGenerating: false,\n error: error instanceof Error ? error.message : 'Failed to generate query'\n }))\n }\n }, [aiState.userPrompt, aiEndpoint, setState, setChartType, setUserManuallySelectedChart, setChartConfig, setActiveView])\n\n /**\n * Accept the AI-generated query (keep changes, close panel)\n */\n const handleAcceptAI = useCallback(() => {\n setAIState({\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null\n })\n }, [])\n\n /**\n * Cancel and restore previous state\n */\n const handleCancelAI = useCallback(() => {\n // Restore previous state\n if (aiState.previousState) {\n setState(prev => ({\n ...prev,\n metrics: aiState.previousState!.metrics,\n breakdowns: aiState.previousState!.breakdowns,\n filters: aiState.previousState!.filters\n }))\n setChartType(aiState.previousState.chartType)\n setChartConfig(aiState.previousState.chartConfig)\n setDisplayConfig(aiState.previousState.displayConfig)\n }\n\n // Close panel\n setAIState({\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null\n })\n }, [aiState.previousState, setState, setChartType, setChartConfig, setDisplayConfig])\n\n return {\n aiState,\n handleOpenAI,\n handleCloseAI,\n handleAIPromptChange,\n handleGenerateAI,\n handleAcceptAI,\n handleCancelAI\n }\n}\n","/**\n * Hook for share URL functionality in AnalysisBuilder\n *\n * Manages:\n * - Share button state (idle, copied, copied-no-chart)\n * - Share URL generation and clipboard copy\n */\n\nimport { useState, useCallback } from 'react'\nimport type { CubeQuery, ChartType, ChartAxisConfig, ChartDisplayConfig, MultiQueryConfig } from '../types'\nimport { compressWithFallback } from '../utils/shareUtils'\n\ninterface UseAnalysisShareOptions {\n /** Whether the current query is valid */\n isValidQuery: boolean\n /** Getter for the query config (matches AnalysisBuilder save format) */\n getQueryConfig: () => CubeQuery | MultiQueryConfig\n /** Current chart type */\n chartType: ChartType\n /** Current chart config */\n chartConfig: ChartAxisConfig\n /** Current display config */\n displayConfig: ChartDisplayConfig\n /** Current active view */\n activeView: 'table' | 'chart'\n}\n\ninterface UseAnalysisShareResult {\n /** Current share button state */\n shareButtonState: 'idle' | 'copied' | 'copied-no-chart'\n /** Handle share button click */\n handleShare: () => Promise<void>\n}\n\nexport function useAnalysisShare({\n isValidQuery,\n getQueryConfig,\n chartType,\n chartConfig,\n displayConfig,\n activeView\n}: UseAnalysisShareOptions): UseAnalysisShareResult {\n const [shareButtonState, setShareButtonState] = useState<'idle' | 'copied' | 'copied-no-chart'>('idle')\n\n /**\n * Generate share URL and copy to clipboard\n */\n const handleShare = useCallback(async () => {\n if (!isValidQuery) return\n\n const queryConfig = getQueryConfig()\n\n const shareableState = {\n query: queryConfig,\n chartType,\n chartConfig,\n displayConfig,\n activeView\n }\n\n // Try full state first, fall back to query-only if too large\n const { encoded, queryOnly } = compressWithFallback(shareableState)\n\n // If even query-only is too large, don't share\n if (!encoded) {\n return\n }\n\n const url = `${window.location.origin}${window.location.pathname}#share=${encoded}`\n\n try {\n await navigator.clipboard.writeText(url)\n } catch {\n // Fallback for older browsers\n const textArea = document.createElement('textarea')\n textArea.value = url\n document.body.appendChild(textArea)\n textArea.select()\n document.execCommand('copy')\n document.body.removeChild(textArea)\n }\n\n // Update button state\n setShareButtonState(queryOnly ? 'copied-no-chart' : 'copied')\n\n // Reset button state after 2 seconds\n setTimeout(() => {\n setShareButtonState('idle')\n }, 2000)\n }, [isValidQuery, getQueryConfig, chartType, chartConfig, displayConfig, activeView])\n\n return {\n shareButtonState,\n handleShare\n }\n}\n","/**\n * FieldSearchItem Component\n *\n * A single field item in the search results list.\n * Shows field icon, title, type badge, and selection state.\n */\n\nimport { memo } from 'react'\nimport { getIcon, getMeasureTypeIcon, getFieldTypeIcon } from '../../icons'\nimport type { FieldSearchItemProps } from './types'\n\nconst CheckIcon = getIcon('check')\n\nfunction FieldSearchItem({\n field,\n isSelected,\n isFocused,\n onClick,\n onMouseEnter,\n ...props\n}: FieldSearchItemProps & { 'data-field-index'?: number }) {\n // Get appropriate icon based on field type\n const getFieldIcon = () => {\n if (field.fieldType === 'measure') {\n const Icon = getMeasureTypeIcon(field.type)\n return Icon ? <Icon className=\"w-4 h-4\" /> : null\n } else if (field.fieldType === 'timeDimension') {\n const Icon = getFieldTypeIcon('time')\n return Icon ? <Icon className=\"w-4 h-4\" /> : null\n } else {\n const Icon = getFieldTypeIcon('dimension')\n return Icon ? <Icon className=\"w-4 h-4\" /> : null\n }\n }\n\n // Get badge color based on field type\n const getBadgeStyle = () => {\n if (field.fieldType === 'measure') {\n return 'bg-dc-measure text-dc-measure-text'\n } else if (field.fieldType === 'timeDimension') {\n return 'bg-dc-time-dimension text-dc-time-dimension-text'\n } else {\n return 'bg-dc-dimension text-dc-dimension-text'\n }\n }\n\n // Get short type label\n const getTypeLabel = () => {\n if (field.fieldType === 'measure') {\n return field.type.charAt(0).toUpperCase() + field.type.slice(1)\n } else if (field.fieldType === 'timeDimension') {\n return 'Time'\n } else {\n return 'Dim'\n }\n }\n\n return (\n <button\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n className={`w-full text-left px-3 py-2 rounded-lg flex items-center gap-3 transition-colors group ${\n isFocused\n ? 'bg-dc-primary/10 ring-1 ring-dc-primary'\n : isSelected\n ? 'bg-dc-success/10'\n : 'hover:bg-dc-surface-hover'\n }`}\n {...props}\n >\n {/* Icon */}\n <span\n className={`shrink-0 w-8 h-8 flex items-center justify-center rounded-md ${\n field.fieldType === 'measure'\n ? 'bg-dc-measure text-dc-measure-text'\n : field.fieldType === 'timeDimension'\n ? 'bg-dc-time-dimension text-dc-time-dimension-text'\n : 'bg-dc-dimension text-dc-dimension-text'\n }`}\n >\n {getFieldIcon()}\n </span>\n\n {/* Title and name */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium text-dc-text truncate\">\n {field.title}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">{field.name}</div>\n </div>\n\n {/* Type badge */}\n <span\n className={`shrink-0 px-2 py-0.5 rounded text-xs font-medium ${getBadgeStyle()}`}\n >\n {getTypeLabel()}\n </span>\n\n {/* Selection indicator */}\n {isSelected && (\n <span className=\"shrink-0 w-5 h-5 flex items-center justify-center rounded-full bg-dc-success text-white\">\n <CheckIcon className=\"w-3 h-3\" />\n </span>\n )}\n </button>\n )\n}\n\nexport default memo(FieldSearchItem)\n","/**\n * FieldDetailPanel Component\n *\n * Shows detailed information about the currently focused/hovered field.\n * Displays: icon, title, description, type, cube name, and technical name.\n */\n\nimport { memo } from 'react'\nimport { getMeasureTypeIcon, getFieldTypeIcon } from '../../icons'\nimport type { FieldDetailPanelProps } from './types'\n\nfunction FieldDetailPanel({ field }: FieldDetailPanelProps) {\n if (!field) {\n return (\n <div className=\"p-6 text-center text-dc-text-muted\">\n <p className=\"text-sm\">Hover over a field to see details</p>\n </div>\n )\n }\n\n // Get appropriate icon based on field type\n const getFieldIcon = () => {\n if (field.fieldType === 'measure') {\n const Icon = getMeasureTypeIcon(field.type)\n return Icon ? <Icon className=\"w-6 h-6\" /> : null\n } else if (field.fieldType === 'timeDimension') {\n const Icon = getFieldTypeIcon('time')\n return Icon ? <Icon className=\"w-6 h-6\" /> : null\n } else {\n const Icon = getFieldTypeIcon('dimension')\n return Icon ? <Icon className=\"w-6 h-6\" /> : null\n }\n }\n\n // Get icon background color - use field type specific colors for consistency\n const getIconBgStyle = () => {\n if (field.fieldType === 'measure') {\n return 'bg-dc-measure text-dc-measure-text'\n } else if (field.fieldType === 'timeDimension') {\n return 'bg-dc-time-dimension text-dc-time-dimension-text'\n } else {\n return 'bg-dc-dimension text-dc-dimension-text'\n }\n }\n\n // Get type display name\n const getTypeDisplay = () => {\n if (field.fieldType === 'measure') {\n const typeMap: Record<string, string> = {\n count: 'Count',\n countDistinct: 'Count Distinct',\n countDistinctApprox: 'Count Distinct (Approx)',\n sum: 'Sum',\n avg: 'Average',\n min: 'Minimum',\n max: 'Maximum',\n runningTotal: 'Running Total',\n number: 'Number'\n }\n return typeMap[field.type] || field.type\n } else if (field.fieldType === 'timeDimension') {\n return 'Time Dimension'\n } else {\n const typeMap: Record<string, string> = {\n string: 'Text',\n number: 'Number',\n boolean: 'Boolean',\n geo: 'Geographic'\n }\n return typeMap[field.type] || 'Dimension'\n }\n }\n\n return (\n <div className=\"p-4\">\n {/* Header with icon and title */}\n <div className=\"flex items-start gap-3 mb-4\">\n <span\n className={`shrink-0 w-12 h-12 flex items-center justify-center rounded-lg ${getIconBgStyle()}`}\n >\n {getFieldIcon()}\n </span>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-base font-semibold text-dc-text leading-tight\">\n {field.title}\n </h3>\n <p className=\"text-xs text-dc-text-muted mt-0.5 truncate\">\n {field.name}\n </p>\n </div>\n </div>\n\n {/* Description */}\n {field.description && (\n <div className=\"mb-4\">\n <p className=\"text-sm text-dc-text-secondary leading-relaxed\">\n {field.description}\n </p>\n </div>\n )}\n\n {/* Metadata */}\n <div className=\"space-y-3 pt-4 border-t border-dc-border\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-dc-text-muted\">Type</span>\n <span className=\"text-sm text-dc-text font-medium\">{getTypeDisplay()}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-dc-text-muted\">Cube</span>\n <span className=\"text-sm text-dc-text font-medium\">{field.cubeName}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-dc-text-muted\">Category</span>\n <span\n className={`text-xs px-2 py-0.5 rounded font-medium ${\n field.fieldType === 'measure'\n ? 'bg-dc-measure text-dc-measure-text'\n : field.fieldType === 'timeDimension'\n ? 'bg-dc-time-dimension text-dc-time-dimension-text'\n : 'bg-dc-dimension text-dc-dimension-text'\n }`}\n >\n {field.fieldType === 'measure'\n ? 'Measure'\n : field.fieldType === 'timeDimension'\n ? 'Time Dimension'\n : 'Dimension'}\n </span>\n </div>\n </div>\n\n {/* Usage hint */}\n <div className=\"mt-6 p-3 bg-dc-surface rounded-lg\">\n <p className=\"text-xs text-dc-text-muted\">\n Press <kbd className=\"px-1 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Enter</kbd> or click to add this field to your query.\n </p>\n </div>\n </div>\n )\n}\n\nexport default memo(FieldDetailPanel)\n","/**\n * FieldSearchModal Component\n *\n * A full-screen search modal for selecting cube fields (measures/dimensions).\n * Features:\n * - Real-time search filtering\n * - Cube-based category filtering\n * - Three-column layout: Categories | Results | Details\n * - Keyboard navigation support\n * - Recent fields tracking\n */\n\nimport { useState, useMemo, useCallback, useEffect, useRef, KeyboardEvent } from 'react'\nimport { getIcon } from '../../icons'\nimport type { FieldSearchModalProps, FieldOption } from './types'\nimport type { MetaField } from '../../shared/types'\nimport {\n schemaToFieldOptions,\n filterFieldOptions,\n groupFieldsByCube,\n getCubeNames,\n getCubeTitle,\n getRecentFields,\n addRecentField,\n getRecentFieldOptions\n} from './utils'\nimport FieldSearchItem from './FieldSearchItem'\nimport FieldDetailPanel from './FieldDetailPanel'\n\nconst SearchIcon = getIcon('search')\nconst CloseIcon = getIcon('close')\n\nexport default function FieldSearchModal({\n isOpen,\n onClose,\n onSelect,\n mode,\n schema,\n selectedFields,\n recentFields: externalRecentFields\n}: FieldSearchModalProps) {\n // State\n const [searchTerm, setSearchTerm] = useState('')\n const [selectedCube, setSelectedCube] = useState<string | null>(null)\n const [focusedField, setFocusedField] = useState<FieldOption | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const [lastSelectedIndex, setLastSelectedIndex] = useState<number | null>(null)\n\n // Refs\n const searchInputRef = useRef<HTMLInputElement>(null)\n const resultsContainerRef = useRef<HTMLDivElement>(null)\n\n // Get recent fields from localStorage or props\n const recentFieldNames = useMemo(() => {\n if (externalRecentFields) return externalRecentFields\n const stored = getRecentFields()\n return mode === 'metrics' ? stored.metrics : stored.breakdowns\n }, [externalRecentFields, mode])\n\n // Map mode to field options mode\n const fieldOptionsMode = mode\n\n // Get all field options for current mode\n const allFieldOptions = useMemo(() => {\n return schemaToFieldOptions(schema, fieldOptionsMode)\n }, [schema, fieldOptionsMode])\n\n // Get cube names for category filter\n const cubeNames = useMemo(() => {\n return getCubeNames(schema)\n }, [schema])\n\n // Filter fields by search and cube\n const filteredFields = useMemo(() => {\n return filterFieldOptions(allFieldOptions, searchTerm, selectedCube)\n }, [allFieldOptions, searchTerm, selectedCube])\n\n // Group filtered fields by cube\n const groupedFields = useMemo(() => {\n return groupFieldsByCube(filteredFields)\n }, [filteredFields])\n\n // Get recent field options (only when not searching)\n const recentOptions = useMemo(() => {\n if (searchTerm.trim()) return []\n return getRecentFieldOptions(schema, fieldOptionsMode, recentFieldNames).filter(\n (f) => !selectedCube || f.cubeName === selectedCube\n )\n }, [schema, fieldOptionsMode, recentFieldNames, searchTerm, selectedCube])\n\n // Flat list of visible fields for keyboard navigation\n const flatFieldsList = useMemo(() => {\n const list: FieldOption[] = [...recentOptions]\n groupedFields.forEach((fields) => {\n list.push(...fields)\n })\n return list\n }, [recentOptions, groupedFields])\n\n // Focus search input when modal opens\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!isOpen) {\n setSearchTerm('')\n setSelectedCube(null)\n setFocusedField(null)\n setFocusedIndex(-1)\n setLastSelectedIndex(null)\n }\n }, [isOpen])\n\n // Handle single field selection\n const selectSingleField = useCallback(\n (field: FieldOption, keepOpen: boolean = false) => {\n // Add to recent fields\n addRecentField(field.name, mode === 'metrics' ? 'metrics' : 'breakdowns')\n\n // Create MetaField object for callback\n const metaField: MetaField = {\n name: field.name,\n title: field.title,\n shortTitle: field.shortTitle,\n type: field.type,\n description: field.description\n }\n\n onSelect(metaField, field.fieldType, field.cubeName, keepOpen)\n },\n [mode, onSelect]\n )\n\n // Handle field selection with shift-click support for range selection\n const handleSelectField = useCallback(\n (field: FieldOption, fieldIndex: number, shiftKey: boolean = false) => {\n // Shift-click for range selection - keep modal open\n if (shiftKey && lastSelectedIndex !== null && lastSelectedIndex !== fieldIndex) {\n const startIndex = Math.min(lastSelectedIndex, fieldIndex)\n const endIndex = Math.max(lastSelectedIndex, fieldIndex)\n\n // Select all fields in the range, keep modal open for all\n for (let i = startIndex; i <= endIndex; i++) {\n const rangeField = flatFieldsList[i]\n if (rangeField && !selectedFields.includes(rangeField.name)) {\n selectSingleField(rangeField, true) // Keep modal open\n }\n }\n } else if (shiftKey) {\n // Shift-click on single item - select but keep modal open\n selectSingleField(field, true)\n } else {\n // Normal single selection - close modal after\n selectSingleField(field, false)\n }\n\n // Update last selected index for next shift-click\n setLastSelectedIndex(fieldIndex)\n },\n [flatFieldsList, lastSelectedIndex, selectSingleField, selectedFields]\n )\n\n // Keyboard navigation\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (flatFieldsList.length === 0) return\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setFocusedIndex((prev) => {\n const next = Math.min(prev + 1, flatFieldsList.length - 1)\n setFocusedField(flatFieldsList[next])\n return next\n })\n break\n\n case 'ArrowUp':\n e.preventDefault()\n setFocusedIndex((prev) => {\n const next = Math.max(prev - 1, 0)\n setFocusedField(flatFieldsList[next])\n return next\n })\n break\n\n case 'Enter':\n e.preventDefault()\n if (focusedIndex >= 0 && flatFieldsList[focusedIndex]) {\n handleSelectField(flatFieldsList[focusedIndex], focusedIndex, e.shiftKey)\n }\n break\n\n case 'Escape':\n e.preventDefault()\n onClose()\n break\n }\n },\n [flatFieldsList, focusedIndex, handleSelectField, onClose]\n )\n\n // Scroll focused item into view\n useEffect(() => {\n if (focusedIndex >= 0 && resultsContainerRef.current) {\n const focusedElement = resultsContainerRef.current.querySelector(\n `[data-field-index=\"${focusedIndex}\"]`\n )\n if (focusedElement) {\n focusedElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' })\n }\n }\n }, [focusedIndex])\n\n if (!isOpen) return null\n\n const searchPlaceholder =\n mode === 'metrics' ? 'Search metrics...' : mode === 'filter' ? 'Search fields to filter...' : 'Search dimensions...'\n\n const modalTitle = mode === 'metrics' ? 'Select a Metric' : mode === 'filter' ? 'Select a Field to Filter' : 'Select a Dimension'\n const focusedFieldId = focusedIndex >= 0 && flatFieldsList[focusedIndex]\n ? `field-option-${flatFieldsList[focusedIndex].name.replace(/\\./g, '-')}`\n : undefined\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{ backgroundColor: 'var(--dc-overlay)' }}\n onClick={onClose}\n role=\"presentation\"\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={modalTitle}\n className=\"bg-dc-surface shadow-xl w-full h-full md:rounded-lg md:w-[900px] md:max-w-[900px] md:h-[80vh] md:max-h-[700px] flex flex-col overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={handleKeyDown}\n >\n {/* Header with Search */}\n <div className=\"shrink-0 border-b border-dc-border\">\n <div className=\"flex items-center px-4 py-3 gap-3\">\n <SearchIcon className=\"w-5 h-5 text-dc-text-muted\" aria-hidden={true} />\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchTerm}\n onChange={(e) => {\n setSearchTerm(e.target.value)\n setFocusedIndex(-1)\n }}\n placeholder={searchPlaceholder}\n className=\"flex-1 bg-transparent border-none outline-none text-dc-text placeholder-dc-text-muted text-lg\"\n aria-label={searchPlaceholder}\n aria-controls=\"field-search-results\"\n aria-activedescendant={focusedFieldId}\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-autocomplete=\"list\"\n />\n <button\n onClick={onClose}\n className=\"p-1 text-dc-text-secondary hover:text-dc-text rounded\"\n aria-label=\"Close dialog\"\n >\n <CloseIcon className=\"w-5 h-5\" aria-hidden={true} />\n </button>\n </div>\n {/* Mobile cube filter - shown only on mobile */}\n {cubeNames.length > 1 && (\n <div className=\"md:hidden px-4 pb-3\">\n <select\n value={selectedCube || ''}\n onChange={(e) => setSelectedCube(e.target.value || null)}\n className=\"w-full px-3 py-2 bg-dc-surface border border-dc-border rounded-lg text-sm text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n aria-label=\"Filter by cube\"\n >\n <option value=\"\">All Cubes</option>\n {cubeNames.map((cubeName) => (\n <option key={cubeName} value={cubeName}>\n {getCubeTitle(cubeName, schema)}\n </option>\n ))}\n </select>\n </div>\n )}\n </div>\n\n {/* Three Column Layout - Single column on mobile */}\n <div className=\"flex-1 flex overflow-hidden\">\n {/* Left Column - Categories (hidden on mobile) */}\n <nav\n className=\"hidden md:block w-48 shrink-0 border-r border-dc-border overflow-y-auto bg-dc-surface-secondary\"\n aria-label=\"Filter by cube\"\n >\n <div className=\"p-2\" role=\"group\" aria-label=\"Cube categories\">\n <button\n onClick={() => setSelectedCube(null)}\n className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${\n selectedCube === null\n ? 'bg-dc-primary/10 text-dc-primary font-medium'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }`}\n aria-pressed={selectedCube === null}\n >\n All\n </button>\n {cubeNames.map((cubeName) => (\n <button\n key={cubeName}\n onClick={() => setSelectedCube(cubeName)}\n className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors truncate ${\n selectedCube === cubeName\n ? 'bg-dc-primary/10 text-dc-primary font-medium'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }`}\n title={getCubeTitle(cubeName, schema)}\n aria-pressed={selectedCube === cubeName}\n >\n {getCubeTitle(cubeName, schema)}\n </button>\n ))}\n </div>\n </nav>\n\n {/* Middle Column - Results */}\n <div\n id=\"field-search-results\"\n ref={resultsContainerRef}\n className=\"flex-1 overflow-y-auto p-4\"\n role=\"listbox\"\n aria-label=\"Available fields\"\n >\n {filteredFields.length === 0 && recentOptions.length === 0 ? (\n <div className=\"text-center py-12 text-dc-text-muted\">\n <p className=\"text-lg mb-2\">No fields found</p>\n <p className=\"text-sm\">\n {searchTerm\n ? `No ${mode === 'metrics' ? 'metrics' : 'dimensions'} match \"${searchTerm}\"`\n : `No ${mode === 'metrics' ? 'metrics' : 'dimensions'} available`}\n </p>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {/* Recent Fields */}\n {recentOptions.length > 0 && (\n <div>\n <h3 className=\"text-xs font-semibold text-dc-text-muted uppercase tracking-wider mb-2\">\n Recents\n </h3>\n <div className=\"space-y-1\">\n {recentOptions.map((field, idx) => (\n <FieldSearchItem\n key={`recent-${field.name}`}\n field={field}\n isSelected={selectedFields.includes(field.name)}\n isFocused={focusedIndex === idx}\n onClick={(e) => handleSelectField(field, idx, e.shiftKey)}\n onMouseEnter={() => {\n setFocusedField(field)\n setFocusedIndex(idx)\n }}\n data-field-index={idx}\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Grouped by Cube */}\n {Array.from(groupedFields.entries()).map(([cubeName, fields]) => (\n <div key={cubeName}>\n <h3 className=\"text-xs font-semibold text-dc-text-muted uppercase tracking-wider mb-2\">\n {getCubeTitle(cubeName, schema)}\n </h3>\n <div className=\"space-y-1\">\n {fields.map((field) => {\n const fieldIndex =\n recentOptions.length +\n Array.from(groupedFields.entries())\n .slice(\n 0,\n Array.from(groupedFields.keys()).indexOf(cubeName)\n )\n .reduce((sum, [, f]) => sum + f.length, 0) +\n fields.indexOf(field)\n\n return (\n <FieldSearchItem\n key={field.name}\n field={field}\n isSelected={selectedFields.includes(field.name)}\n isFocused={focusedIndex === fieldIndex}\n onClick={(e) => handleSelectField(field, fieldIndex, e.shiftKey)}\n onMouseEnter={() => {\n setFocusedField(field)\n setFocusedIndex(fieldIndex)\n }}\n data-field-index={fieldIndex}\n />\n )\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Right Column - Field Details (hidden on mobile) */}\n <div className=\"hidden md:block w-72 shrink-0 border-l border-dc-border bg-dc-surface-secondary overflow-y-auto\">\n <FieldDetailPanel field={focusedField} />\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"shrink-0 border-t border-dc-border px-4 py-3 flex items-center justify-between text-sm text-dc-text-muted\">\n <div>\n <span className=\"text-dc-text-secondary\">{filteredFields.length}</span>{' '}\n {mode === 'metrics' ? 'metrics' : mode === 'filter' ? 'fields' : 'dimensions'} available\n </div>\n {/* Keyboard shortcuts - hidden on mobile */}\n <div className=\"hidden md:flex items-center gap-4\">\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">↑↓</kbd> Navigate\n </span>\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Enter</kbd> Select\n </span>\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Shift</kbd>+Click Multi-select\n </span>\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Esc</kbd> Close\n </span>\n </div>\n </div>\n </div>\n </div>\n )\n}\n","/**\n * QueryAnalysisPanel Component\n * Displays query planning analysis for debugging and transparency\n */\n\nimport React from 'react'\nimport { getIcon } from '../../icons'\nimport type { QueryAnalysis } from '../types'\n\ninterface QueryAnalysisPanelProps {\n analysis: QueryAnalysis\n}\n\n/**\n * Format reason string for display\n */\nfunction formatReason(reason: string): string {\n return reason.replace(/_/g, ' ')\n}\n\n/**\n * Get badge color based on reason\n */\nfunction getReasonBadgeClasses(reason: string): string {\n switch (reason) {\n case 'most_dimensions':\n return 'bg-dc-info-bg text-dc-info'\n case 'most_connected':\n return 'bg-dc-accent-bg text-dc-accent'\n case 'alphabetical_fallback':\n return 'bg-dc-warning-bg text-dc-warning'\n case 'single_cube':\n return 'bg-dc-success-bg text-dc-success'\n default:\n return 'bg-dc-muted-bg text-dc-muted'\n }\n}\n\nconst QueryAnalysisPanel: React.FC<QueryAnalysisPanelProps> = ({ analysis }) => {\n const InfoIcon = getIcon('info')\n const ArrowRightIcon = getIcon('chevronRight')\n const WarningIcon = getIcon('warning')\n const TableIcon = getIcon('table')\n const LinkIcon = getIcon('link')\n const SuccessIcon = getIcon('success')\n const ErrorIcon = getIcon('error')\n\n return (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded-lg p-4 space-y-4\">\n {/* Query Summary Section */}\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <InfoIcon className=\"w-4 h-4 mr-2\" />\n Query Summary\n </h4>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2 text-xs\">\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Type:</span>\n <span className=\"ml-1 font-medium text-dc-text\">\n {formatReason(analysis.querySummary.queryType)}\n </span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Cubes:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.cubeCount}</span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Joins:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.querySummary.joinCount}</span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">CTEs:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.querySummary.cteCount}</span>\n </div>\n </div>\n </div>\n\n {/* Primary Cube Section */}\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <TableIcon className=\"w-4 h-4 mr-2\" />\n Primary Cube (FROM table)\n </h4>\n <div className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-2 flex-wrap\">\n <span className=\"font-mono font-medium text-dc-primary\">\n {analysis.primaryCube.selectedCube}\n </span>\n <span className={`text-xs px-2 py-0.5 rounded ${getReasonBadgeClasses(analysis.primaryCube.reason)}`}>\n {formatReason(analysis.primaryCube.reason)}\n </span>\n </div>\n <p className=\"text-dc-text-secondary text-xs\">\n {analysis.primaryCube.explanation}\n </p>\n {analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1 && (\n <details className=\"mt-2\">\n <summary className=\"text-xs text-dc-text-muted cursor-pointer hover:text-dc-text\">\n Show candidates ({analysis.primaryCube.candidates.length})\n </summary>\n <div className=\"mt-2 space-y-1 ml-2\">\n {analysis.primaryCube.candidates.map((c, i) => (\n <div key={i} className=\"text-xs flex items-center gap-2 flex-wrap\">\n <span className={`font-mono ${c.cubeName === analysis.primaryCube.selectedCube ? 'font-bold text-dc-primary' : 'text-dc-text-muted'}`}>\n {c.cubeName}\n </span>\n <span className=\"text-dc-text-muted\">\n dims: {c.dimensionCount}, joins: {c.joinCount}\n </span>\n {c.canReachAll ? (\n <span className=\"text-dc-success flex items-center gap-0.5\">\n <SuccessIcon className=\"w-3 h-3\" />\n reachable\n </span>\n ) : (\n <span className=\"text-dc-error flex items-center gap-0.5\">\n <ErrorIcon className=\"w-3 h-3\" />\n cannot reach all\n </span>\n )}\n </div>\n ))}\n </div>\n </details>\n )}\n </div>\n </div>\n\n {/* Join Paths Section */}\n {analysis.joinPaths.length > 0 && (\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <LinkIcon className=\"w-4 h-4 mr-2\" />\n Join Paths\n </h4>\n <div className=\"space-y-2\">\n {analysis.joinPaths.map((jp, idx) => (\n <div key={idx} className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-2 flex-wrap\">\n <span className=\"font-mono text-dc-text-secondary\">{analysis.primaryCube.selectedCube}</span>\n <ArrowRightIcon className=\"w-4 h-4 text-dc-text-muted\" />\n <span className=\"font-mono font-medium text-dc-text\">{jp.targetCube}</span>\n {jp.pathFound ? (\n <span className=\"text-xs px-2 py-0.5 bg-dc-success-bg text-dc-success rounded\">\n {jp.pathLength} step{jp.pathLength !== 1 ? 's' : ''}\n </span>\n ) : (\n <span className=\"text-xs px-2 py-0.5 bg-dc-error-bg text-dc-error rounded\">\n No path\n </span>\n )}\n </div>\n {jp.pathFound && jp.path && jp.path.length > 0 && (\n <div className=\"space-y-1 ml-2\">\n {jp.path.map((step, stepIdx) => (\n <div key={stepIdx} className=\"flex items-center gap-1 text-xs flex-wrap\">\n <span className=\"font-mono text-dc-text-secondary\">{step.fromCube}</span>\n <ArrowRightIcon className=\"w-3 h-3 text-dc-text-muted\" />\n <span className=\"font-mono text-dc-text\">{step.toCube}</span>\n <span className=\"text-dc-text-muted\">\n ({step.relationship}, {step.joinType} join)\n </span>\n {step.joinColumns.length > 0 && (\n <span className=\"text-dc-text-muted\">\n on {step.joinColumns.map(jc => `${jc.sourceColumn}=${jc.targetColumn}`).join(', ')}\n </span>\n )}\n </div>\n ))}\n </div>\n )}\n {!jp.pathFound && jp.error && (\n <p className=\"text-xs text-dc-error mt-1\">{jp.error}</p>\n )}\n {jp.visitedCubes && jp.visitedCubes.length > 0 && !jp.pathFound && (\n <details className=\"mt-1\">\n <summary className=\"text-xs text-dc-text-muted cursor-pointer hover:text-dc-text\">\n Cubes visited during search ({jp.visitedCubes.length})\n </summary>\n <div className=\"mt-1 text-xs text-dc-text-muted ml-2\">\n {jp.visitedCubes.join(' → ')}\n </div>\n </details>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Pre-Aggregations Section */}\n {analysis.preAggregations.length > 0 && (\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <TableIcon className=\"w-4 h-4 mr-2\" />\n Pre-Aggregation CTEs\n </h4>\n <div className=\"space-y-2\">\n {analysis.preAggregations.map((pa, idx) => (\n <div key={idx} className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-1 flex-wrap\">\n <span className=\"font-mono font-medium text-dc-text\">{pa.cubeName}</span>\n <span className=\"text-xs text-dc-text-muted\">as</span>\n <code className=\"text-xs bg-dc-surface-secondary px-1 rounded font-mono\">{pa.cteAlias}</code>\n </div>\n <p className=\"text-xs text-dc-text-secondary\">{pa.reason}</p>\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"font-medium\">Measures:</span> {pa.measures.join(', ')}\n </div>\n {pa.joinKeys.length > 0 && (\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"font-medium\">Join keys:</span> {pa.joinKeys.map(jk => `${jk.sourceColumn}=${jk.targetColumn}`).join(', ')}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Warnings Section */}\n {analysis.warnings && analysis.warnings.length > 0 && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-warning mb-2 flex items-center\">\n <WarningIcon className=\"w-4 h-4 mr-2\" />\n Warnings\n </h4>\n <ul className=\"list-disc list-inside text-xs text-dc-warning space-y-1\">\n {analysis.warnings.map((w, i) => (\n <li key={i}>{w}</li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Cubes Involved */}\n {analysis.cubesInvolved.length > 0 && (\n <div className=\"text-xs text-dc-text-muted pt-2 border-t border-dc-border\">\n <span className=\"font-medium\">Cubes involved:</span> {analysis.cubesInvolved.join(', ')}\n </div>\n )}\n </div>\n )\n}\n\nexport default QueryAnalysisPanel\n","/* eslint-disable no-multi-assign */\n\nfunction deepFreeze(obj) {\n if (obj instanceof Map) {\n obj.clear =\n obj.delete =\n obj.set =\n function () {\n throw new Error('map is read-only');\n };\n } else if (obj instanceof Set) {\n obj.add =\n obj.clear =\n obj.delete =\n function () {\n throw new Error('set is read-only');\n };\n }\n\n // Freeze self\n Object.freeze(obj);\n\n Object.getOwnPropertyNames(obj).forEach((name) => {\n const prop = obj[name];\n const type = typeof prop;\n\n // Freeze prop if it is an object or function and also not already frozen\n if ((type === 'object' || type === 'function') && !Object.isFrozen(prop)) {\n deepFreeze(prop);\n }\n });\n\n return obj;\n}\n\n/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */\n/** @typedef {import('highlight.js').CompiledMode} CompiledMode */\n/** @implements CallbackResponse */\n\nclass Response {\n /**\n * @param {CompiledMode} mode\n */\n constructor(mode) {\n // eslint-disable-next-line no-undefined\n if (mode.data === undefined) mode.data = {};\n\n this.data = mode.data;\n this.isMatchIgnored = false;\n }\n\n ignoreMatch() {\n this.isMatchIgnored = true;\n }\n}\n\n/**\n * @param {string} value\n * @returns {string}\n */\nfunction escapeHTML(value) {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * performs a shallow merge of multiple objects into one\n *\n * @template T\n * @param {T} original\n * @param {Record<string,any>[]} objects\n * @returns {T} a single new object\n */\nfunction inherit$1(original, ...objects) {\n /** @type Record<string,any> */\n const result = Object.create(null);\n\n for (const key in original) {\n result[key] = original[key];\n }\n objects.forEach(function(obj) {\n for (const key in obj) {\n result[key] = obj[key];\n }\n });\n return /** @type {T} */ (result);\n}\n\n/**\n * @typedef {object} Renderer\n * @property {(text: string) => void} addText\n * @property {(node: Node) => void} openNode\n * @property {(node: Node) => void} closeNode\n * @property {() => string} value\n */\n\n/** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */\n/** @typedef {{walk: (r: Renderer) => void}} Tree */\n/** */\n\nconst SPAN_CLOSE = '</span>';\n\n/**\n * Determines if a node needs to be wrapped in <span>\n *\n * @param {Node} node */\nconst emitsWrappingTags = (node) => {\n // rarely we can have a sublanguage where language is undefined\n // TODO: track down why\n return !!node.scope;\n};\n\n/**\n *\n * @param {string} name\n * @param {{prefix:string}} options\n */\nconst scopeToCSSClass = (name, { prefix }) => {\n // sub-language\n if (name.startsWith(\"language:\")) {\n return name.replace(\"language:\", \"language-\");\n }\n // tiered scope: comment.line\n if (name.includes(\".\")) {\n const pieces = name.split(\".\");\n return [\n `${prefix}${pieces.shift()}`,\n ...(pieces.map((x, i) => `${x}${\"_\".repeat(i + 1)}`))\n ].join(\" \");\n }\n // simple scope\n return `${prefix}${name}`;\n};\n\n/** @type {Renderer} */\nclass HTMLRenderer {\n /**\n * Creates a new HTMLRenderer\n *\n * @param {Tree} parseTree - the parse tree (must support `walk` API)\n * @param {{classPrefix: string}} options\n */\n constructor(parseTree, options) {\n this.buffer = \"\";\n this.classPrefix = options.classPrefix;\n parseTree.walk(this);\n }\n\n /**\n * Adds texts to the output stream\n *\n * @param {string} text */\n addText(text) {\n this.buffer += escapeHTML(text);\n }\n\n /**\n * Adds a node open to the output stream (if needed)\n *\n * @param {Node} node */\n openNode(node) {\n if (!emitsWrappingTags(node)) return;\n\n const className = scopeToCSSClass(node.scope,\n { prefix: this.classPrefix });\n this.span(className);\n }\n\n /**\n * Adds a node close to the output stream (if needed)\n *\n * @param {Node} node */\n closeNode(node) {\n if (!emitsWrappingTags(node)) return;\n\n this.buffer += SPAN_CLOSE;\n }\n\n /**\n * returns the accumulated buffer\n */\n value() {\n return this.buffer;\n }\n\n // helpers\n\n /**\n * Builds a span element\n *\n * @param {string} className */\n span(className) {\n this.buffer += `<span class=\"${className}\">`;\n }\n}\n\n/** @typedef {{scope?: string, language?: string, children: Node[]} | string} Node */\n/** @typedef {{scope?: string, language?: string, children: Node[]} } DataNode */\n/** @typedef {import('highlight.js').Emitter} Emitter */\n/** */\n\n/** @returns {DataNode} */\nconst newNode = (opts = {}) => {\n /** @type DataNode */\n const result = { children: [] };\n Object.assign(result, opts);\n return result;\n};\n\nclass TokenTree {\n constructor() {\n /** @type DataNode */\n this.rootNode = newNode();\n this.stack = [this.rootNode];\n }\n\n get top() {\n return this.stack[this.stack.length - 1];\n }\n\n get root() { return this.rootNode; }\n\n /** @param {Node} node */\n add(node) {\n this.top.children.push(node);\n }\n\n /** @param {string} scope */\n openNode(scope) {\n /** @type Node */\n const node = newNode({ scope });\n this.add(node);\n this.stack.push(node);\n }\n\n closeNode() {\n if (this.stack.length > 1) {\n return this.stack.pop();\n }\n // eslint-disable-next-line no-undefined\n return undefined;\n }\n\n closeAllNodes() {\n while (this.closeNode());\n }\n\n toJSON() {\n return JSON.stringify(this.rootNode, null, 4);\n }\n\n /**\n * @typedef { import(\"./html_renderer\").Renderer } Renderer\n * @param {Renderer} builder\n */\n walk(builder) {\n // this does not\n return this.constructor._walk(builder, this.rootNode);\n // this works\n // return TokenTree._walk(builder, this.rootNode);\n }\n\n /**\n * @param {Renderer} builder\n * @param {Node} node\n */\n static _walk(builder, node) {\n if (typeof node === \"string\") {\n builder.addText(node);\n } else if (node.children) {\n builder.openNode(node);\n node.children.forEach((child) => this._walk(builder, child));\n builder.closeNode(node);\n }\n return builder;\n }\n\n /**\n * @param {Node} node\n */\n static _collapse(node) {\n if (typeof node === \"string\") return;\n if (!node.children) return;\n\n if (node.children.every(el => typeof el === \"string\")) {\n // node.text = node.children.join(\"\");\n // delete node.children;\n node.children = [node.children.join(\"\")];\n } else {\n node.children.forEach((child) => {\n TokenTree._collapse(child);\n });\n }\n }\n}\n\n/**\n Currently this is all private API, but this is the minimal API necessary\n that an Emitter must implement to fully support the parser.\n\n Minimal interface:\n\n - addText(text)\n - __addSublanguage(emitter, subLanguageName)\n - startScope(scope)\n - endScope()\n - finalize()\n - toHTML()\n\n*/\n\n/**\n * @implements {Emitter}\n */\nclass TokenTreeEmitter extends TokenTree {\n /**\n * @param {*} options\n */\n constructor(options) {\n super();\n this.options = options;\n }\n\n /**\n * @param {string} text\n */\n addText(text) {\n if (text === \"\") { return; }\n\n this.add(text);\n }\n\n /** @param {string} scope */\n startScope(scope) {\n this.openNode(scope);\n }\n\n endScope() {\n this.closeNode();\n }\n\n /**\n * @param {Emitter & {root: DataNode}} emitter\n * @param {string} name\n */\n __addSublanguage(emitter, name) {\n /** @type DataNode */\n const node = emitter.root;\n if (name) node.scope = `language:${name}`;\n\n this.add(node);\n }\n\n toHTML() {\n const renderer = new HTMLRenderer(this, this.options);\n return renderer.value();\n }\n\n finalize() {\n this.closeAllNodes();\n return true;\n }\n}\n\n/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n if (!re) return null;\n if (typeof re === \"string\") return re;\n\n return re.source;\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction lookahead(re) {\n return concat('(?=', re, ')');\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction anyNumberOfTimes(re) {\n return concat('(?:', re, ')*');\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction optional(re) {\n return concat('(?:', re, ')?');\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n const joined = args.map((x) => source(x)).join(\"\");\n return joined;\n}\n\n/**\n * @param { Array<string | RegExp | Object> } args\n * @returns {object}\n */\nfunction stripOptionsFromArgs(args) {\n const opts = args[args.length - 1];\n\n if (typeof opts === 'object' && opts.constructor === Object) {\n args.splice(args.length - 1, 1);\n return opts;\n } else {\n return {};\n }\n}\n\n/** @typedef { {capture?: boolean} } RegexEitherOptions */\n\n/**\n * Any of the passed expresssions may match\n *\n * Creates a huge this | this | that | that match\n * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args\n * @returns {string}\n */\nfunction either(...args) {\n /** @type { object & {capture?: boolean} } */\n const opts = stripOptionsFromArgs(args);\n const joined = '('\n + (opts.capture ? \"\" : \"?:\")\n + args.map((x) => source(x)).join(\"|\") + \")\";\n return joined;\n}\n\n/**\n * @param {RegExp | string} re\n * @returns {number}\n */\nfunction countMatchGroups(re) {\n return (new RegExp(re.toString() + '|')).exec('').length - 1;\n}\n\n/**\n * Does lexeme start with a regular expression match at the beginning\n * @param {RegExp} re\n * @param {string} lexeme\n */\nfunction startsWith(re, lexeme) {\n const match = re && re.exec(lexeme);\n return match && match.index === 0;\n}\n\n// BACKREF_RE matches an open parenthesis or backreference. To avoid\n// an incorrect parse, it additionally matches the following:\n// - [...] elements, where the meaning of parentheses and escapes change\n// - other escape sequences, so we do not misparse escape sequences as\n// interesting elements\n// - non-matching or lookahead parentheses, which do not capture. These\n// follow the '(' with a '?'.\nconst BACKREF_RE = /\\[(?:[^\\\\\\]]|\\\\.)*\\]|\\(\\??|\\\\([1-9][0-9]*)|\\\\./;\n\n// **INTERNAL** Not intended for outside usage\n// join logically computes regexps.join(separator), but fixes the\n// backreferences so they continue to match.\n// it also places each individual regular expression into it's own\n// match group, keeping track of the sequencing of those match groups\n// is currently an exercise for the caller. :-)\n/**\n * @param {(string | RegExp)[]} regexps\n * @param {{joinWith: string}} opts\n * @returns {string}\n */\nfunction _rewriteBackreferences(regexps, { joinWith }) {\n let numCaptures = 0;\n\n return regexps.map((regex) => {\n numCaptures += 1;\n const offset = numCaptures;\n let re = source(regex);\n let out = '';\n\n while (re.length > 0) {\n const match = BACKREF_RE.exec(re);\n if (!match) {\n out += re;\n break;\n }\n out += re.substring(0, match.index);\n re = re.substring(match.index + match[0].length);\n if (match[0][0] === '\\\\' && match[1]) {\n // Adjust the backreference.\n out += '\\\\' + String(Number(match[1]) + offset);\n } else {\n out += match[0];\n if (match[0] === '(') {\n numCaptures++;\n }\n }\n }\n return out;\n }).map(re => `(${re})`).join(joinWith);\n}\n\n/** @typedef {import('highlight.js').Mode} Mode */\n/** @typedef {import('highlight.js').ModeCallback} ModeCallback */\n\n// Common regexps\nconst MATCH_NOTHING_RE = /\\b\\B/;\nconst IDENT_RE = '[a-zA-Z]\\\\w*';\nconst UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\\\w*';\nconst NUMBER_RE = '\\\\b\\\\d+(\\\\.\\\\d+)?';\nconst C_NUMBER_RE = '(-?)(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)'; // 0x..., 0..., decimal, float\nconst BINARY_NUMBER_RE = '\\\\b(0b[01]+)'; // 0b...\nconst RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~';\n\n/**\n* @param { Partial<Mode> & {binary?: string | RegExp} } opts\n*/\nconst SHEBANG = (opts = {}) => {\n const beginShebang = /^#![ ]*\\//;\n if (opts.binary) {\n opts.begin = concat(\n beginShebang,\n /.*\\b/,\n opts.binary,\n /\\b.*/);\n }\n return inherit$1({\n scope: 'meta',\n begin: beginShebang,\n end: /$/,\n relevance: 0,\n /** @type {ModeCallback} */\n \"on:begin\": (m, resp) => {\n if (m.index !== 0) resp.ignoreMatch();\n }\n }, opts);\n};\n\n// Common modes\nconst BACKSLASH_ESCAPE = {\n begin: '\\\\\\\\[\\\\s\\\\S]', relevance: 0\n};\nconst APOS_STRING_MODE = {\n scope: 'string',\n begin: '\\'',\n end: '\\'',\n illegal: '\\\\n',\n contains: [BACKSLASH_ESCAPE]\n};\nconst QUOTE_STRING_MODE = {\n scope: 'string',\n begin: '\"',\n end: '\"',\n illegal: '\\\\n',\n contains: [BACKSLASH_ESCAPE]\n};\nconst PHRASAL_WORDS_MODE = {\n begin: /\\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\\b/\n};\n/**\n * Creates a comment mode\n *\n * @param {string | RegExp} begin\n * @param {string | RegExp} end\n * @param {Mode | {}} [modeOptions]\n * @returns {Partial<Mode>}\n */\nconst COMMENT = function(begin, end, modeOptions = {}) {\n const mode = inherit$1(\n {\n scope: 'comment',\n begin,\n end,\n contains: []\n },\n modeOptions\n );\n mode.contains.push({\n scope: 'doctag',\n // hack to avoid the space from being included. the space is necessary to\n // match here to prevent the plain text rule below from gobbling up doctags\n begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)',\n end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,\n excludeBegin: true,\n relevance: 0\n });\n const ENGLISH_WORD = either(\n // list of common 1 and 2 letter words in English\n \"I\",\n \"a\",\n \"is\",\n \"so\",\n \"us\",\n \"to\",\n \"at\",\n \"if\",\n \"in\",\n \"it\",\n \"on\",\n // note: this is not an exhaustive list of contractions, just popular ones\n /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc\n /[A-Za-z]+[-][a-z]+/, // `no-way`, etc.\n /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences\n );\n // looking like plain text, more likely to be a comment\n mode.contains.push(\n {\n // TODO: how to include \", (, ) without breaking grammars that use these for\n // comment delimiters?\n // begin: /[ ]+([()\"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()\":]?([.][ ]|[ ]|\\))){3}/\n // ---\n\n // this tries to find sequences of 3 english words in a row (without any\n // \"programming\" type syntax) this gives us a strong signal that we've\n // TRULY found a comment - vs perhaps scanning with the wrong language.\n // It's possible to find something that LOOKS like the start of the\n // comment - but then if there is no readable text - good chance it is a\n // false match and not a comment.\n //\n // for a visual example please see:\n // https://github.com/highlightjs/highlight.js/issues/2827\n\n begin: concat(\n /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */\n '(',\n ENGLISH_WORD,\n /[.]?[:]?([.][ ]|[ ])/,\n '){3}') // look for 3 words in a row\n }\n );\n return mode;\n};\nconst C_LINE_COMMENT_MODE = COMMENT('//', '$');\nconst C_BLOCK_COMMENT_MODE = COMMENT('/\\\\*', '\\\\*/');\nconst HASH_COMMENT_MODE = COMMENT('#', '$');\nconst NUMBER_MODE = {\n scope: 'number',\n begin: NUMBER_RE,\n relevance: 0\n};\nconst C_NUMBER_MODE = {\n scope: 'number',\n begin: C_NUMBER_RE,\n relevance: 0\n};\nconst BINARY_NUMBER_MODE = {\n scope: 'number',\n begin: BINARY_NUMBER_RE,\n relevance: 0\n};\nconst REGEXP_MODE = {\n scope: \"regexp\",\n begin: /\\/(?=[^/\\n]*\\/)/,\n end: /\\/[gimuy]*/,\n contains: [\n BACKSLASH_ESCAPE,\n {\n begin: /\\[/,\n end: /\\]/,\n relevance: 0,\n contains: [BACKSLASH_ESCAPE]\n }\n ]\n};\nconst TITLE_MODE = {\n scope: 'title',\n begin: IDENT_RE,\n relevance: 0\n};\nconst UNDERSCORE_TITLE_MODE = {\n scope: 'title',\n begin: UNDERSCORE_IDENT_RE,\n relevance: 0\n};\nconst METHOD_GUARD = {\n // excludes method names from keyword processing\n begin: '\\\\.\\\\s*' + UNDERSCORE_IDENT_RE,\n relevance: 0\n};\n\n/**\n * Adds end same as begin mechanics to a mode\n *\n * Your mode must include at least a single () match group as that first match\n * group is what is used for comparison\n * @param {Partial<Mode>} mode\n */\nconst END_SAME_AS_BEGIN = function(mode) {\n return Object.assign(mode,\n {\n /** @type {ModeCallback} */\n 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; },\n /** @type {ModeCallback} */\n 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); }\n });\n};\n\nvar MODES = /*#__PURE__*/Object.freeze({\n __proto__: null,\n APOS_STRING_MODE: APOS_STRING_MODE,\n BACKSLASH_ESCAPE: BACKSLASH_ESCAPE,\n BINARY_NUMBER_MODE: BINARY_NUMBER_MODE,\n BINARY_NUMBER_RE: BINARY_NUMBER_RE,\n COMMENT: COMMENT,\n C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE,\n C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE,\n C_NUMBER_MODE: C_NUMBER_MODE,\n C_NUMBER_RE: C_NUMBER_RE,\n END_SAME_AS_BEGIN: END_SAME_AS_BEGIN,\n HASH_COMMENT_MODE: HASH_COMMENT_MODE,\n IDENT_RE: IDENT_RE,\n MATCH_NOTHING_RE: MATCH_NOTHING_RE,\n METHOD_GUARD: METHOD_GUARD,\n NUMBER_MODE: NUMBER_MODE,\n NUMBER_RE: NUMBER_RE,\n PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE,\n QUOTE_STRING_MODE: QUOTE_STRING_MODE,\n REGEXP_MODE: REGEXP_MODE,\n RE_STARTERS_RE: RE_STARTERS_RE,\n SHEBANG: SHEBANG,\n TITLE_MODE: TITLE_MODE,\n UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE,\n UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE\n});\n\n/**\n@typedef {import('highlight.js').CallbackResponse} CallbackResponse\n@typedef {import('highlight.js').CompilerExt} CompilerExt\n*/\n\n// Grammar extensions / plugins\n// See: https://github.com/highlightjs/highlight.js/issues/2833\n\n// Grammar extensions allow \"syntactic sugar\" to be added to the grammar modes\n// without requiring any underlying changes to the compiler internals.\n\n// `compileMatch` being the perfect small example of now allowing a grammar\n// author to write `match` when they desire to match a single expression rather\n// than being forced to use `begin`. The extension then just moves `match` into\n// `begin` when it runs. Ie, no features have been added, but we've just made\n// the experience of writing (and reading grammars) a little bit nicer.\n\n// ------\n\n// TODO: We need negative look-behind support to do this properly\n/**\n * Skip a match if it has a preceding dot\n *\n * This is used for `beginKeywords` to prevent matching expressions such as\n * `bob.keyword.do()`. The mode compiler automatically wires this up as a\n * special _internal_ 'on:begin' callback for modes with `beginKeywords`\n * @param {RegExpMatchArray} match\n * @param {CallbackResponse} response\n */\nfunction skipIfHasPrecedingDot(match, response) {\n const before = match.input[match.index - 1];\n if (before === \".\") {\n response.ignoreMatch();\n }\n}\n\n/**\n *\n * @type {CompilerExt}\n */\nfunction scopeClassName(mode, _parent) {\n // eslint-disable-next-line no-undefined\n if (mode.className !== undefined) {\n mode.scope = mode.className;\n delete mode.className;\n }\n}\n\n/**\n * `beginKeywords` syntactic sugar\n * @type {CompilerExt}\n */\nfunction beginKeywords(mode, parent) {\n if (!parent) return;\n if (!mode.beginKeywords) return;\n\n // for languages with keywords that include non-word characters checking for\n // a word boundary is not sufficient, so instead we check for a word boundary\n // or whitespace - this does no harm in any case since our keyword engine\n // doesn't allow spaces in keywords anyways and we still check for the boundary\n // first\n mode.begin = '\\\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\\\.)(?=\\\\b|\\\\s)';\n mode.__beforeBegin = skipIfHasPrecedingDot;\n mode.keywords = mode.keywords || mode.beginKeywords;\n delete mode.beginKeywords;\n\n // prevents double relevance, the keywords themselves provide\n // relevance, the mode doesn't need to double it\n // eslint-disable-next-line no-undefined\n if (mode.relevance === undefined) mode.relevance = 0;\n}\n\n/**\n * Allow `illegal` to contain an array of illegal values\n * @type {CompilerExt}\n */\nfunction compileIllegal(mode, _parent) {\n if (!Array.isArray(mode.illegal)) return;\n\n mode.illegal = either(...mode.illegal);\n}\n\n/**\n * `match` to match a single expression for readability\n * @type {CompilerExt}\n */\nfunction compileMatch(mode, _parent) {\n if (!mode.match) return;\n if (mode.begin || mode.end) throw new Error(\"begin & end are not supported with match\");\n\n mode.begin = mode.match;\n delete mode.match;\n}\n\n/**\n * provides the default 1 relevance to all modes\n * @type {CompilerExt}\n */\nfunction compileRelevance(mode, _parent) {\n // eslint-disable-next-line no-undefined\n if (mode.relevance === undefined) mode.relevance = 1;\n}\n\n// allow beforeMatch to act as a \"qualifier\" for the match\n// the full match begin must be [beforeMatch][begin]\nconst beforeMatchExt = (mode, parent) => {\n if (!mode.beforeMatch) return;\n // starts conflicts with endsParent which we need to make sure the child\n // rule is not matched multiple times\n if (mode.starts) throw new Error(\"beforeMatch cannot be used with starts\");\n\n const originalMode = Object.assign({}, mode);\n Object.keys(mode).forEach((key) => { delete mode[key]; });\n\n mode.keywords = originalMode.keywords;\n mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));\n mode.starts = {\n relevance: 0,\n contains: [\n Object.assign(originalMode, { endsParent: true })\n ]\n };\n mode.relevance = 0;\n\n delete originalMode.beforeMatch;\n};\n\n// keywords that should have no default relevance value\nconst COMMON_KEYWORDS = [\n 'of',\n 'and',\n 'for',\n 'in',\n 'not',\n 'or',\n 'if',\n 'then',\n 'parent', // common variable name\n 'list', // common variable name\n 'value' // common variable name\n];\n\nconst DEFAULT_KEYWORD_SCOPE = \"keyword\";\n\n/**\n * Given raw keywords from a language definition, compile them.\n *\n * @param {string | Record<string,string|string[]> | Array<string>} rawKeywords\n * @param {boolean} caseInsensitive\n */\nfunction compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) {\n /** @type {import(\"highlight.js/private\").KeywordDict} */\n const compiledKeywords = Object.create(null);\n\n // input can be a string of keywords, an array of keywords, or a object with\n // named keys representing scopeName (which can then point to a string or array)\n if (typeof rawKeywords === 'string') {\n compileList(scopeName, rawKeywords.split(\" \"));\n } else if (Array.isArray(rawKeywords)) {\n compileList(scopeName, rawKeywords);\n } else {\n Object.keys(rawKeywords).forEach(function(scopeName) {\n // collapse all our objects back into the parent object\n Object.assign(\n compiledKeywords,\n compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName)\n );\n });\n }\n return compiledKeywords;\n\n // ---\n\n /**\n * Compiles an individual list of keywords\n *\n * Ex: \"for if when while|5\"\n *\n * @param {string} scopeName\n * @param {Array<string>} keywordList\n */\n function compileList(scopeName, keywordList) {\n if (caseInsensitive) {\n keywordList = keywordList.map(x => x.toLowerCase());\n }\n keywordList.forEach(function(keyword) {\n const pair = keyword.split('|');\n compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])];\n });\n }\n}\n\n/**\n * Returns the proper score for a given keyword\n *\n * Also takes into account comment keywords, which will be scored 0 UNLESS\n * another score has been manually assigned.\n * @param {string} keyword\n * @param {string} [providedScore]\n */\nfunction scoreForKeyword(keyword, providedScore) {\n // manual scores always win over common keywords\n // so you can force a score of 1 if you really insist\n if (providedScore) {\n return Number(providedScore);\n }\n\n return commonKeyword(keyword) ? 0 : 1;\n}\n\n/**\n * Determines if a given keyword is common or not\n *\n * @param {string} keyword */\nfunction commonKeyword(keyword) {\n return COMMON_KEYWORDS.includes(keyword.toLowerCase());\n}\n\n/*\n\nFor the reasoning behind this please see:\nhttps://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419\n\n*/\n\n/**\n * @type {Record<string, boolean>}\n */\nconst seenDeprecations = {};\n\n/**\n * @param {string} message\n */\nconst error = (message) => {\n console.error(message);\n};\n\n/**\n * @param {string} message\n * @param {any} args\n */\nconst warn = (message, ...args) => {\n console.log(`WARN: ${message}`, ...args);\n};\n\n/**\n * @param {string} version\n * @param {string} message\n */\nconst deprecated = (version, message) => {\n if (seenDeprecations[`${version}/${message}`]) return;\n\n console.log(`Deprecated as of ${version}. ${message}`);\n seenDeprecations[`${version}/${message}`] = true;\n};\n\n/* eslint-disable no-throw-literal */\n\n/**\n@typedef {import('highlight.js').CompiledMode} CompiledMode\n*/\n\nconst MultiClassError = new Error();\n\n/**\n * Renumbers labeled scope names to account for additional inner match\n * groups that otherwise would break everything.\n *\n * Lets say we 3 match scopes:\n *\n * { 1 => ..., 2 => ..., 3 => ... }\n *\n * So what we need is a clean match like this:\n *\n * (a)(b)(c) => [ \"a\", \"b\", \"c\" ]\n *\n * But this falls apart with inner match groups:\n *\n * (a)(((b)))(c) => [\"a\", \"b\", \"b\", \"b\", \"c\" ]\n *\n * Our scopes are now \"out of alignment\" and we're repeating `b` 3 times.\n * What needs to happen is the numbers are remapped:\n *\n * { 1 => ..., 2 => ..., 5 => ... }\n *\n * We also need to know that the ONLY groups that should be output\n * are 1, 2, and 5. This function handles this behavior.\n *\n * @param {CompiledMode} mode\n * @param {Array<RegExp | string>} regexes\n * @param {{key: \"beginScope\"|\"endScope\"}} opts\n */\nfunction remapScopeNames(mode, regexes, { key }) {\n let offset = 0;\n const scopeNames = mode[key];\n /** @type Record<number,boolean> */\n const emit = {};\n /** @type Record<number,string> */\n const positions = {};\n\n for (let i = 1; i <= regexes.length; i++) {\n positions[i + offset] = scopeNames[i];\n emit[i + offset] = true;\n offset += countMatchGroups(regexes[i - 1]);\n }\n // we use _emit to keep track of which match groups are \"top-level\" to avoid double\n // output from inside match groups\n mode[key] = positions;\n mode[key]._emit = emit;\n mode[key]._multi = true;\n}\n\n/**\n * @param {CompiledMode} mode\n */\nfunction beginMultiClass(mode) {\n if (!Array.isArray(mode.begin)) return;\n\n if (mode.skip || mode.excludeBegin || mode.returnBegin) {\n error(\"skip, excludeBegin, returnBegin not compatible with beginScope: {}\");\n throw MultiClassError;\n }\n\n if (typeof mode.beginScope !== \"object\" || mode.beginScope === null) {\n error(\"beginScope must be object\");\n throw MultiClassError;\n }\n\n remapScopeNames(mode, mode.begin, { key: \"beginScope\" });\n mode.begin = _rewriteBackreferences(mode.begin, { joinWith: \"\" });\n}\n\n/**\n * @param {CompiledMode} mode\n */\nfunction endMultiClass(mode) {\n if (!Array.isArray(mode.end)) return;\n\n if (mode.skip || mode.excludeEnd || mode.returnEnd) {\n error(\"skip, excludeEnd, returnEnd not compatible with endScope: {}\");\n throw MultiClassError;\n }\n\n if (typeof mode.endScope !== \"object\" || mode.endScope === null) {\n error(\"endScope must be object\");\n throw MultiClassError;\n }\n\n remapScopeNames(mode, mode.end, { key: \"endScope\" });\n mode.end = _rewriteBackreferences(mode.end, { joinWith: \"\" });\n}\n\n/**\n * this exists only to allow `scope: {}` to be used beside `match:`\n * Otherwise `beginScope` would necessary and that would look weird\n\n {\n match: [ /def/, /\\w+/ ]\n scope: { 1: \"keyword\" , 2: \"title\" }\n }\n\n * @param {CompiledMode} mode\n */\nfunction scopeSugar(mode) {\n if (mode.scope && typeof mode.scope === \"object\" && mode.scope !== null) {\n mode.beginScope = mode.scope;\n delete mode.scope;\n }\n}\n\n/**\n * @param {CompiledMode} mode\n */\nfunction MultiClass(mode) {\n scopeSugar(mode);\n\n if (typeof mode.beginScope === \"string\") {\n mode.beginScope = { _wrap: mode.beginScope };\n }\n if (typeof mode.endScope === \"string\") {\n mode.endScope = { _wrap: mode.endScope };\n }\n\n beginMultiClass(mode);\n endMultiClass(mode);\n}\n\n/**\n@typedef {import('highlight.js').Mode} Mode\n@typedef {import('highlight.js').CompiledMode} CompiledMode\n@typedef {import('highlight.js').Language} Language\n@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin\n@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage\n*/\n\n// compilation\n\n/**\n * Compiles a language definition result\n *\n * Given the raw result of a language definition (Language), compiles this so\n * that it is ready for highlighting code.\n * @param {Language} language\n * @returns {CompiledLanguage}\n */\nfunction compileLanguage(language) {\n /**\n * Builds a regex with the case sensitivity of the current language\n *\n * @param {RegExp | string} value\n * @param {boolean} [global]\n */\n function langRe(value, global) {\n return new RegExp(\n source(value),\n 'm'\n + (language.case_insensitive ? 'i' : '')\n + (language.unicodeRegex ? 'u' : '')\n + (global ? 'g' : '')\n );\n }\n\n /**\n Stores multiple regular expressions and allows you to quickly search for\n them all in a string simultaneously - returning the first match. It does\n this by creating a huge (a|b|c) regex - each individual item wrapped with ()\n and joined by `|` - using match groups to track position. When a match is\n found checking which position in the array has content allows us to figure\n out which of the original regexes / match groups triggered the match.\n\n The match object itself (the result of `Regex.exec`) is returned but also\n enhanced by merging in any meta-data that was registered with the regex.\n This is how we keep track of which mode matched, and what type of rule\n (`illegal`, `begin`, end, etc).\n */\n class MultiRegex {\n constructor() {\n this.matchIndexes = {};\n // @ts-ignore\n this.regexes = [];\n this.matchAt = 1;\n this.position = 0;\n }\n\n // @ts-ignore\n addRule(re, opts) {\n opts.position = this.position++;\n // @ts-ignore\n this.matchIndexes[this.matchAt] = opts;\n this.regexes.push([opts, re]);\n this.matchAt += countMatchGroups(re) + 1;\n }\n\n compile() {\n if (this.regexes.length === 0) {\n // avoids the need to check length every time exec is called\n // @ts-ignore\n this.exec = () => null;\n }\n const terminators = this.regexes.map(el => el[1]);\n this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true);\n this.lastIndex = 0;\n }\n\n /** @param {string} s */\n exec(s) {\n this.matcherRe.lastIndex = this.lastIndex;\n const match = this.matcherRe.exec(s);\n if (!match) { return null; }\n\n // eslint-disable-next-line no-undefined\n const i = match.findIndex((el, i) => i > 0 && el !== undefined);\n // @ts-ignore\n const matchData = this.matchIndexes[i];\n // trim off any earlier non-relevant match groups (ie, the other regex\n // match groups that make up the multi-matcher)\n match.splice(0, i);\n\n return Object.assign(match, matchData);\n }\n }\n\n /*\n Created to solve the key deficiently with MultiRegex - there is no way to\n test for multiple matches at a single location. Why would we need to do\n that? In the future a more dynamic engine will allow certain matches to be\n ignored. An example: if we matched say the 3rd regex in a large group but\n decided to ignore it - we'd need to started testing again at the 4th\n regex... but MultiRegex itself gives us no real way to do that.\n\n So what this class creates MultiRegexs on the fly for whatever search\n position they are needed.\n\n NOTE: These additional MultiRegex objects are created dynamically. For most\n grammars most of the time we will never actually need anything more than the\n first MultiRegex - so this shouldn't have too much overhead.\n\n Say this is our search group, and we match regex3, but wish to ignore it.\n\n regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0\n\n What we need is a new MultiRegex that only includes the remaining\n possibilities:\n\n regex4 | regex5 ' ie, startAt = 3\n\n This class wraps all that complexity up in a simple API... `startAt` decides\n where in the array of expressions to start doing the matching. It\n auto-increments, so if a match is found at position 2, then startAt will be\n set to 3. If the end is reached startAt will return to 0.\n\n MOST of the time the parser will be setting startAt manually to 0.\n */\n class ResumableMultiRegex {\n constructor() {\n // @ts-ignore\n this.rules = [];\n // @ts-ignore\n this.multiRegexes = [];\n this.count = 0;\n\n this.lastIndex = 0;\n this.regexIndex = 0;\n }\n\n // @ts-ignore\n getMatcher(index) {\n if (this.multiRegexes[index]) return this.multiRegexes[index];\n\n const matcher = new MultiRegex();\n this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts));\n matcher.compile();\n this.multiRegexes[index] = matcher;\n return matcher;\n }\n\n resumingScanAtSamePosition() {\n return this.regexIndex !== 0;\n }\n\n considerAll() {\n this.regexIndex = 0;\n }\n\n // @ts-ignore\n addRule(re, opts) {\n this.rules.push([re, opts]);\n if (opts.type === \"begin\") this.count++;\n }\n\n /** @param {string} s */\n exec(s) {\n const m = this.getMatcher(this.regexIndex);\n m.lastIndex = this.lastIndex;\n let result = m.exec(s);\n\n // The following is because we have no easy way to say \"resume scanning at the\n // existing position but also skip the current rule ONLY\". What happens is\n // all prior rules are also skipped which can result in matching the wrong\n // thing. Example of matching \"booger\":\n\n // our matcher is [string, \"booger\", number]\n //\n // ....booger....\n\n // if \"booger\" is ignored then we'd really need a regex to scan from the\n // SAME position for only: [string, number] but ignoring \"booger\" (if it\n // was the first match), a simple resume would scan ahead who knows how\n // far looking only for \"number\", ignoring potential string matches (or\n // future \"booger\" matches that might be valid.)\n\n // So what we do: We execute two matchers, one resuming at the same\n // position, but the second full matcher starting at the position after:\n\n // /--- resume first regex match here (for [number])\n // |/---- full match here for [string, \"booger\", number]\n // vv\n // ....booger....\n\n // Which ever results in a match first is then used. So this 3-4 step\n // process essentially allows us to say \"match at this position, excluding\n // a prior rule that was ignored\".\n //\n // 1. Match \"booger\" first, ignore. Also proves that [string] does non match.\n // 2. Resume matching for [number]\n // 3. Match at index + 1 for [string, \"booger\", number]\n // 4. If #2 and #3 result in matches, which came first?\n if (this.resumingScanAtSamePosition()) {\n if (result && result.index === this.lastIndex) ; else { // use the second matcher result\n const m2 = this.getMatcher(0);\n m2.lastIndex = this.lastIndex + 1;\n result = m2.exec(s);\n }\n }\n\n if (result) {\n this.regexIndex += result.position + 1;\n if (this.regexIndex === this.count) {\n // wrap-around to considering all matches again\n this.considerAll();\n }\n }\n\n return result;\n }\n }\n\n /**\n * Given a mode, builds a huge ResumableMultiRegex that can be used to walk\n * the content and find matches.\n *\n * @param {CompiledMode} mode\n * @returns {ResumableMultiRegex}\n */\n function buildModeRegex(mode) {\n const mm = new ResumableMultiRegex();\n\n mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: \"begin\" }));\n\n if (mode.terminatorEnd) {\n mm.addRule(mode.terminatorEnd, { type: \"end\" });\n }\n if (mode.illegal) {\n mm.addRule(mode.illegal, { type: \"illegal\" });\n }\n\n return mm;\n }\n\n /** skip vs abort vs ignore\n *\n * @skip - The mode is still entered and exited normally (and contains rules apply),\n * but all content is held and added to the parent buffer rather than being\n * output when the mode ends. Mostly used with `sublanguage` to build up\n * a single large buffer than can be parsed by sublanguage.\n *\n * - The mode begin ands ends normally.\n * - Content matched is added to the parent mode buffer.\n * - The parser cursor is moved forward normally.\n *\n * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it\n * never matched) but DOES NOT continue to match subsequent `contains`\n * modes. Abort is bad/suboptimal because it can result in modes\n * farther down not getting applied because an earlier rule eats the\n * content but then aborts.\n *\n * - The mode does not begin.\n * - Content matched by `begin` is added to the mode buffer.\n * - The parser cursor is moved forward accordingly.\n *\n * @ignore - Ignores the mode (as if it never matched) and continues to match any\n * subsequent `contains` modes. Ignore isn't technically possible with\n * the current parser implementation.\n *\n * - The mode does not begin.\n * - Content matched by `begin` is ignored.\n * - The parser cursor is not moved forward.\n */\n\n /**\n * Compiles an individual mode\n *\n * This can raise an error if the mode contains certain detectable known logic\n * issues.\n * @param {Mode} mode\n * @param {CompiledMode | null} [parent]\n * @returns {CompiledMode | never}\n */\n function compileMode(mode, parent) {\n const cmode = /** @type CompiledMode */ (mode);\n if (mode.isCompiled) return cmode;\n\n [\n scopeClassName,\n // do this early so compiler extensions generally don't have to worry about\n // the distinction between match/begin\n compileMatch,\n MultiClass,\n beforeMatchExt\n ].forEach(ext => ext(mode, parent));\n\n language.compilerExtensions.forEach(ext => ext(mode, parent));\n\n // __beforeBegin is considered private API, internal use only\n mode.__beforeBegin = null;\n\n [\n beginKeywords,\n // do this later so compiler extensions that come earlier have access to the\n // raw array if they wanted to perhaps manipulate it, etc.\n compileIllegal,\n // default to 1 relevance if not specified\n compileRelevance\n ].forEach(ext => ext(mode, parent));\n\n mode.isCompiled = true;\n\n let keywordPattern = null;\n if (typeof mode.keywords === \"object\" && mode.keywords.$pattern) {\n // we need a copy because keywords might be compiled multiple times\n // so we can't go deleting $pattern from the original on the first\n // pass\n mode.keywords = Object.assign({}, mode.keywords);\n keywordPattern = mode.keywords.$pattern;\n delete mode.keywords.$pattern;\n }\n keywordPattern = keywordPattern || /\\w+/;\n\n if (mode.keywords) {\n mode.keywords = compileKeywords(mode.keywords, language.case_insensitive);\n }\n\n cmode.keywordPatternRe = langRe(keywordPattern, true);\n\n if (parent) {\n if (!mode.begin) mode.begin = /\\B|\\b/;\n cmode.beginRe = langRe(cmode.begin);\n if (!mode.end && !mode.endsWithParent) mode.end = /\\B|\\b/;\n if (mode.end) cmode.endRe = langRe(cmode.end);\n cmode.terminatorEnd = source(cmode.end) || '';\n if (mode.endsWithParent && parent.terminatorEnd) {\n cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd;\n }\n }\n if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal));\n if (!mode.contains) mode.contains = [];\n\n mode.contains = [].concat(...mode.contains.map(function(c) {\n return expandOrCloneMode(c === 'self' ? mode : c);\n }));\n mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); });\n\n if (mode.starts) {\n compileMode(mode.starts, parent);\n }\n\n cmode.matcher = buildModeRegex(cmode);\n return cmode;\n }\n\n if (!language.compilerExtensions) language.compilerExtensions = [];\n\n // self is not valid at the top-level\n if (language.contains && language.contains.includes('self')) {\n throw new Error(\"ERR: contains `self` is not supported at the top-level of a language. See documentation.\");\n }\n\n // we need a null object, which inherit will guarantee\n language.classNameAliases = inherit$1(language.classNameAliases || {});\n\n return compileMode(/** @type Mode */ (language));\n}\n\n/**\n * Determines if a mode has a dependency on it's parent or not\n *\n * If a mode does have a parent dependency then often we need to clone it if\n * it's used in multiple places so that each copy points to the correct parent,\n * where-as modes without a parent can often safely be re-used at the bottom of\n * a mode chain.\n *\n * @param {Mode | null} mode\n * @returns {boolean} - is there a dependency on the parent?\n * */\nfunction dependencyOnParent(mode) {\n if (!mode) return false;\n\n return mode.endsWithParent || dependencyOnParent(mode.starts);\n}\n\n/**\n * Expands a mode or clones it if necessary\n *\n * This is necessary for modes with parental dependenceis (see notes on\n * `dependencyOnParent`) and for nodes that have `variants` - which must then be\n * exploded into their own individual modes at compile time.\n *\n * @param {Mode} mode\n * @returns {Mode | Mode[]}\n * */\nfunction expandOrCloneMode(mode) {\n if (mode.variants && !mode.cachedVariants) {\n mode.cachedVariants = mode.variants.map(function(variant) {\n return inherit$1(mode, { variants: null }, variant);\n });\n }\n\n // EXPAND\n // if we have variants then essentially \"replace\" the mode with the variants\n // this happens in compileMode, where this function is called from\n if (mode.cachedVariants) {\n return mode.cachedVariants;\n }\n\n // CLONE\n // if we have dependencies on parents then we need a unique\n // instance of ourselves, so we can be reused with many\n // different parents without issue\n if (dependencyOnParent(mode)) {\n return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null });\n }\n\n if (Object.isFrozen(mode)) {\n return inherit$1(mode);\n }\n\n // no special dependency issues, just return ourselves\n return mode;\n}\n\nvar version = \"11.11.1\";\n\nclass HTMLInjectionError extends Error {\n constructor(reason, html) {\n super(reason);\n this.name = \"HTMLInjectionError\";\n this.html = html;\n }\n}\n\n/*\nSyntax highlighting with language autodetection.\nhttps://highlightjs.org/\n*/\n\n\n\n/**\n@typedef {import('highlight.js').Mode} Mode\n@typedef {import('highlight.js').CompiledMode} CompiledMode\n@typedef {import('highlight.js').CompiledScope} CompiledScope\n@typedef {import('highlight.js').Language} Language\n@typedef {import('highlight.js').HLJSApi} HLJSApi\n@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin\n@typedef {import('highlight.js').PluginEvent} PluginEvent\n@typedef {import('highlight.js').HLJSOptions} HLJSOptions\n@typedef {import('highlight.js').LanguageFn} LanguageFn\n@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement\n@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext\n@typedef {import('highlight.js/private').MatchType} MatchType\n@typedef {import('highlight.js/private').KeywordData} KeywordData\n@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch\n@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError\n@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult\n@typedef {import('highlight.js').HighlightOptions} HighlightOptions\n@typedef {import('highlight.js').HighlightResult} HighlightResult\n*/\n\n\nconst escape = escapeHTML;\nconst inherit = inherit$1;\nconst NO_MATCH = Symbol(\"nomatch\");\nconst MAX_KEYWORD_HITS = 7;\n\n/**\n * @param {any} hljs - object that is extended (legacy)\n * @returns {HLJSApi}\n */\nconst HLJS = function(hljs) {\n // Global internal variables used within the highlight.js library.\n /** @type {Record<string, Language>} */\n const languages = Object.create(null);\n /** @type {Record<string, string>} */\n const aliases = Object.create(null);\n /** @type {HLJSPlugin[]} */\n const plugins = [];\n\n // safe/production mode - swallows more errors, tries to keep running\n // even if a single syntax or parse hits a fatal error\n let SAFE_MODE = true;\n const LANGUAGE_NOT_FOUND = \"Could not find the language '{}', did you forget to load/include a language module?\";\n /** @type {Language} */\n const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] };\n\n // Global options used when within external APIs. This is modified when\n // calling the `hljs.configure` function.\n /** @type HLJSOptions */\n let options = {\n ignoreUnescapedHTML: false,\n throwUnescapedHTML: false,\n noHighlightRe: /^(no-?highlight)$/i,\n languageDetectRe: /\\blang(?:uage)?-([\\w-]+)\\b/i,\n classPrefix: 'hljs-',\n cssSelector: 'pre code',\n languages: null,\n // beta configuration options, subject to change, welcome to discuss\n // https://github.com/highlightjs/highlight.js/issues/1086\n __emitter: TokenTreeEmitter\n };\n\n /* Utility functions */\n\n /**\n * Tests a language name to see if highlighting should be skipped\n * @param {string} languageName\n */\n function shouldNotHighlight(languageName) {\n return options.noHighlightRe.test(languageName);\n }\n\n /**\n * @param {HighlightedHTMLElement} block - the HTML element to determine language for\n */\n function blockLanguage(block) {\n let classes = block.className + ' ';\n\n classes += block.parentNode ? block.parentNode.className : '';\n\n // language-* takes precedence over non-prefixed class names.\n const match = options.languageDetectRe.exec(classes);\n if (match) {\n const language = getLanguage(match[1]);\n if (!language) {\n warn(LANGUAGE_NOT_FOUND.replace(\"{}\", match[1]));\n warn(\"Falling back to no-highlight mode for this block.\", block);\n }\n return language ? match[1] : 'no-highlight';\n }\n\n return classes\n .split(/\\s+/)\n .find((_class) => shouldNotHighlight(_class) || getLanguage(_class));\n }\n\n /**\n * Core highlighting function.\n *\n * OLD API\n * highlight(lang, code, ignoreIllegals, continuation)\n *\n * NEW API\n * highlight(code, {lang, ignoreIllegals})\n *\n * @param {string} codeOrLanguageName - the language to use for highlighting\n * @param {string | HighlightOptions} optionsOrCode - the code to highlight\n * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail\n *\n * @returns {HighlightResult} Result - an object that represents the result\n * @property {string} language - the language name\n * @property {number} relevance - the relevance score\n * @property {string} value - the highlighted HTML code\n * @property {string} code - the original raw code\n * @property {CompiledMode} top - top of the current mode stack\n * @property {boolean} illegal - indicates whether any illegal matches were found\n */\n function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) {\n let code = \"\";\n let languageName = \"\";\n if (typeof optionsOrCode === \"object\") {\n code = codeOrLanguageName;\n ignoreIllegals = optionsOrCode.ignoreIllegals;\n languageName = optionsOrCode.language;\n } else {\n // old API\n deprecated(\"10.7.0\", \"highlight(lang, code, ...args) has been deprecated.\");\n deprecated(\"10.7.0\", \"Please use highlight(code, options) instead.\\nhttps://github.com/highlightjs/highlight.js/issues/2277\");\n languageName = codeOrLanguageName;\n code = optionsOrCode;\n }\n\n // https://github.com/highlightjs/highlight.js/issues/3149\n // eslint-disable-next-line no-undefined\n if (ignoreIllegals === undefined) { ignoreIllegals = true; }\n\n /** @type {BeforeHighlightContext} */\n const context = {\n code,\n language: languageName\n };\n // the plugin can change the desired language or the code to be highlighted\n // just be changing the object it was passed\n fire(\"before:highlight\", context);\n\n // a before plugin can usurp the result completely by providing it's own\n // in which case we don't even need to call highlight\n const result = context.result\n ? context.result\n : _highlight(context.language, context.code, ignoreIllegals);\n\n result.code = context.code;\n // the plugin can change anything in result to suite it\n fire(\"after:highlight\", result);\n\n return result;\n }\n\n /**\n * private highlight that's used internally and does not fire callbacks\n *\n * @param {string} languageName - the language to use for highlighting\n * @param {string} codeToHighlight - the code to highlight\n * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail\n * @param {CompiledMode?} [continuation] - current continuation mode, if any\n * @returns {HighlightResult} - result of the highlight operation\n */\n function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {\n const keywordHits = Object.create(null);\n\n /**\n * Return keyword data if a match is a keyword\n * @param {CompiledMode} mode - current mode\n * @param {string} matchText - the textual match\n * @returns {KeywordData | false}\n */\n function keywordData(mode, matchText) {\n return mode.keywords[matchText];\n }\n\n function processKeywords() {\n if (!top.keywords) {\n emitter.addText(modeBuffer);\n return;\n }\n\n let lastIndex = 0;\n top.keywordPatternRe.lastIndex = 0;\n let match = top.keywordPatternRe.exec(modeBuffer);\n let buf = \"\";\n\n while (match) {\n buf += modeBuffer.substring(lastIndex, match.index);\n const word = language.case_insensitive ? match[0].toLowerCase() : match[0];\n const data = keywordData(top, word);\n if (data) {\n const [kind, keywordRelevance] = data;\n emitter.addText(buf);\n buf = \"\";\n\n keywordHits[word] = (keywordHits[word] || 0) + 1;\n if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance;\n if (kind.startsWith(\"_\")) {\n // _ implied for relevance only, do not highlight\n // by applying a class name\n buf += match[0];\n } else {\n const cssClass = language.classNameAliases[kind] || kind;\n emitKeyword(match[0], cssClass);\n }\n } else {\n buf += match[0];\n }\n lastIndex = top.keywordPatternRe.lastIndex;\n match = top.keywordPatternRe.exec(modeBuffer);\n }\n buf += modeBuffer.substring(lastIndex);\n emitter.addText(buf);\n }\n\n function processSubLanguage() {\n if (modeBuffer === \"\") return;\n /** @type HighlightResult */\n let result = null;\n\n if (typeof top.subLanguage === 'string') {\n if (!languages[top.subLanguage]) {\n emitter.addText(modeBuffer);\n return;\n }\n result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]);\n continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top);\n } else {\n result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null);\n }\n\n // Counting embedded language score towards the host language may be disabled\n // with zeroing the containing mode relevance. Use case in point is Markdown that\n // allows XML everywhere and makes every XML snippet to have a much larger Markdown\n // score.\n if (top.relevance > 0) {\n relevance += result.relevance;\n }\n emitter.__addSublanguage(result._emitter, result.language);\n }\n\n function processBuffer() {\n if (top.subLanguage != null) {\n processSubLanguage();\n } else {\n processKeywords();\n }\n modeBuffer = '';\n }\n\n /**\n * @param {string} text\n * @param {string} scope\n */\n function emitKeyword(keyword, scope) {\n if (keyword === \"\") return;\n\n emitter.startScope(scope);\n emitter.addText(keyword);\n emitter.endScope();\n }\n\n /**\n * @param {CompiledScope} scope\n * @param {RegExpMatchArray} match\n */\n function emitMultiClass(scope, match) {\n let i = 1;\n const max = match.length - 1;\n while (i <= max) {\n if (!scope._emit[i]) { i++; continue; }\n const klass = language.classNameAliases[scope[i]] || scope[i];\n const text = match[i];\n if (klass) {\n emitKeyword(text, klass);\n } else {\n modeBuffer = text;\n processKeywords();\n modeBuffer = \"\";\n }\n i++;\n }\n }\n\n /**\n * @param {CompiledMode} mode - new mode to start\n * @param {RegExpMatchArray} match\n */\n function startNewMode(mode, match) {\n if (mode.scope && typeof mode.scope === \"string\") {\n emitter.openNode(language.classNameAliases[mode.scope] || mode.scope);\n }\n if (mode.beginScope) {\n // beginScope just wraps the begin match itself in a scope\n if (mode.beginScope._wrap) {\n emitKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap);\n modeBuffer = \"\";\n } else if (mode.beginScope._multi) {\n // at this point modeBuffer should just be the match\n emitMultiClass(mode.beginScope, match);\n modeBuffer = \"\";\n }\n }\n\n top = Object.create(mode, { parent: { value: top } });\n return top;\n }\n\n /**\n * @param {CompiledMode } mode - the mode to potentially end\n * @param {RegExpMatchArray} match - the latest match\n * @param {string} matchPlusRemainder - match plus remainder of content\n * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode\n */\n function endOfMode(mode, match, matchPlusRemainder) {\n let matched = startsWith(mode.endRe, matchPlusRemainder);\n\n if (matched) {\n if (mode[\"on:end\"]) {\n const resp = new Response(mode);\n mode[\"on:end\"](match, resp);\n if (resp.isMatchIgnored) matched = false;\n }\n\n if (matched) {\n while (mode.endsParent && mode.parent) {\n mode = mode.parent;\n }\n return mode;\n }\n }\n // even if on:end fires an `ignore` it's still possible\n // that we might trigger the end node because of a parent mode\n if (mode.endsWithParent) {\n return endOfMode(mode.parent, match, matchPlusRemainder);\n }\n }\n\n /**\n * Handle matching but then ignoring a sequence of text\n *\n * @param {string} lexeme - string containing full match text\n */\n function doIgnore(lexeme) {\n if (top.matcher.regexIndex === 0) {\n // no more regexes to potentially match here, so we move the cursor forward one\n // space\n modeBuffer += lexeme[0];\n return 1;\n } else {\n // no need to move the cursor, we still have additional regexes to try and\n // match at this very spot\n resumeScanAtSamePosition = true;\n return 0;\n }\n }\n\n /**\n * Handle the start of a new potential mode match\n *\n * @param {EnhancedMatch} match - the current match\n * @returns {number} how far to advance the parse cursor\n */\n function doBeginMatch(match) {\n const lexeme = match[0];\n const newMode = match.rule;\n\n const resp = new Response(newMode);\n // first internal before callbacks, then the public ones\n const beforeCallbacks = [newMode.__beforeBegin, newMode[\"on:begin\"]];\n for (const cb of beforeCallbacks) {\n if (!cb) continue;\n cb(match, resp);\n if (resp.isMatchIgnored) return doIgnore(lexeme);\n }\n\n if (newMode.skip) {\n modeBuffer += lexeme;\n } else {\n if (newMode.excludeBegin) {\n modeBuffer += lexeme;\n }\n processBuffer();\n if (!newMode.returnBegin && !newMode.excludeBegin) {\n modeBuffer = lexeme;\n }\n }\n startNewMode(newMode, match);\n return newMode.returnBegin ? 0 : lexeme.length;\n }\n\n /**\n * Handle the potential end of mode\n *\n * @param {RegExpMatchArray} match - the current match\n */\n function doEndMatch(match) {\n const lexeme = match[0];\n const matchPlusRemainder = codeToHighlight.substring(match.index);\n\n const endMode = endOfMode(top, match, matchPlusRemainder);\n if (!endMode) { return NO_MATCH; }\n\n const origin = top;\n if (top.endScope && top.endScope._wrap) {\n processBuffer();\n emitKeyword(lexeme, top.endScope._wrap);\n } else if (top.endScope && top.endScope._multi) {\n processBuffer();\n emitMultiClass(top.endScope, match);\n } else if (origin.skip) {\n modeBuffer += lexeme;\n } else {\n if (!(origin.returnEnd || origin.excludeEnd)) {\n modeBuffer += lexeme;\n }\n processBuffer();\n if (origin.excludeEnd) {\n modeBuffer = lexeme;\n }\n }\n do {\n if (top.scope) {\n emitter.closeNode();\n }\n if (!top.skip && !top.subLanguage) {\n relevance += top.relevance;\n }\n top = top.parent;\n } while (top !== endMode.parent);\n if (endMode.starts) {\n startNewMode(endMode.starts, match);\n }\n return origin.returnEnd ? 0 : lexeme.length;\n }\n\n function processContinuations() {\n const list = [];\n for (let current = top; current !== language; current = current.parent) {\n if (current.scope) {\n list.unshift(current.scope);\n }\n }\n list.forEach(item => emitter.openNode(item));\n }\n\n /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */\n let lastMatch = {};\n\n /**\n * Process an individual match\n *\n * @param {string} textBeforeMatch - text preceding the match (since the last match)\n * @param {EnhancedMatch} [match] - the match itself\n */\n function processLexeme(textBeforeMatch, match) {\n const lexeme = match && match[0];\n\n // add non-matched text to the current mode buffer\n modeBuffer += textBeforeMatch;\n\n if (lexeme == null) {\n processBuffer();\n return 0;\n }\n\n // we've found a 0 width match and we're stuck, so we need to advance\n // this happens when we have badly behaved rules that have optional matchers to the degree that\n // sometimes they can end up matching nothing at all\n // Ref: https://github.com/highlightjs/highlight.js/issues/2140\n if (lastMatch.type === \"begin\" && match.type === \"end\" && lastMatch.index === match.index && lexeme === \"\") {\n // spit the \"skipped\" character that our regex choked on back into the output sequence\n modeBuffer += codeToHighlight.slice(match.index, match.index + 1);\n if (!SAFE_MODE) {\n /** @type {AnnotatedError} */\n const err = new Error(`0 width match regex (${languageName})`);\n err.languageName = languageName;\n err.badRule = lastMatch.rule;\n throw err;\n }\n return 1;\n }\n lastMatch = match;\n\n if (match.type === \"begin\") {\n return doBeginMatch(match);\n } else if (match.type === \"illegal\" && !ignoreIllegals) {\n // illegal match, we do not continue processing\n /** @type {AnnotatedError} */\n const err = new Error('Illegal lexeme \"' + lexeme + '\" for mode \"' + (top.scope || '<unnamed>') + '\"');\n err.mode = top;\n throw err;\n } else if (match.type === \"end\") {\n const processed = doEndMatch(match);\n if (processed !== NO_MATCH) {\n return processed;\n }\n }\n\n // edge case for when illegal matches $ (end of line) which is technically\n // a 0 width match but not a begin/end match so it's not caught by the\n // first handler (when ignoreIllegals is true)\n if (match.type === \"illegal\" && lexeme === \"\") {\n // advance so we aren't stuck in an infinite loop\n modeBuffer += \"\\n\";\n return 1;\n }\n\n // infinite loops are BAD, this is a last ditch catch all. if we have a\n // decent number of iterations yet our index (cursor position in our\n // parsing) still 3x behind our index then something is very wrong\n // so we bail\n if (iterations > 100000 && iterations > match.index * 3) {\n const err = new Error('potential infinite loop, way more iterations than matches');\n throw err;\n }\n\n /*\n Why might be find ourselves here? An potential end match that was\n triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH.\n (this could be because a callback requests the match be ignored, etc)\n\n This causes no real harm other than stopping a few times too many.\n */\n\n modeBuffer += lexeme;\n return lexeme.length;\n }\n\n const language = getLanguage(languageName);\n if (!language) {\n error(LANGUAGE_NOT_FOUND.replace(\"{}\", languageName));\n throw new Error('Unknown language: \"' + languageName + '\"');\n }\n\n const md = compileLanguage(language);\n let result = '';\n /** @type {CompiledMode} */\n let top = continuation || md;\n /** @type Record<string,CompiledMode> */\n const continuations = {}; // keep continuations for sub-languages\n const emitter = new options.__emitter(options);\n processContinuations();\n let modeBuffer = '';\n let relevance = 0;\n let index = 0;\n let iterations = 0;\n let resumeScanAtSamePosition = false;\n\n try {\n if (!language.__emitTokens) {\n top.matcher.considerAll();\n\n for (;;) {\n iterations++;\n if (resumeScanAtSamePosition) {\n // only regexes not matched previously will now be\n // considered for a potential match\n resumeScanAtSamePosition = false;\n } else {\n top.matcher.considerAll();\n }\n top.matcher.lastIndex = index;\n\n const match = top.matcher.exec(codeToHighlight);\n // console.log(\"match\", match[0], match.rule && match.rule.begin)\n\n if (!match) break;\n\n const beforeMatch = codeToHighlight.substring(index, match.index);\n const processedCount = processLexeme(beforeMatch, match);\n index = match.index + processedCount;\n }\n processLexeme(codeToHighlight.substring(index));\n } else {\n language.__emitTokens(codeToHighlight, emitter);\n }\n\n emitter.finalize();\n result = emitter.toHTML();\n\n return {\n language: languageName,\n value: result,\n relevance,\n illegal: false,\n _emitter: emitter,\n _top: top\n };\n } catch (err) {\n if (err.message && err.message.includes('Illegal')) {\n return {\n language: languageName,\n value: escape(codeToHighlight),\n illegal: true,\n relevance: 0,\n _illegalBy: {\n message: err.message,\n index,\n context: codeToHighlight.slice(index - 100, index + 100),\n mode: err.mode,\n resultSoFar: result\n },\n _emitter: emitter\n };\n } else if (SAFE_MODE) {\n return {\n language: languageName,\n value: escape(codeToHighlight),\n illegal: false,\n relevance: 0,\n errorRaised: err,\n _emitter: emitter,\n _top: top\n };\n } else {\n throw err;\n }\n }\n }\n\n /**\n * returns a valid highlight result, without actually doing any actual work,\n * auto highlight starts with this and it's possible for small snippets that\n * auto-detection may not find a better match\n * @param {string} code\n * @returns {HighlightResult}\n */\n function justTextHighlightResult(code) {\n const result = {\n value: escape(code),\n illegal: false,\n relevance: 0,\n _top: PLAINTEXT_LANGUAGE,\n _emitter: new options.__emitter(options)\n };\n result._emitter.addText(code);\n return result;\n }\n\n /**\n Highlighting with language detection. Accepts a string with the code to\n highlight. Returns an object with the following properties:\n\n - language (detected language)\n - relevance (int)\n - value (an HTML string with highlighting markup)\n - secondBest (object with the same structure for second-best heuristically\n detected language, may be absent)\n\n @param {string} code\n @param {Array<string>} [languageSubset]\n @returns {AutoHighlightResult}\n */\n function highlightAuto(code, languageSubset) {\n languageSubset = languageSubset || options.languages || Object.keys(languages);\n const plaintext = justTextHighlightResult(code);\n\n const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name =>\n _highlight(name, code, false)\n );\n results.unshift(plaintext); // plaintext is always an option\n\n const sorted = results.sort((a, b) => {\n // sort base on relevance\n if (a.relevance !== b.relevance) return b.relevance - a.relevance;\n\n // always award the tie to the base language\n // ie if C++ and Arduino are tied, it's more likely to be C++\n if (a.language && b.language) {\n if (getLanguage(a.language).supersetOf === b.language) {\n return 1;\n } else if (getLanguage(b.language).supersetOf === a.language) {\n return -1;\n }\n }\n\n // otherwise say they are equal, which has the effect of sorting on\n // relevance while preserving the original ordering - which is how ties\n // have historically been settled, ie the language that comes first always\n // wins in the case of a tie\n return 0;\n });\n\n const [best, secondBest] = sorted;\n\n /** @type {AutoHighlightResult} */\n const result = best;\n result.secondBest = secondBest;\n\n return result;\n }\n\n /**\n * Builds new class name for block given the language name\n *\n * @param {HTMLElement} element\n * @param {string} [currentLang]\n * @param {string} [resultLang]\n */\n function updateClassName(element, currentLang, resultLang) {\n const language = (currentLang && aliases[currentLang]) || resultLang;\n\n element.classList.add(\"hljs\");\n element.classList.add(`language-${language}`);\n }\n\n /**\n * Applies highlighting to a DOM node containing code.\n *\n * @param {HighlightedHTMLElement} element - the HTML element to highlight\n */\n function highlightElement(element) {\n /** @type HTMLElement */\n let node = null;\n const language = blockLanguage(element);\n\n if (shouldNotHighlight(language)) return;\n\n fire(\"before:highlightElement\",\n { el: element, language });\n\n if (element.dataset.highlighted) {\n console.log(\"Element previously highlighted. To highlight again, first unset `dataset.highlighted`.\", element);\n return;\n }\n\n // we should be all text, no child nodes (unescaped HTML) - this is possibly\n // an HTML injection attack - it's likely too late if this is already in\n // production (the code has likely already done its damage by the time\n // we're seeing it)... but we yell loudly about this so that hopefully it's\n // more likely to be caught in development before making it to production\n if (element.children.length > 0) {\n if (!options.ignoreUnescapedHTML) {\n console.warn(\"One of your code blocks includes unescaped HTML. This is a potentially serious security risk.\");\n console.warn(\"https://github.com/highlightjs/highlight.js/wiki/security\");\n console.warn(\"The element with unescaped HTML:\");\n console.warn(element);\n }\n if (options.throwUnescapedHTML) {\n const err = new HTMLInjectionError(\n \"One of your code blocks includes unescaped HTML.\",\n element.innerHTML\n );\n throw err;\n }\n }\n\n node = element;\n const text = node.textContent;\n const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);\n\n element.innerHTML = result.value;\n element.dataset.highlighted = \"yes\";\n updateClassName(element, language, result.language);\n element.result = {\n language: result.language,\n // TODO: remove with version 11.0\n re: result.relevance,\n relevance: result.relevance\n };\n if (result.secondBest) {\n element.secondBest = {\n language: result.secondBest.language,\n relevance: result.secondBest.relevance\n };\n }\n\n fire(\"after:highlightElement\", { el: element, result, text });\n }\n\n /**\n * Updates highlight.js global options with the passed options\n *\n * @param {Partial<HLJSOptions>} userOptions\n */\n function configure(userOptions) {\n options = inherit(options, userOptions);\n }\n\n // TODO: remove v12, deprecated\n const initHighlighting = () => {\n highlightAll();\n deprecated(\"10.6.0\", \"initHighlighting() deprecated. Use highlightAll() now.\");\n };\n\n // TODO: remove v12, deprecated\n function initHighlightingOnLoad() {\n highlightAll();\n deprecated(\"10.6.0\", \"initHighlightingOnLoad() deprecated. Use highlightAll() now.\");\n }\n\n let wantsHighlight = false;\n\n /**\n * auto-highlights all pre>code elements on the page\n */\n function highlightAll() {\n function boot() {\n // if a highlight was requested before DOM was loaded, do now\n highlightAll();\n }\n\n // if we are called too early in the loading process\n if (document.readyState === \"loading\") {\n // make sure the event listener is only added once\n if (!wantsHighlight) {\n window.addEventListener('DOMContentLoaded', boot, false);\n }\n wantsHighlight = true;\n return;\n }\n\n const blocks = document.querySelectorAll(options.cssSelector);\n blocks.forEach(highlightElement);\n }\n\n /**\n * Register a language grammar module\n *\n * @param {string} languageName\n * @param {LanguageFn} languageDefinition\n */\n function registerLanguage(languageName, languageDefinition) {\n let lang = null;\n try {\n lang = languageDefinition(hljs);\n } catch (error$1) {\n error(\"Language definition for '{}' could not be registered.\".replace(\"{}\", languageName));\n // hard or soft error\n if (!SAFE_MODE) { throw error$1; } else { error(error$1); }\n // languages that have serious errors are replaced with essentially a\n // \"plaintext\" stand-in so that the code blocks will still get normal\n // css classes applied to them - and one bad language won't break the\n // entire highlighter\n lang = PLAINTEXT_LANGUAGE;\n }\n // give it a temporary name if it doesn't have one in the meta-data\n if (!lang.name) lang.name = languageName;\n languages[languageName] = lang;\n lang.rawDefinition = languageDefinition.bind(null, hljs);\n\n if (lang.aliases) {\n registerAliases(lang.aliases, { languageName });\n }\n }\n\n /**\n * Remove a language grammar module\n *\n * @param {string} languageName\n */\n function unregisterLanguage(languageName) {\n delete languages[languageName];\n for (const alias of Object.keys(aliases)) {\n if (aliases[alias] === languageName) {\n delete aliases[alias];\n }\n }\n }\n\n /**\n * @returns {string[]} List of language internal names\n */\n function listLanguages() {\n return Object.keys(languages);\n }\n\n /**\n * @param {string} name - name of the language to retrieve\n * @returns {Language | undefined}\n */\n function getLanguage(name) {\n name = (name || '').toLowerCase();\n return languages[name] || languages[aliases[name]];\n }\n\n /**\n *\n * @param {string|string[]} aliasList - single alias or list of aliases\n * @param {{languageName: string}} opts\n */\n function registerAliases(aliasList, { languageName }) {\n if (typeof aliasList === 'string') {\n aliasList = [aliasList];\n }\n aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; });\n }\n\n /**\n * Determines if a given language has auto-detection enabled\n * @param {string} name - name of the language\n */\n function autoDetection(name) {\n const lang = getLanguage(name);\n return lang && !lang.disableAutodetect;\n }\n\n /**\n * Upgrades the old highlightBlock plugins to the new\n * highlightElement API\n * @param {HLJSPlugin} plugin\n */\n function upgradePluginAPI(plugin) {\n // TODO: remove with v12\n if (plugin[\"before:highlightBlock\"] && !plugin[\"before:highlightElement\"]) {\n plugin[\"before:highlightElement\"] = (data) => {\n plugin[\"before:highlightBlock\"](\n Object.assign({ block: data.el }, data)\n );\n };\n }\n if (plugin[\"after:highlightBlock\"] && !plugin[\"after:highlightElement\"]) {\n plugin[\"after:highlightElement\"] = (data) => {\n plugin[\"after:highlightBlock\"](\n Object.assign({ block: data.el }, data)\n );\n };\n }\n }\n\n /**\n * @param {HLJSPlugin} plugin\n */\n function addPlugin(plugin) {\n upgradePluginAPI(plugin);\n plugins.push(plugin);\n }\n\n /**\n * @param {HLJSPlugin} plugin\n */\n function removePlugin(plugin) {\n const index = plugins.indexOf(plugin);\n if (index !== -1) {\n plugins.splice(index, 1);\n }\n }\n\n /**\n *\n * @param {PluginEvent} event\n * @param {any} args\n */\n function fire(event, args) {\n const cb = event;\n plugins.forEach(function(plugin) {\n if (plugin[cb]) {\n plugin[cb](args);\n }\n });\n }\n\n /**\n * DEPRECATED\n * @param {HighlightedHTMLElement} el\n */\n function deprecateHighlightBlock(el) {\n deprecated(\"10.7.0\", \"highlightBlock will be removed entirely in v12.0\");\n deprecated(\"10.7.0\", \"Please use highlightElement now.\");\n\n return highlightElement(el);\n }\n\n /* Interface definition */\n Object.assign(hljs, {\n highlight,\n highlightAuto,\n highlightAll,\n highlightElement,\n // TODO: Remove with v12 API\n highlightBlock: deprecateHighlightBlock,\n configure,\n initHighlighting,\n initHighlightingOnLoad,\n registerLanguage,\n unregisterLanguage,\n listLanguages,\n getLanguage,\n registerAliases,\n autoDetection,\n inherit,\n addPlugin,\n removePlugin\n });\n\n hljs.debugMode = function() { SAFE_MODE = false; };\n hljs.safeMode = function() { SAFE_MODE = true; };\n hljs.versionString = version;\n\n hljs.regex = {\n concat: concat,\n lookahead: lookahead,\n either: either,\n optional: optional,\n anyNumberOfTimes: anyNumberOfTimes\n };\n\n for (const key in MODES) {\n // @ts-ignore\n if (typeof MODES[key] === \"object\") {\n // @ts-ignore\n deepFreeze(MODES[key]);\n }\n }\n\n // merge all the modes/regexes into our main object\n Object.assign(hljs, MODES);\n\n return hljs;\n};\n\n// Other names for the variable may break build script\nconst highlight = HLJS({});\n\n// returns a new instance of the highlighter to be used for extensions\n// check https://github.com/wooorm/lowlight/issues/47\nhighlight.newInstance = () => HLJS({});\n\nmodule.exports = highlight;\nhighlight.HighlightJS = highlight;\nhighlight.default = highlight;\n","/*\nLanguage: JSON\nDescription: JSON (JavaScript Object Notation) is a lightweight data-interchange format.\nAuthor: Ivan Sagalaev <maniac@softwaremaniacs.org>\nWebsite: http://www.json.org\nCategory: common, protocols, web\n*/\n\nfunction json(hljs) {\n const ATTRIBUTE = {\n className: 'attr',\n begin: /\"(\\\\.|[^\\\\\"\\r\\n])*\"(?=\\s*:)/,\n relevance: 1.01\n };\n const PUNCTUATION = {\n match: /[{}[\\],:]/,\n className: \"punctuation\",\n relevance: 0\n };\n const LITERALS = [\n \"true\",\n \"false\",\n \"null\"\n ];\n // NOTE: normally we would rely on `keywords` for this but using a mode here allows us\n // - to use the very tight `illegal: \\S` rule later to flag any other character\n // - as illegal indicating that despite looking like JSON we do not truly have\n // - JSON and thus improve false-positively greatly since JSON will try and claim\n // - all sorts of JSON looking stuff\n const LITERALS_MODE = {\n scope: \"literal\",\n beginKeywords: LITERALS.join(\" \"),\n };\n\n return {\n name: 'JSON',\n aliases: ['jsonc'],\n keywords:{\n literal: LITERALS,\n },\n contains: [\n ATTRIBUTE,\n PUNCTUATION,\n hljs.QUOTE_STRING_MODE,\n LITERALS_MODE,\n hljs.C_NUMBER_MODE,\n hljs.C_LINE_COMMENT_MODE,\n hljs.C_BLOCK_COMMENT_MODE\n ],\n illegal: '\\\\S'\n };\n}\n\nexport { json as default };\n","/*\n Language: SQL\n Website: https://en.wikipedia.org/wiki/SQL\n Category: common, database\n */\n\n/*\n\nGoals:\n\nSQL is intended to highlight basic/common SQL keywords and expressions\n\n- If pretty much every single SQL server includes supports, then it's a canidate.\n- It is NOT intended to include tons of vendor specific keywords (Oracle, MySQL,\n PostgreSQL) although the list of data types is purposely a bit more expansive.\n- For more specific SQL grammars please see:\n - PostgreSQL and PL/pgSQL - core\n - T-SQL - https://github.com/highlightjs/highlightjs-tsql\n - sql_more (core)\n\n */\n\nfunction sql(hljs) {\n const regex = hljs.regex;\n const COMMENT_MODE = hljs.COMMENT('--', '$');\n const STRING = {\n scope: 'string',\n variants: [\n {\n begin: /'/,\n end: /'/,\n contains: [ { match: /''/ } ]\n }\n ]\n };\n const QUOTED_IDENTIFIER = {\n begin: /\"/,\n end: /\"/,\n contains: [ { match: /\"\"/ } ]\n };\n\n const LITERALS = [\n \"true\",\n \"false\",\n // Not sure it's correct to call NULL literal, and clauses like IS [NOT] NULL look strange that way.\n // \"null\",\n \"unknown\"\n ];\n\n const MULTI_WORD_TYPES = [\n \"double precision\",\n \"large object\",\n \"with timezone\",\n \"without timezone\"\n ];\n\n const TYPES = [\n 'bigint',\n 'binary',\n 'blob',\n 'boolean',\n 'char',\n 'character',\n 'clob',\n 'date',\n 'dec',\n 'decfloat',\n 'decimal',\n 'float',\n 'int',\n 'integer',\n 'interval',\n 'nchar',\n 'nclob',\n 'national',\n 'numeric',\n 'real',\n 'row',\n 'smallint',\n 'time',\n 'timestamp',\n 'varchar',\n 'varying', // modifier (character varying)\n 'varbinary'\n ];\n\n const NON_RESERVED_WORDS = [\n \"add\",\n \"asc\",\n \"collation\",\n \"desc\",\n \"final\",\n \"first\",\n \"last\",\n \"view\"\n ];\n\n // https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#reserved-word\n const RESERVED_WORDS = [\n \"abs\",\n \"acos\",\n \"all\",\n \"allocate\",\n \"alter\",\n \"and\",\n \"any\",\n \"are\",\n \"array\",\n \"array_agg\",\n \"array_max_cardinality\",\n \"as\",\n \"asensitive\",\n \"asin\",\n \"asymmetric\",\n \"at\",\n \"atan\",\n \"atomic\",\n \"authorization\",\n \"avg\",\n \"begin\",\n \"begin_frame\",\n \"begin_partition\",\n \"between\",\n \"bigint\",\n \"binary\",\n \"blob\",\n \"boolean\",\n \"both\",\n \"by\",\n \"call\",\n \"called\",\n \"cardinality\",\n \"cascaded\",\n \"case\",\n \"cast\",\n \"ceil\",\n \"ceiling\",\n \"char\",\n \"char_length\",\n \"character\",\n \"character_length\",\n \"check\",\n \"classifier\",\n \"clob\",\n \"close\",\n \"coalesce\",\n \"collate\",\n \"collect\",\n \"column\",\n \"commit\",\n \"condition\",\n \"connect\",\n \"constraint\",\n \"contains\",\n \"convert\",\n \"copy\",\n \"corr\",\n \"corresponding\",\n \"cos\",\n \"cosh\",\n \"count\",\n \"covar_pop\",\n \"covar_samp\",\n \"create\",\n \"cross\",\n \"cube\",\n \"cume_dist\",\n \"current\",\n \"current_catalog\",\n \"current_date\",\n \"current_default_transform_group\",\n \"current_path\",\n \"current_role\",\n \"current_row\",\n \"current_schema\",\n \"current_time\",\n \"current_timestamp\",\n \"current_path\",\n \"current_role\",\n \"current_transform_group_for_type\",\n \"current_user\",\n \"cursor\",\n \"cycle\",\n \"date\",\n \"day\",\n \"deallocate\",\n \"dec\",\n \"decimal\",\n \"decfloat\",\n \"declare\",\n \"default\",\n \"define\",\n \"delete\",\n \"dense_rank\",\n \"deref\",\n \"describe\",\n \"deterministic\",\n \"disconnect\",\n \"distinct\",\n \"double\",\n \"drop\",\n \"dynamic\",\n \"each\",\n \"element\",\n \"else\",\n \"empty\",\n \"end\",\n \"end_frame\",\n \"end_partition\",\n \"end-exec\",\n \"equals\",\n \"escape\",\n \"every\",\n \"except\",\n \"exec\",\n \"execute\",\n \"exists\",\n \"exp\",\n \"external\",\n \"extract\",\n \"false\",\n \"fetch\",\n \"filter\",\n \"first_value\",\n \"float\",\n \"floor\",\n \"for\",\n \"foreign\",\n \"frame_row\",\n \"free\",\n \"from\",\n \"full\",\n \"function\",\n \"fusion\",\n \"get\",\n \"global\",\n \"grant\",\n \"group\",\n \"grouping\",\n \"groups\",\n \"having\",\n \"hold\",\n \"hour\",\n \"identity\",\n \"in\",\n \"indicator\",\n \"initial\",\n \"inner\",\n \"inout\",\n \"insensitive\",\n \"insert\",\n \"int\",\n \"integer\",\n \"intersect\",\n \"intersection\",\n \"interval\",\n \"into\",\n \"is\",\n \"join\",\n \"json_array\",\n \"json_arrayagg\",\n \"json_exists\",\n \"json_object\",\n \"json_objectagg\",\n \"json_query\",\n \"json_table\",\n \"json_table_primitive\",\n \"json_value\",\n \"lag\",\n \"language\",\n \"large\",\n \"last_value\",\n \"lateral\",\n \"lead\",\n \"leading\",\n \"left\",\n \"like\",\n \"like_regex\",\n \"listagg\",\n \"ln\",\n \"local\",\n \"localtime\",\n \"localtimestamp\",\n \"log\",\n \"log10\",\n \"lower\",\n \"match\",\n \"match_number\",\n \"match_recognize\",\n \"matches\",\n \"max\",\n \"member\",\n \"merge\",\n \"method\",\n \"min\",\n \"minute\",\n \"mod\",\n \"modifies\",\n \"module\",\n \"month\",\n \"multiset\",\n \"national\",\n \"natural\",\n \"nchar\",\n \"nclob\",\n \"new\",\n \"no\",\n \"none\",\n \"normalize\",\n \"not\",\n \"nth_value\",\n \"ntile\",\n \"null\",\n \"nullif\",\n \"numeric\",\n \"octet_length\",\n \"occurrences_regex\",\n \"of\",\n \"offset\",\n \"old\",\n \"omit\",\n \"on\",\n \"one\",\n \"only\",\n \"open\",\n \"or\",\n \"order\",\n \"out\",\n \"outer\",\n \"over\",\n \"overlaps\",\n \"overlay\",\n \"parameter\",\n \"partition\",\n \"pattern\",\n \"per\",\n \"percent\",\n \"percent_rank\",\n \"percentile_cont\",\n \"percentile_disc\",\n \"period\",\n \"portion\",\n \"position\",\n \"position_regex\",\n \"power\",\n \"precedes\",\n \"precision\",\n \"prepare\",\n \"primary\",\n \"procedure\",\n \"ptf\",\n \"range\",\n \"rank\",\n \"reads\",\n \"real\",\n \"recursive\",\n \"ref\",\n \"references\",\n \"referencing\",\n \"regr_avgx\",\n \"regr_avgy\",\n \"regr_count\",\n \"regr_intercept\",\n \"regr_r2\",\n \"regr_slope\",\n \"regr_sxx\",\n \"regr_sxy\",\n \"regr_syy\",\n \"release\",\n \"result\",\n \"return\",\n \"returns\",\n \"revoke\",\n \"right\",\n \"rollback\",\n \"rollup\",\n \"row\",\n \"row_number\",\n \"rows\",\n \"running\",\n \"savepoint\",\n \"scope\",\n \"scroll\",\n \"search\",\n \"second\",\n \"seek\",\n \"select\",\n \"sensitive\",\n \"session_user\",\n \"set\",\n \"show\",\n \"similar\",\n \"sin\",\n \"sinh\",\n \"skip\",\n \"smallint\",\n \"some\",\n \"specific\",\n \"specifictype\",\n \"sql\",\n \"sqlexception\",\n \"sqlstate\",\n \"sqlwarning\",\n \"sqrt\",\n \"start\",\n \"static\",\n \"stddev_pop\",\n \"stddev_samp\",\n \"submultiset\",\n \"subset\",\n \"substring\",\n \"substring_regex\",\n \"succeeds\",\n \"sum\",\n \"symmetric\",\n \"system\",\n \"system_time\",\n \"system_user\",\n \"table\",\n \"tablesample\",\n \"tan\",\n \"tanh\",\n \"then\",\n \"time\",\n \"timestamp\",\n \"timezone_hour\",\n \"timezone_minute\",\n \"to\",\n \"trailing\",\n \"translate\",\n \"translate_regex\",\n \"translation\",\n \"treat\",\n \"trigger\",\n \"trim\",\n \"trim_array\",\n \"true\",\n \"truncate\",\n \"uescape\",\n \"union\",\n \"unique\",\n \"unknown\",\n \"unnest\",\n \"update\",\n \"upper\",\n \"user\",\n \"using\",\n \"value\",\n \"values\",\n \"value_of\",\n \"var_pop\",\n \"var_samp\",\n \"varbinary\",\n \"varchar\",\n \"varying\",\n \"versioning\",\n \"when\",\n \"whenever\",\n \"where\",\n \"width_bucket\",\n \"window\",\n \"with\",\n \"within\",\n \"without\",\n \"year\",\n ];\n\n // these are reserved words we have identified to be functions\n // and should only be highlighted in a dispatch-like context\n // ie, array_agg(...), etc.\n const RESERVED_FUNCTIONS = [\n \"abs\",\n \"acos\",\n \"array_agg\",\n \"asin\",\n \"atan\",\n \"avg\",\n \"cast\",\n \"ceil\",\n \"ceiling\",\n \"coalesce\",\n \"corr\",\n \"cos\",\n \"cosh\",\n \"count\",\n \"covar_pop\",\n \"covar_samp\",\n \"cume_dist\",\n \"dense_rank\",\n \"deref\",\n \"element\",\n \"exp\",\n \"extract\",\n \"first_value\",\n \"floor\",\n \"json_array\",\n \"json_arrayagg\",\n \"json_exists\",\n \"json_object\",\n \"json_objectagg\",\n \"json_query\",\n \"json_table\",\n \"json_table_primitive\",\n \"json_value\",\n \"lag\",\n \"last_value\",\n \"lead\",\n \"listagg\",\n \"ln\",\n \"log\",\n \"log10\",\n \"lower\",\n \"max\",\n \"min\",\n \"mod\",\n \"nth_value\",\n \"ntile\",\n \"nullif\",\n \"percent_rank\",\n \"percentile_cont\",\n \"percentile_disc\",\n \"position\",\n \"position_regex\",\n \"power\",\n \"rank\",\n \"regr_avgx\",\n \"regr_avgy\",\n \"regr_count\",\n \"regr_intercept\",\n \"regr_r2\",\n \"regr_slope\",\n \"regr_sxx\",\n \"regr_sxy\",\n \"regr_syy\",\n \"row_number\",\n \"sin\",\n \"sinh\",\n \"sqrt\",\n \"stddev_pop\",\n \"stddev_samp\",\n \"substring\",\n \"substring_regex\",\n \"sum\",\n \"tan\",\n \"tanh\",\n \"translate\",\n \"translate_regex\",\n \"treat\",\n \"trim\",\n \"trim_array\",\n \"unnest\",\n \"upper\",\n \"value_of\",\n \"var_pop\",\n \"var_samp\",\n \"width_bucket\",\n ];\n\n // these functions can\n const POSSIBLE_WITHOUT_PARENS = [\n \"current_catalog\",\n \"current_date\",\n \"current_default_transform_group\",\n \"current_path\",\n \"current_role\",\n \"current_schema\",\n \"current_transform_group_for_type\",\n \"current_user\",\n \"session_user\",\n \"system_time\",\n \"system_user\",\n \"current_time\",\n \"localtime\",\n \"current_timestamp\",\n \"localtimestamp\"\n ];\n\n // those exist to boost relevance making these very\n // \"SQL like\" keyword combos worth +1 extra relevance\n const COMBOS = [\n \"create table\",\n \"insert into\",\n \"primary key\",\n \"foreign key\",\n \"not null\",\n \"alter table\",\n \"add constraint\",\n \"grouping sets\",\n \"on overflow\",\n \"character set\",\n \"respect nulls\",\n \"ignore nulls\",\n \"nulls first\",\n \"nulls last\",\n \"depth first\",\n \"breadth first\"\n ];\n\n const FUNCTIONS = RESERVED_FUNCTIONS;\n\n const KEYWORDS = [\n ...RESERVED_WORDS,\n ...NON_RESERVED_WORDS\n ].filter((keyword) => {\n return !RESERVED_FUNCTIONS.includes(keyword);\n });\n\n const VARIABLE = {\n scope: \"variable\",\n match: /@[a-z0-9][a-z0-9_]*/,\n };\n\n const OPERATOR = {\n scope: \"operator\",\n match: /[-+*/=%^~]|&&?|\\|\\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,\n relevance: 0,\n };\n\n const FUNCTION_CALL = {\n match: regex.concat(/\\b/, regex.either(...FUNCTIONS), /\\s*\\(/),\n relevance: 0,\n keywords: { built_in: FUNCTIONS }\n };\n\n // turns a multi-word keyword combo into a regex that doesn't\n // care about extra whitespace etc.\n // input: \"START QUERY\"\n // output: /\\bSTART\\s+QUERY\\b/\n function kws_to_regex(list) {\n return regex.concat(\n /\\b/,\n regex.either(...list.map((kw) => {\n return kw.replace(/\\s+/, \"\\\\s+\")\n })),\n /\\b/\n )\n }\n\n const MULTI_WORD_KEYWORDS = {\n scope: \"keyword\",\n match: kws_to_regex(COMBOS),\n relevance: 0,\n };\n\n // keywords with less than 3 letters are reduced in relevancy\n function reduceRelevancy(list, {\n exceptions, when\n } = {}) {\n const qualifyFn = when;\n exceptions = exceptions || [];\n return list.map((item) => {\n if (item.match(/\\|\\d+$/) || exceptions.includes(item)) {\n return item;\n } else if (qualifyFn(item)) {\n return `${item}|0`;\n } else {\n return item;\n }\n });\n }\n\n return {\n name: 'SQL',\n case_insensitive: true,\n // does not include {} or HTML tags `</`\n illegal: /[{}]|<\\//,\n keywords: {\n $pattern: /\\b[\\w\\.]+/,\n keyword:\n reduceRelevancy(KEYWORDS, { when: (x) => x.length < 3 }),\n literal: LITERALS,\n type: TYPES,\n built_in: POSSIBLE_WITHOUT_PARENS\n },\n contains: [\n {\n scope: \"type\",\n match: kws_to_regex(MULTI_WORD_TYPES)\n },\n MULTI_WORD_KEYWORDS,\n FUNCTION_CALL,\n VARIABLE,\n STRING,\n QUOTED_IDENTIFIER,\n hljs.C_NUMBER_MODE,\n hljs.C_BLOCK_COMMENT_MODE,\n COMMENT_MODE,\n OPERATOR\n ]\n };\n}\n\nexport { sql as default };\n","/**\n * CodeBlock Component\n * Displays syntax-highlighted code with copy-to-clipboard functionality\n */\n\nimport React, { useState, useEffect, useRef } from 'react'\nimport hljs from 'highlight.js/lib/core'\nimport json from 'highlight.js/lib/languages/json'\nimport sql from 'highlight.js/lib/languages/sql'\nimport { getIcon } from '../../icons'\nimport './CodeBlock.css'\n\n// Register languages\nhljs.registerLanguage('json', json)\nhljs.registerLanguage('sql', sql)\n\ninterface CodeBlockProps {\n code: string\n language: 'json' | 'sql'\n title?: string\n maxHeight?: string\n height?: string\n className?: string\n}\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({\n code,\n language,\n title,\n maxHeight = '16rem',\n height,\n className = ''\n}) => {\n const [copied, setCopied] = useState(false)\n const codeRef = useRef<HTMLElement>(null)\n const CopyIcon = getIcon('copy')\n const CheckIcon = getIcon('check')\n\n // Apply syntax highlighting\n useEffect(() => {\n if (codeRef.current && code) {\n codeRef.current.innerHTML = hljs.highlight(code, { language }).value\n }\n }, [code, language])\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n // Fallback for older browsers\n const textArea = document.createElement('textarea')\n textArea.value = code\n textArea.style.position = 'fixed'\n textArea.style.left = '-999999px'\n document.body.appendChild(textArea)\n textArea.select()\n document.execCommand('copy')\n document.body.removeChild(textArea)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n return (\n <div className={`relative ${className}`}>\n {/* Header with title and copy button */}\n <div className=\"flex items-center justify-between mb-2\">\n {title && (\n <h4 className=\"text-sm font-semibold text-dc-text\">{title}</h4>\n )}\n <button\n onClick={handleCopy}\n className=\"ml-auto px-2 py-1 text-xs rounded hover:bg-dc-surface-secondary border border-dc-border transition-colors flex items-center gap-1.5\"\n title={copied ? 'Copied!' : 'Copy to clipboard'}\n >\n {copied ? (\n <>\n <CheckIcon className=\"w-3.5 h-3.5 text-dc-success\" />\n <span className=\"text-dc-success\">Copied</span>\n </>\n ) : (\n <>\n <CopyIcon className=\"w-3.5 h-3.5 text-dc-text-secondary\" />\n <span className=\"text-dc-text-secondary\">Copy</span>\n </>\n )}\n </button>\n </div>\n\n {/* Code block with syntax highlighting */}\n <div\n className=\"bg-dc-surface-secondary border border-dc-border rounded overflow-auto\"\n style={height ? { height, minHeight: height, maxHeight: height } : { maxHeight }}\n >\n <pre className=\"p-3 text-xs m-0\">\n <code\n ref={codeRef}\n className={`hljs language-${language}`}\n >\n {code}\n </code>\n </pre>\n </div>\n </div>\n )\n}\n\nexport default CodeBlock\n","/**\n * Color Palette Selector Component\n * Allows users to select from predefined color palettes for their dashboard\n */\n\nimport { useState, useRef, useEffect } from 'react'\nimport { COLOR_PALETTES, getColorPalette } from '../utils/colorPalettes'\nimport { getIcon } from '../icons'\n\nconst ChevronDownIcon = getIcon('chevronDown')\n\ninterface ColorPaletteSelectorProps {\n currentPalette?: string\n onPaletteChange: (paletteName: string) => void\n className?: string\n}\n\nexport default function ColorPaletteSelector({\n currentPalette = 'default',\n onPaletteChange,\n className = ''\n}: ColorPaletteSelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const dropdownRef = useRef<HTMLDivElement>(null)\n \n const currentPaletteObj = getColorPalette(currentPalette)\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n const handlePaletteSelect = (paletteName: string) => {\n onPaletteChange(paletteName)\n setIsOpen(false)\n }\n\n return (\n <div className={`relative ${className}`} ref={dropdownRef}>\n {/* Trigger Button */}\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 bg-dc-surface border border-dc-border rounded-md shadow-xs text-sm font-medium text-dc-text-secondary hover:bg-dc-surface-hover focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-dc-accent\"\n >\n {/* Current Palette Preview - Hidden on mobile */}\n <div className=\"hidden md:flex items-center gap-1.5\">\n <div className=\"flex gap-0.5\">\n {currentPaletteObj.colors.slice(0, 4).map((color, index) => (\n <div\n key={index}\n className=\"w-3 h-3 rounded-xs border border-dc-border\"\n style={{ backgroundColor: color }}\n title={`Series Color ${index + 1}`}\n />\n ))}\n </div>\n <span className=\"text-xs text-dc-text-secondary\">|</span>\n <div className=\"flex gap-0.5\">\n {currentPaletteObj.gradient.slice(0, 3).map((color, index) => (\n <div\n key={index}\n className=\"w-2 h-3 border-r first:rounded-l-sm last:rounded-r-sm last:border-r-0\"\n style={{\n backgroundColor: color,\n borderColor: 'var(--dc-border)'\n }}\n title={`Gradient Color ${index + 1}`}\n />\n ))}\n </div>\n </div>\n <span>{currentPaletteObj.label}</span>\n <ChevronDownIcon \n className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`} \n />\n </button>\n\n {/* Dropdown Menu - Responsive width */}\n {isOpen && (\n <div className=\"absolute top-full left-0 mt-1 w-72 md:w-80 lg:w-96 bg-dc-surface border border-dc-border rounded-md shadow-lg z-50 max-h-80 overflow-y-auto\">\n <div className=\"py-1\">\n {COLOR_PALETTES.slice().sort((a, b) => a.label.localeCompare(b.label)).map((palette) => (\n <button\n key={palette.name}\n type=\"button\"\n onClick={() => handlePaletteSelect(palette.name)}\n className={`w-full px-3 py-2 text-left text-sm hover:bg-dc-surface-hover focus:outline-hidden focus:bg-dc-surface-hover ${\n palette.name === currentPalette ? 'bg-dc-surface-secondary' : 'text-dc-text-secondary'\n }`}\n style={palette.name === currentPalette ? { color: 'var(--dc-primary)' } : undefined}\n >\n <div className=\"flex items-center gap-3\">\n {/* Palette Preview - Hidden on mobile */}\n <div className=\"hidden md:flex items-center gap-2\">\n {/* Series Colors */}\n <div className=\"flex gap-0.5\">\n {palette.colors.slice(0, 6).map((color, index) => (\n <div\n key={`series-${index}`}\n className=\"w-3 h-3 rounded-xs border border-dc-border\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n\n {/* Separator */}\n <div className=\"w-px h-4 bg-dc-border\" />\n \n {/* Gradient Colors */}\n <div className=\"flex\">\n {palette.gradient.map((color, index) => (\n <div\n key={`gradient-${index}`}\n className=\"w-2 h-4 first:rounded-l-sm last:rounded-r-sm\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n </div>\n \n {/* Palette Name */}\n <span className=\"font-medium\">{palette.label}</span>\n \n {/* Current Indicator */}\n {palette.name === currentPalette && (\n <div className=\"ml-auto\">\n <div className=\"w-2 h-2 rounded-full\" style={{ backgroundColor: 'var(--dc-primary)' }}></div>\n </div>\n )}\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n )\n}","/**\n * AnalysisResultsPanel Component\n *\n * Displays query execution results with chart and table views.\n * Used in the left panel of AnalysisBuilder.\n */\n\nimport { useState, useEffect, useMemo, memo } from 'react'\nimport type { AnalysisResultsPanelProps } from './types'\nimport { LazyChart, isValidChartType } from '../../charts/ChartLoader'\nimport { getIcon } from '../../icons'\nimport { QueryAnalysisPanel, CodeBlock } from '../../shared'\nimport ColorPaletteSelector from '../ColorPaletteSelector'\n\n/**\n * AnalysisResultsPanel displays query results with chart/table toggle.\n *\n * Features:\n * - Chart visualization with LazyChart\n * - Table view with DataTable\n * - Loading, error, and empty states\n * - Stale results indicator\n * - Display limit control for tables\n */\nconst AnalysisResultsPanel = memo(function AnalysisResultsPanel({\n executionStatus,\n executionResults,\n executionError,\n totalRowCount,\n resultsStale = false,\n chartType = 'line',\n chartConfig = {},\n displayConfig = {},\n colorPalette,\n currentPaletteName,\n onColorPaletteChange,\n allQueries,\n funnelExecutedQueries,\n activeView = 'chart',\n onActiveViewChange,\n displayLimit = 100,\n onDisplayLimitChange,\n hasMetrics = false,\n // Debug props - per-query for multi-query mode\n debugDataPerQuery = [],\n // Share props\n onShareClick,\n canShare = false,\n shareButtonState = 'idle',\n // Refresh functionality\n onRefreshClick,\n canRefresh = false,\n isRefreshing = false,\n // Clear functionality\n onClearClick,\n canClear = false,\n // AI functionality\n enableAI = false,\n isAIOpen = false,\n onAIToggle,\n // Multi-query props\n queryCount = 1,\n perQueryResults,\n activeTableIndex = 0,\n onActiveTableChange\n}: AnalysisResultsPanelProps) {\n // Debug view toggle state\n const [showDebug, setShowDebug] = useState(false)\n // Active debug query tab (independent of main query tabs)\n const [activeDebugIndex, setActiveDebugIndex] = useState(0)\n\n // Clamp activeDebugIndex when queries are removed\n useEffect(() => {\n if (debugDataPerQuery.length > 0 && activeDebugIndex >= debugDataPerQuery.length) {\n setActiveDebugIndex(debugDataPerQuery.length - 1)\n }\n }, [debugDataPerQuery.length, activeDebugIndex])\n\n // Get current debug data based on active index\n const currentDebugData = debugDataPerQuery[activeDebugIndex] || {\n sql: null,\n analysis: null,\n loading: false,\n error: null\n }\n const debugSql = currentDebugData.sql\n const debugAnalysis = currentDebugData.analysis\n const debugLoading = currentDebugData.loading\n const debugError = currentDebugData.error\n // Get the query for the active debug tab\n // In funnel mode, prefer showing the executed queries which include:\n // - The binding key dimension (auto-added)\n // - The IN filter for steps 2+ (with values from previous step)\n const debugQuery = funnelExecutedQueries?.[activeDebugIndex] ?? allQueries?.[activeDebugIndex] ?? null\n\n // Determine if we're showing funnel executed queries (for visual indicator)\n const isShowingFunnelQuery = Boolean(funnelExecutedQueries?.length && funnelExecutedQueries[activeDebugIndex])\n // Force table view when no metrics are selected\n useEffect(() => {\n if (!hasMetrics && activeView === 'chart') {\n onActiveViewChange('table')\n }\n }, [hasMetrics, activeView, onActiveViewChange])\n\n // Create a combined query object for the chart (includes measures from ALL queries)\n const combinedQueryForChart = useMemo(() => {\n if (!allQueries || allQueries.length === 0) return undefined\n if (allQueries.length === 1) return allQueries[0]\n\n // Combine measures from all queries, dimensions are shared (from Q1)\n const allMeasures = allQueries.flatMap(q => q?.measures || [])\n return {\n ...allQueries[0],\n measures: allMeasures\n }\n }, [allQueries])\n\n // Icons\n const SuccessIcon = getIcon('success')\n const ErrorIcon = getIcon('error')\n const WarningIcon = getIcon('warning')\n const TableIcon = getIcon('table')\n const ChartIcon = getIcon('measure')\n const CodeIcon = getIcon('codeBracket')\n const ShareIcon = getIcon('share')\n const CheckIcon = getIcon('check')\n const TrashIcon = getIcon('delete')\n const SparklesIcon = getIcon('sparkles')\n const RefreshIcon = getIcon('arrowPath')\n\n // Loading state - initial load\n const renderLoading = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Executing Query...\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Running your query against the cube API\n </div>\n </div>\n </div>\n )\n\n // Error state - no previous results\n const renderError = () => (\n <div className=\"h-full flex flex-col\">\n {renderHeader()}\n <div className=\"flex-1 flex items-center justify-center p-4\">\n {showDebug ? (\n <div className=\"w-full h-full overflow-auto\">\n {renderDebug()}\n </div>\n ) : (\n <div className=\"text-center max-w-md\">\n <ErrorIcon className=\"w-12 h-12 mx-auto text-dc-error mb-4\" />\n <div className=\"text-sm font-semibold text-dc-text mb-2\">\n Query Execution Failed\n </div>\n <div className=\"text-sm text-dc-text-secondary mb-4\">\n There was an error executing your query. Please check the query and try again.\n </div>\n {executionError && (\n <div className=\"bg-dc-danger-bg border border-dc-error rounded-lg p-3 text-left\">\n <div className=\"text-xs font-mono text-dc-error break-words\">\n {executionError}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )\n\n // Check if any query has content (pending execution)\n const hasQueryContent = !!(allQueries?.some(q =>\n (q?.measures && q.measures.length > 0) ||\n (q?.dimensions && q.dimensions.length > 0) ||\n (q?.timeDimensions && q.timeDimensions.length > 0)\n ))\n\n // Waiting state - query built but not yet executed (debounce period)\n const renderWaiting = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Preparing Query...\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Your query will execute shortly\n </div>\n </div>\n </div>\n )\n\n // Empty state - no query built yet\n const renderEmpty = () => (\n <div className=\"h-full flex items-center justify-center pt-6\">\n <div className=\"text-center mb-16\">\n <ChartIcon className=\"w-12 h-12 mx-auto text-dc-text-muted mb-3\" />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n No Results Yet\n </div>\n <div className=\"text-xs text-dc-text-muted mb-4\">\n Add metrics or breakdowns from the panel on the right to see results\n </div>\n {/* Prominent AI button when enabled */}\n {enableAI && onAIToggle && (\n <button\n onClick={onAIToggle}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-dc-accent hover:bg-dc-accent rounded-lg transition-colors shadow-sm\"\n >\n <SparklesIcon className=\"w-4 h-4\" />\n Analyse with AI\n </button>\n )}\n </div>\n </div>\n )\n\n // No data returned state\n const renderNoData = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <SuccessIcon className=\"w-12 h-12 mx-auto text-dc-success mb-3\" />\n <div className=\"text-sm font-semibold text-dc-text mb-1\">\n Query Successful\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n No data returned from the query\n </div>\n </div>\n </div>\n )\n\n // Render chart\n const renderChart = () => {\n if (!executionResults || executionResults.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <ChartIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No data to display</div>\n <div className=\"text-xs\">Run a query to see chart visualization</div>\n </div>\n </div>\n )\n }\n\n if (!isValidChartType(chartType)) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <WarningIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">Unsupported chart type</div>\n <div className=\"text-xs\">{chartType}</div>\n </div>\n </div>\n )\n }\n\n return (\n <LazyChart\n chartType={chartType}\n data={executionResults}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n queryObject={combinedQueryForChart}\n height=\"100%\"\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full\" />\n </div>\n }\n />\n )\n }\n\n // Render debug view\n const renderDebug = () => (\n <div className=\"p-4 space-y-4 overflow-auto h-full\">\n {/* Query tabs for multi-query mode */}\n {debugDataPerQuery.length > 1 && (\n <div className=\"flex items-center gap-1 mb-4\">\n <span className=\"text-xs font-medium text-dc-text-muted mr-2\">Query:</span>\n <div className=\"flex border border-dc-border rounded-md overflow-hidden\">\n {debugDataPerQuery.map((data, idx) => (\n <button\n key={idx}\n onClick={() => setActiveDebugIndex(idx)}\n className={`px-3 py-1 text-xs font-medium transition-colors border-r last:border-r-0 border-dc-border ${\n activeDebugIndex === idx\n ? 'bg-dc-accent text-white'\n : 'bg-dc-bg text-dc-text-secondary hover:bg-dc-bg-secondary'\n }`}\n >\n Q{idx + 1}\n {data.loading && (\n <span className=\"ml-1 opacity-70\">•</span>\n )}\n {data.error && (\n <span className=\"ml-1 text-dc-error\">!</span>\n )}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Execution Error Banner (if any) */}\n {executionError && (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg border border-dc-error dark:border-dc-error rounded p-3\">\n <h4 className=\"text-sm font-semibold text-dc-error dark:text-dc-error mb-1\">\n Execution Error\n </h4>\n <p className=\"text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )}\n\n {/* Query Analysis - full width (at top for visibility) */}\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Query Analysis</h4>\n {debugLoading ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n Loading...\n </div>\n ) : debugAnalysis ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <QueryAnalysisPanel analysis={debugAnalysis} />\n </div>\n ) : (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n {debugError ? 'Analysis unavailable due to error' : 'Add metrics to see analysis'}\n </div>\n )}\n </div>\n\n {/* Cube Query and SQL Query in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {/* Cube Query */}\n <div>\n {debugQuery ? (\n <>\n <CodeBlock\n code={JSON.stringify(debugQuery, null, 2)}\n language=\"json\"\n title={isShowingFunnelQuery ? \"Executed Query (with funnel filters)\" : \"Cube Query\"}\n height=\"16rem\"\n />\n {isShowingFunnelQuery && activeDebugIndex > 0 && (\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"text-dc-accent\">ℹ</span> This query includes an IN filter with binding key values from the previous step\n </div>\n )}\n </>\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Cube Query</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm h-64 overflow-auto\">\n No query\n </div>\n </>\n )}\n </div>\n\n {/* Generated SQL */}\n <div>\n {debugLoading ? (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Generated SQL</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm h-64 overflow-auto\">\n Loading...\n </div>\n </>\n ) : debugError ? (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Generated SQL</h4>\n <div className=\"text-dc-error text-sm bg-dc-danger-bg dark:bg-dc-danger-bg p-3 rounded border border-dc-error dark:border-dc-error h-64 overflow-auto\">\n {debugError.message}\n </div>\n </>\n ) : debugSql ? (\n <CodeBlock\n code={\n debugSql.sql +\n (debugSql.params && debugSql.params.length > 0\n ? '\\n\\n-- Parameters:\\n' + JSON.stringify(debugSql.params, null, 2)\n : '')\n }\n language=\"sql\"\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Generated SQL</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm h-64 overflow-auto\">\n Add metrics to generate SQL\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Chart Config & Display Config in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {/* Chart Config */}\n <div>\n <CodeBlock\n code={JSON.stringify(chartConfig, null, 2)}\n language=\"json\"\n title=\"Chart Config\"\n height=\"16rem\"\n />\n </div>\n\n {/* Display Config */}\n <div>\n <CodeBlock\n code={JSON.stringify(displayConfig, null, 2)}\n language=\"json\"\n title=\"Display Config\"\n height=\"16rem\"\n />\n </div>\n </div>\n\n {/* Server Response - full width */}\n <div>\n {executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title={`Server Response (${executionResults.length} rows)`}\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n </div>\n )\n\n // Determine if we're in multi-query mode\n const isMultiQuery = queryCount > 1 && perQueryResults && perQueryResults.length > 1\n\n // Render table - uses per-query results in multi-query mode\n const renderTable = (tableIndex?: number) => {\n // In multi-query mode, use specific query's results and query object\n // tableIndex: undefined = single query, -1 = merged view, 0+ = per-query view\n let tableData: any[] | null = null\n let tableQuery = allQueries?.[0] // Default to first query\n\n if (isMultiQuery && tableIndex !== undefined && tableIndex >= 0 && perQueryResults) {\n // Per-query table view\n tableData = perQueryResults[tableIndex] || null\n tableQuery = allQueries?.[tableIndex]\n } else {\n // Merged view (tableIndex === -1) or single query mode\n tableData = executionResults\n // For merged view, use combined query\n if (isMultiQuery) {\n tableQuery = combinedQueryForChart\n }\n }\n\n if (!tableData || tableData.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <TableIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No data to display</div>\n <div className=\"text-xs\">Run a query to see table data</div>\n </div>\n </div>\n )\n }\n\n // Apply display limit\n const limitedData = tableData.slice(0, displayLimit)\n\n return (\n <LazyChart\n chartType=\"table\"\n data={limitedData}\n colorPalette={colorPalette}\n queryObject={tableQuery}\n height=\"100%\"\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full\" />\n </div>\n }\n />\n )\n }\n\n // Overlay spinner for refreshing\n const renderOverlaySpinner = () => (\n <div className=\"absolute inset-0 flex items-center justify-center bg-dc-surface bg-opacity-75 z-10\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-10 w-10 border-b-2 mx-auto mb-2\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-xs text-dc-text-secondary\">Refreshing results...</div>\n </div>\n </div>\n )\n\n // Render header - shown whenever we have query content\n const renderHeader = () => {\n const hasResults = executionResults && executionResults.length > 0\n\n return (\n <div className=\"px-4 py-2 border-b border-dc-border bg-dc-surface-secondary flex-shrink-0\">\n <div className=\"flex items-center justify-between\">\n {/* Left side: Status and row count */}\n <div className=\"flex items-center\">\n {executionStatus === 'refreshing' ? (\n <div\n className=\"w-4 h-4 mr-2 rounded-full border-b-2 animate-spin\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n ) : hasResults ? (\n <SuccessIcon className=\"w-4 h-4 text-dc-success mr-2\" />\n ) : executionStatus === 'error' ? (\n <ErrorIcon className=\"w-4 h-4 text-dc-error mr-2\" />\n ) : (\n <WarningIcon className=\"w-4 h-4 text-dc-text-muted mr-2\" />\n )}\n <span className=\"text-sm text-dc-text-secondary\">\n {hasResults ? (\n <>\n {executionResults.length} row{executionResults.length !== 1 ? 's' : ''}\n {totalRowCount !== null && totalRowCount > executionResults.length && (\n <span className=\"text-dc-text-muted\"> of {totalRowCount.toLocaleString()}</span>\n )}\n {resultsStale && (\n <span className=\"text-dc-warning ml-2\">• Results may be outdated</span>\n )}\n </>\n ) : executionStatus === 'error' ? (\n 'Query failed'\n ) : executionStatus === 'loading' ? (\n 'Executing...'\n ) : (\n 'No results'\n )}\n </span>\n </div>\n\n {/* Right side: Display limit (table only) and Debug toggle */}\n <div className=\"flex items-center gap-2\">\n {/* Display Limit (only for table view) */}\n {hasResults && activeView === 'table' && !showDebug && onDisplayLimitChange && (\n <select\n value={displayLimit}\n onChange={(e) => onDisplayLimitChange(Number(e.target.value))}\n className=\"text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n >\n <option value={50}>50 rows</option>\n <option value={100}>100 rows</option>\n <option value={250}>250 rows</option>\n <option value={500}>500 rows</option>\n </select>\n )}\n\n {/* AI Button - positioned before palette selector */}\n {enableAI && onAIToggle && (\n <button\n onClick={onAIToggle}\n className={`flex items-center gap-1 px-2 py-1.5 text-xs font-medium rounded transition-colors ${\n isAIOpen\n ? 'text-white bg-dc-accent border border-dc-accent'\n : 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n }`}\n title={isAIOpen ? 'Close AI assistant' : 'Analyse with AI'}\n >\n <SparklesIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Analyse with AI</span>\n </button>\n )}\n\n {/* Color Palette Selector (only when callback is provided, i.e., standalone mode) */}\n {onColorPaletteChange && hasResults && (\n <ColorPaletteSelector\n currentPalette={currentPaletteName || 'default'}\n onPaletteChange={onColorPaletteChange}\n />\n )}\n\n {/* Share Button */}\n {onShareClick && (\n <button\n onClick={onShareClick}\n className={`flex items-center gap-1 px-2 py-1.5 text-xs font-medium rounded transition-colors ${\n shareButtonState === 'idle' && canShare\n ? 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n : shareButtonState !== 'idle'\n ? 'text-dc-success dark:text-dc-success bg-dc-success-bg dark:bg-dc-success-bg border border-dc-success dark:border-dc-success'\n : 'text-dc-text-muted bg-dc-surface-secondary border border-dc-border cursor-not-allowed'\n }`}\n title={shareButtonState === 'idle' ? 'Share this analysis' : 'Link copied!'}\n disabled={!canShare || shareButtonState !== 'idle'}\n >\n {shareButtonState === 'idle' ? (\n <>\n <ShareIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Share</span>\n </>\n ) : shareButtonState === 'copied' ? (\n <>\n <CheckIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Copied!</span>\n </>\n ) : (\n <>\n <CheckIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Copied!</span>\n <span className=\"hidden lg:inline text-[10px] opacity-75\">(no chart)</span>\n </>\n )}\n </button>\n )}\n\n {/* Refresh Button */}\n {onRefreshClick && canRefresh && (\n <button\n onClick={onRefreshClick}\n disabled={isRefreshing}\n className={`flex items-center gap-1 px-2 py-1.5 text-xs font-medium rounded transition-colors ${\n isRefreshing\n ? 'text-dc-text-muted bg-dc-surface-secondary border border-dc-border cursor-wait'\n : 'text-dc-accent bg-dc-accent-bg border border-dc-accent hover:bg-dc-accent-bg'\n }`}\n title={isRefreshing ? 'Refreshing...' : 'Refresh data'}\n >\n <RefreshIcon className={`w-3 h-3 ${isRefreshing ? 'animate-spin' : ''}`} />\n <span className=\"hidden sm:inline\">{isRefreshing ? 'Refreshing' : 'Refresh'}</span>\n </button>\n )}\n\n {/* Clear Button */}\n {onClearClick && canClear && (\n <button\n onClick={onClearClick}\n className=\"flex items-center gap-1 px-2 py-1.5 text-xs font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover border border-dc-border rounded transition-colors\"\n title=\"Clear all query data\"\n >\n <TrashIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Clear</span>\n </button>\n )}\n\n {/* Debug Toggle Button */}\n <button\n onClick={() => setShowDebug(!showDebug)}\n className={`p-1.5 rounded transition-colors relative ${\n showDebug\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:text-dc-text hover:bg-dc-surface-hover'\n }`}\n title={showDebug ? 'Hide debug info' : 'Show debug info'}\n >\n <CodeIcon className=\"w-4 h-4\" />\n {/* Error indicator dot - show if ANY query has an error */}\n {(executionError || debugDataPerQuery.some(d => d.error)) && !showDebug && (\n <span className=\"absolute -top-0.5 -right-0.5 w-2 h-2 bg-dc-danger-bg0 rounded-full\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Performance Warning */}\n {hasResults && totalRowCount !== null && totalRowCount > 1000 && (\n <div className=\"mt-2 bg-dc-warning-bg border border-dc-warning rounded-lg p-2 flex items-start\">\n <WarningIcon className=\"w-4 h-4 text-dc-warning mr-2 shrink-0 mt-0.5\" />\n <div className=\"text-xs text-dc-warning\">\n <span className=\"font-semibold\">Large dataset:</span> {totalRowCount.toLocaleString()} rows.\n Consider adding filters to improve performance.\n </div>\n </div>\n )}\n </div>\n )\n }\n\n // Success state with data\n const renderSuccess = () => {\n const hasResults = executionResults && executionResults.length > 0\n\n if (!hasResults) {\n return (\n <div className=\"h-full flex flex-col\">\n {renderHeader()}\n <div className=\"flex-1 min-h-0 relative overflow-auto\">\n {showDebug ? renderDebug() : renderNoData()}\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"h-full flex flex-col\">\n {renderHeader()}\n\n {/* Results Content */}\n <div className=\"flex-1 min-h-0 relative overflow-auto\">\n {showDebug ? (\n renderDebug()\n ) : activeView === 'chart' ? (\n <div className=\"p-4 h-full\">{renderChart()}</div>\n ) : isMultiQuery ? (\n <div className=\"h-full\" key={`table-${activeTableIndex}`}>{renderTable(activeTableIndex)}</div>\n ) : (\n <div className=\"h-full\" key=\"table-single\">{renderTable()}</div>\n )}\n </div>\n\n {/* View Toggle - Below content, centered */}\n {!showDebug && (\n <div className=\"px-4 py-3 border-t border-dc-border bg-dc-surface flex justify-center flex-shrink-0\">\n <div className=\"flex items-center bg-dc-surface-secondary border border-dc-border rounded-md overflow-hidden\">\n {/* Chart button */}\n <button\n onClick={() => hasMetrics && onActiveViewChange('chart')}\n disabled={!hasMetrics}\n className={`flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'chart'\n ? 'bg-dc-primary text-white'\n : !hasMetrics\n ? 'text-dc-text-disabled bg-dc-surface-tertiary cursor-not-allowed'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title={hasMetrics ? 'Chart view' : 'Add metrics to enable chart view'}\n >\n <ChartIcon className=\"w-4 h-4\" />\n Chart\n </button>\n\n {/* Table buttons - show multiple when in multi-query mode */}\n {isMultiQuery ? (\n <>\n {/* Per-query table buttons */}\n {Array.from({ length: queryCount }).map((_, index) => (\n <button\n key={`table-${index}`}\n onClick={() => {\n onActiveViewChange('table')\n onActiveTableChange?.(index)\n }}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table' && activeTableIndex === index\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title={`Table Q${index + 1}`}\n >\n <TableIcon className=\"w-4 h-4\" />\n Q{index + 1}\n </button>\n ))}\n {/* Merged table button */}\n <button\n onClick={() => {\n onActiveViewChange('table')\n onActiveTableChange?.(-1) // -1 = merged view\n }}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table' && activeTableIndex === -1\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title=\"Merged table view\"\n >\n <TableIcon className=\"w-4 h-4\" />\n Merged\n </button>\n </>\n ) : (\n <button\n onClick={() => onActiveViewChange('table')}\n className={`flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table'\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title=\"Table view\"\n >\n <TableIcon className=\"w-4 h-4\" />\n Table\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n\n // Determine what to render based on execution status\n const hasResults = executionResults !== null\n\n // Don't show results if we're in idle state with no query content (cleared state)\n const shouldShowResults = hasResults && (executionStatus !== 'idle' || hasQueryContent)\n\n return (\n <div className=\"h-full min-h-[400px] flex flex-col bg-dc-surface relative\">\n {/* Main content */}\n {executionStatus === 'idle' && !hasQueryContent && renderEmpty()}\n {executionStatus === 'idle' && hasQueryContent && !hasResults && renderWaiting()}\n {executionStatus === 'loading' && !hasResults && renderLoading()}\n {executionStatus === 'error' && !hasResults && renderError()}\n {(executionStatus === 'success' || shouldShowResults) && renderSuccess()}\n\n {/* Overlay states */}\n {(executionStatus === 'loading' || executionStatus === 'refreshing') && hasResults && renderOverlaySpinner()}\n </div>\n )\n})\n\nexport default AnalysisResultsPanel\n","/**\n * MetricItemCard Component\n *\n * Displays a single metric item with remove button.\n */\n\nimport { memo } from 'react'\nimport type { MetricItemCardProps } from './types'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\n\n/**\n * MetricItemCard displays a selected metric with:\n * - Field icon based on measure type\n * - Field title or full name\n * - Sort toggle button (visible on hover, or always visible when sorted)\n * - Remove button (visible on hover)\n * - Drag handle for reordering\n */\nconst MetricItemCard = memo(function MetricItemCard({\n metric,\n fieldMeta,\n onRemove,\n sortDirection,\n sortPriority,\n onToggleSort,\n index,\n isDragging,\n onDragStart,\n onDragEnd\n}: MetricItemCardProps) {\n const CloseIcon = getIcon('close')\n const ChevronUpIcon = getIcon('chevronUp')\n const ChevronDownIcon = getIcon('chevronDown')\n const ChevronUpDownIcon = getIcon('chevronUpDown')\n\n // Get the appropriate icon based on measure type\n const measureType = fieldMeta?.type || 'count'\n const MeasureIcon = getMeasureTypeIcon(measureType) || getIcon('measure')\n\n // Get display title - prefer shortTitle, then title, then field name\n const displayTitle = fieldMeta?.shortTitle || fieldMeta?.title || metric.field.split('.').pop() || metric.field\n\n // Get the cube name from the field\n const cubeName = metric.field.split('.')[0]\n\n // Get sort icon based on direction\n const getSortIcon = () => {\n switch (sortDirection) {\n case 'asc':\n return ChevronUpIcon ? <ChevronUpIcon className=\"w-4 h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"w-4 h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"w-4 h-4\" /> : '⇅'\n }\n }\n\n // Get sort tooltip\n const getSortTooltip = () => {\n switch (sortDirection) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n }\n\n // Check if drag/drop is enabled\n const isDraggable = typeof index === 'number' && onDragStart && onDragEnd\n\n return (\n <div\n className={`flex items-center gap-2 p-2 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-all duration-150 ${\n isDraggable ? 'cursor-grab active:cursor-grabbing' : ''\n } ${isDragging ? 'opacity-30' : ''}`}\n draggable={isDraggable ? true : undefined}\n onDragStart={isDraggable ? (e) => onDragStart(e, index) : undefined}\n onDragEnd={isDraggable ? onDragEnd : undefined}\n >\n {/* Icon - colored background matching field selector */}\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-measure text-dc-measure-text flex-shrink-0\">\n {MeasureIcon && <MeasureIcon className=\"w-4 h-4\" />}\n </span>\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={metric.field}>\n {displayTitle}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`p-1 transition-opacity flex-shrink-0 flex items-center gap-0.5 ${\n sortDirection\n ? 'opacity-100 text-dc-primary'\n : 'opacity-100 sm:opacity-0 sm:group-hover:opacity-100 text-dc-text-muted hover:text-dc-primary'\n }`}\n title={getSortTooltip()}\n >\n {getSortIcon()}\n {sortDirection && sortPriority && (\n <span className=\"text-xs font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title=\"Remove metric\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )\n})\n\nexport default MetricItemCard\n","/**\n * MetricsSection Component\n *\n * Displays the Metrics section in the query panel with expandable list of metrics.\n */\n\nimport { useMemo, useState, useCallback, useRef, memo, DragEvent } from 'react'\nimport type { MetricsSectionProps } from './types'\nimport type { MetaField } from '../../shared/types'\nimport MetricItemCard from './MetricItemCard'\nimport SectionHeading from './SectionHeading'\nimport { getIcon } from '../../icons'\n\n// Get icon once at module level to avoid recreating\nconst AddIcon = getIcon('add')\n\n/**\n * Find field metadata by field name\n */\nfunction findFieldMeta(fieldName: string, schema: MetricsSectionProps['schema']): MetaField | null {\n if (!schema?.cubes) return null\n\n const [cubeName] = fieldName.split('.')\n const cube = schema.cubes.find((c) => c.name === cubeName)\n if (!cube) return null\n\n return cube.measures?.find((m) => m.name === fieldName) || null\n}\n\n/**\n * Get next sort direction in the cycle: null -> asc -> desc -> null\n */\nfunction getNextSortDirection(current: 'asc' | 'desc' | null): 'asc' | 'desc' | null {\n switch (current) {\n case null:\n return 'asc'\n case 'asc':\n return 'desc'\n case 'desc':\n return null\n default:\n return 'asc'\n }\n}\n\n/**\n * MetricsSection displays a collapsible section with:\n * - Header with title and add button\n * - List of selected metrics (using MetricItemCard)\n * - Drag/drop reordering support\n */\nconst MetricsSection = memo(function MetricsSection({\n metrics,\n schema,\n onAdd,\n onRemove,\n order,\n onOrderChange,\n onReorder\n}: MetricsSectionProps) {\n\n // Drag/drop state\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null)\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null) // Index where item will be inserted\n\n // Use refs to track current values for use in drop handler (avoids stale closure issues)\n const draggedIndexRef = useRef<number | null>(null)\n const dropTargetIndexRef = useRef<number | null>(null)\n\n // Get the ordered keys to calculate priority\n const orderKeys = useMemo(() => order ? Object.keys(order) : [], [order])\n\n // Resolve field metadata for all metrics with sort info\n const metricsWithMeta = useMemo(() => {\n return metrics.map((metric, index) => {\n const sortDirection = order?.[metric.field] || null\n const sortPriority = sortDirection ? orderKeys.indexOf(metric.field) + 1 : undefined\n return {\n metric,\n fieldMeta: findFieldMeta(metric.field, schema),\n sortDirection,\n sortPriority,\n index\n }\n })\n }, [metrics, schema, order, orderKeys])\n\n // Track drag clone for cleanup\n const dragCloneRef = useRef<HTMLElement | null>(null)\n\n // Drag handlers\n const handleDragStart = useCallback((e: DragEvent, index: number) => {\n setDraggedIndex(index)\n draggedIndexRef.current = index\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', JSON.stringify({ type: 'metric', index, field: metrics[index].field }))\n\n // Create a semi-transparent, slightly tilted drag image\n const target = e.currentTarget as HTMLElement\n const clone = target.cloneNode(true) as HTMLElement\n clone.style.cssText = `\n position: absolute;\n top: -9999px;\n left: -9999px;\n width: ${target.offsetWidth}px;\n opacity: 0.7;\n transform: rotate(2deg);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n pointer-events: none;\n `\n document.body.appendChild(clone)\n dragCloneRef.current = clone\n\n // Calculate offset from click position\n const rect = target.getBoundingClientRect()\n const offsetX = e.clientX - rect.left\n const offsetY = e.clientY - rect.top\n e.dataTransfer.setDragImage(clone, offsetX, offsetY)\n }, [metrics])\n\n const handleDragEnd = useCallback(() => {\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n // Clean up the drag clone\n if (dragCloneRef.current) {\n document.body.removeChild(dragCloneRef.current)\n dragCloneRef.current = null\n }\n }, [])\n\n // Handle drag over an item - determine drop position based on mouse position\n const handleItemDragOver = useCallback((e: DragEvent, itemIndex: number) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Only process if we're dragging from this section\n const currentDraggedIndex = draggedIndexRef.current\n if (currentDraggedIndex === null) return\n\n // Determine if we're in the top or bottom half of the item\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseY = e.clientY - rect.top\n const isTopHalf = mouseY < rect.height / 2\n\n // Calculate target index based on position\n let targetIndex = isTopHalf ? itemIndex : itemIndex + 1\n\n // Don't set drop target if it would result in no movement\n if (targetIndex === currentDraggedIndex || targetIndex === currentDraggedIndex + 1) {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n } else {\n setDropTargetIndex(targetIndex)\n dropTargetIndexRef.current = targetIndex\n }\n }, [])\n\n // Handle drop on an item\n const handleItemDrop = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Use refs to get current values (avoids stale closure issues)\n const currentDraggedIndex = draggedIndexRef.current\n const currentDropTargetIndex = dropTargetIndexRef.current\n\n // Reset visual state immediately\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n\n // Validate and reorder - use refs directly, no dataTransfer parsing needed\n if (currentDraggedIndex === null || currentDropTargetIndex === null || !onReorder) {\n return\n }\n\n // Adjust target index when dragging down (after splice, indices shift)\n const adjustedTarget = currentDropTargetIndex > currentDraggedIndex\n ? currentDropTargetIndex - 1\n : currentDropTargetIndex\n\n if (adjustedTarget !== currentDraggedIndex) {\n onReorder(currentDraggedIndex, adjustedTarget)\n }\n }, [onReorder])\n\n // Clear drop target when leaving the section\n const handleSectionDragLeave = useCallback((e: DragEvent) => {\n const relatedTarget = e.relatedTarget as HTMLElement | null\n if (!relatedTarget || !e.currentTarget.contains(relatedTarget)) {\n setDropTargetIndex(null)\n }\n }, [])\n\n // Calculate if an item should be shifted to make room for the drop\n const getItemTransform = useCallback((itemIndex: number): string => {\n if (draggedIndex === null || dropTargetIndex === null) return ''\n\n // Gap size in pixels\n const gapSize = 40\n\n // If this is the dragged item, no transform needed (it's already faded)\n if (itemIndex === draggedIndex) return ''\n\n // Items at or after drop target need to shift down\n // But we need to account for the dragged item's position\n if (draggedIndex < dropTargetIndex) {\n // Dragging down: items between dragged+1 and dropTarget-1 shift up\n if (itemIndex > draggedIndex && itemIndex < dropTargetIndex) {\n return '' // No gap needed, item stays in place\n }\n // Item at dropTarget-1 position should show gap after it\n if (itemIndex === dropTargetIndex - 1) {\n return `translateY(-${gapSize / 2}px)` // Shift up to make room\n }\n if (itemIndex >= dropTargetIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down\n }\n } else {\n // Dragging up: items from dropTarget to draggedIndex-1 shift down\n if (itemIndex >= dropTargetIndex && itemIndex < draggedIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down to make room\n }\n }\n\n return ''\n }, [draggedIndex, dropTargetIndex])\n\n // Determine if gap indicator should show at a position\n const shouldShowGapIndicator = useCallback((itemIndex: number): boolean => {\n if (draggedIndex === null || dropTargetIndex === null) return false\n\n // Show indicator before the item that matches dropTargetIndex\n return itemIndex === dropTargetIndex\n }, [draggedIndex, dropTargetIndex])\n\n return (\n <div>\n {/* Section Header - entire row is clickable */}\n <button\n onClick={onAdd}\n className=\"flex items-center justify-between mb-3 w-full py-1 px-2 -ml-2 rounded-lg hover:bg-dc-primary/10 transition-colors group\"\n title=\"Add metric\"\n >\n <SectionHeading>Metrics</SectionHeading>\n <AddIcon className=\"w-5 h-5 text-dc-text-secondary group-hover:text-dc-primary transition-colors\" />\n </button>\n\n {/* Metrics List */}\n <div\n className=\"space-y-2\"\n onDragLeave={onReorder ? handleSectionDragLeave : undefined}\n onDragOver={onReorder ? (e) => e.preventDefault() : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {metricsWithMeta.map(({ metric, fieldMeta, sortDirection, sortPriority, index }) => {\n const transform = getItemTransform(index)\n const showGapBefore = shouldShowGapIndicator(index)\n\n return (\n <div\n key={metric.id}\n className=\"relative\"\n style={{\n transform,\n transition: draggedIndex !== null ? 'transform 0.15s ease-out' : 'none'\n }}\n onDragOver={onReorder ? (e) => handleItemDragOver(e, index) : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {/* Gap indicator line - shows where item will be inserted */}\n {showGapBefore && (\n <div className=\"absolute -top-5 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n )}\n <MetricItemCard\n metric={metric}\n fieldMeta={fieldMeta}\n onRemove={() => onRemove(metric.id)}\n sortDirection={sortDirection}\n sortPriority={sortPriority}\n onToggleSort={onOrderChange ? () => {\n const nextDirection = getNextSortDirection(sortDirection)\n onOrderChange(metric.field, nextDirection)\n } : undefined}\n index={index}\n isDragging={draggedIndex === index}\n onDragStart={onReorder ? handleDragStart : undefined}\n onDragEnd={onReorder ? handleDragEnd : undefined}\n />\n </div>\n )\n })}\n {/* Gap indicator after the last item - shows when dropping at end */}\n {onReorder && draggedIndex !== null && dropTargetIndex === metrics.length && (\n <div className=\"relative h-2\">\n <div className=\"absolute top-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n </div>\n )}\n {/* Handle drop at the end of the list */}\n {onReorder && metrics.length > 0 && draggedIndex !== null && (\n <div\n className=\"h-8\"\n onDragOver={(e) => {\n e.preventDefault()\n // Set drop target to end of list\n const lastIndex = metrics.length\n const currentDraggedIndex = draggedIndexRef.current\n if (dropTargetIndexRef.current !== lastIndex && currentDraggedIndex !== lastIndex - 1) {\n setDropTargetIndex(lastIndex)\n dropTargetIndexRef.current = lastIndex\n }\n }}\n onDrop={handleItemDrop}\n />\n )}\n </div>\n </div>\n )\n})\n\nexport default MetricsSection\n","/**\n * Type definitions for AnalysisBuilder components\n *\n * AnalysisBuilder is a redesigned query builder with:\n * - Results panel on the left (large)\n * - Query builder panel on the right\n * - Search-based field selection via modal\n * - Sections: Metrics (measures), Breakdown (dimensions), Filters\n */\n\nimport type { MouseEvent, DragEvent } from 'react'\nimport type {\n CubeQuery,\n Filter,\n ChartType,\n ChartAxisConfig,\n ChartDisplayConfig,\n MultiQueryConfig,\n QueryMergeStrategy,\n FunnelBindingKey,\n} from '../../types'\nimport type { ColorPalette } from '../../utils/colorPalettes'\nimport type { MetaResponse, MetaField, MetaCube, QueryAnalysis } from '../../shared/types'\nimport type { ChartAvailabilityMap } from '../../shared/chartDefaults'\nimport type { MultiQueryValidationResult } from '../../utils/multiQueryValidation'\n\n// Re-export types from shared for convenience\nexport type { MetaResponse, MetaField, MetaCube, QueryAnalysis }\n\n// ============================================================================\n// Metric and Breakdown Items\n// ============================================================================\n\n/**\n * A selected metric (measure) with a letter label (A, B, C, ...)\n */\nexport interface MetricItem {\n /** Unique identifier for this metric selection */\n id: string\n /** Full field name, e.g., \"Employees.count\" */\n field: string\n /** Display label (A, B, C, ...) */\n label: string\n}\n\n/**\n * A selected breakdown (dimension or time dimension)\n */\nexport interface BreakdownItem {\n /** Unique identifier for this breakdown selection */\n id: string\n /** Full field name, e.g., \"Employees.departmentName\" */\n field: string\n /** Granularity for time dimensions (day, week, month, quarter, year) */\n granularity?: string\n /** Whether this is a time dimension */\n isTimeDimension: boolean\n /** Enable period comparison for time dimensions (compares current filter period vs prior period) */\n enableComparison?: boolean\n}\n\n// ============================================================================\n// State Types\n// ============================================================================\n\n/** Validation status for query building */\nexport type ValidationStatus = 'idle' | 'validating' | 'valid' | 'invalid'\n\n/** Execution status for query results */\nexport type ExecutionStatus = 'idle' | 'loading' | 'refreshing' | 'success' | 'error'\n\n/**\n * Main state for the AnalysisBuilder component\n *\n * Note: Execution state (results, loading, error) is NOT stored here.\n * All server state is managed by TanStack Query. This state only contains\n * client-side configuration (metrics, breakdowns, filters, validation).\n */\nexport interface AnalysisBuilderState {\n /** Selected metrics (measures) */\n metrics: MetricItem[]\n /** Selected breakdowns (dimensions and time dimensions) */\n breakdowns: BreakdownItem[]\n /** Applied filters */\n filters: Filter[]\n /** Sort order for this query (field name -> 'asc' | 'desc') */\n order?: Record<string, 'asc' | 'desc'>\n\n // Validation state (client-side query validation)\n validationStatus: ValidationStatus\n validationError: string | null\n}\n\n/**\n * State for the AI query generation panel\n */\nexport interface AIState {\n /** Whether the AI panel is open */\n isOpen: boolean\n /** User's natural language prompt */\n userPrompt: string\n /** Whether a query is being generated */\n isGenerating: boolean\n /** Error message from generation */\n error: string | null\n /** Whether the AI has generated a query that's been loaded */\n hasGeneratedQuery: boolean\n /** Snapshot of state before AI was opened (for undo) */\n previousState: {\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n } | null\n}\n\n// ============================================================================\n// Field Search Modal Types\n// ============================================================================\n\n/**\n * Mode for the field search modal - determines which field types are shown\n */\nexport type FieldSearchMode = 'metrics' | 'breakdown' | 'filter'\n\n/**\n * Field type categorization\n */\nexport type FieldType = 'measure' | 'dimension' | 'timeDimension'\n\n/**\n * A field option for display in the search modal\n */\nexport interface FieldOption {\n /** Full field name, e.g., \"Employees.count\" */\n name: string\n /** Display title */\n title: string\n /** Short title for compact display */\n shortTitle: string\n /** Field type (count, sum, avg, string, time, number, etc.) */\n type: string\n /** Optional description */\n description?: string\n /** Parent cube name */\n cubeName: string\n /** Categorized field type */\n fieldType: FieldType\n}\n\n/**\n * Props for the FieldSearchModal component\n */\nexport interface FieldSearchModalProps {\n /** Whether the modal is open */\n isOpen: boolean\n /** Callback to close the modal */\n onClose: () => void\n /** Callback when a field is selected. keepOpen=true when shift-click multi-selecting */\n onSelect: (field: MetaField, fieldType: FieldType, cubeName: string, keepOpen?: boolean) => void\n /** Mode determines which field types to show */\n mode: FieldSearchMode\n /** Schema metadata */\n schema: MetaResponse | null\n /** Already selected field names (to show checkmarks) */\n selectedFields: string[]\n /** Recently used field names */\n recentFields?: string[]\n}\n\n/**\n * Props for the FieldSearchItem component\n */\nexport interface FieldSearchItemProps {\n /** Field data */\n field: FieldOption\n /** Whether this field is selected */\n isSelected: boolean\n /** Whether this field is focused/highlighted */\n isFocused: boolean\n /** Click handler - receives mouse event for shift-click multi-select */\n onClick: (e: MouseEvent) => void\n /** Mouse enter handler (for detail panel) */\n onMouseEnter: () => void\n}\n\n/**\n * Props for the FieldDetailPanel component\n */\nexport interface FieldDetailPanelProps {\n /** Field to display details for */\n field: FieldOption | null\n}\n\n// ============================================================================\n// Panel Component Props\n// ============================================================================\n\n/**\n * Tab options for the query panel\n */\nexport type QueryPanelTab = 'query' | 'chart' | 'display'\n\n/**\n * Props for the AnalysisQueryPanel component\n */\nexport interface AnalysisQueryPanelProps {\n /** Selected metrics */\n metrics: MetricItem[]\n /** Selected breakdowns */\n breakdowns: BreakdownItem[]\n /** Applied filters */\n filters: Filter[]\n /** Schema metadata */\n schema: MetaResponse | null\n\n /** Currently active tab */\n activeTab: QueryPanelTab\n /** Callback when active tab changes */\n onActiveTabChange: (tab: QueryPanelTab) => void\n\n // Metric actions\n onAddMetric: () => void\n onRemoveMetric: (id: string) => void\n onReorderMetrics?: (fromIndex: number, toIndex: number) => void\n\n // Breakdown actions\n onAddBreakdown: () => void\n onRemoveBreakdown: (id: string) => void\n onBreakdownGranularityChange: (id: string, granularity: string) => void\n onBreakdownComparisonToggle?: (id: string) => void\n onReorderBreakdowns?: (fromIndex: number, toIndex: number) => void\n\n // Filter actions\n onFiltersChange: (filters: Filter[]) => void\n onDropFieldToFilter?: (field: string) => void\n\n // Sorting\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n\n // Chart configuration\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n /** Color palette for display config options */\n colorPalette?: ColorPalette\n /** Map of chart type availability for disabling unavailable chart types */\n chartAvailability?: ChartAvailabilityMap\n onChartTypeChange: (type: ChartType) => void\n onChartConfigChange: (config: ChartAxisConfig) => void\n onDisplayConfigChange: (config: ChartDisplayConfig) => void\n\n // Validation state (for showing errors)\n validationStatus: ValidationStatus\n validationError: string | null\n\n // Multi-query props\n /** Number of queries (determines single vs multi-query display) */\n queryCount?: number\n /** Index of the currently active query tab */\n activeQueryIndex?: number\n /** Strategy for merging results from multiple queries */\n mergeStrategy?: QueryMergeStrategy\n /** Callback when active query tab changes */\n onActiveQueryChange?: (index: number) => void\n /** Callback to add a new query */\n onAddQuery?: () => void\n /** Callback to remove a query at specified index */\n onRemoveQuery?: (index: number) => void\n /** Callback when merge strategy changes */\n onMergeStrategyChange?: (strategy: QueryMergeStrategy) => void\n /** Whether breakdowns are locked (synced from Q1 in merge mode) */\n breakdownsLocked?: boolean\n /** Combined metrics from all queries (for chart config in multi-query mode) */\n combinedMetrics?: MetricItem[]\n /** Combined breakdowns from all queries (for chart config in multi-query mode) */\n combinedBreakdowns?: BreakdownItem[]\n /** Validation result for multi-query mode (errors and warnings) */\n multiQueryValidation?: MultiQueryValidationResult | null\n\n // Funnel-specific props (when mergeStrategy === 'funnel')\n /** Binding key dimension that links funnel steps together */\n funnelBindingKey?: FunnelBindingKey | null\n /** Callback when funnel binding key changes */\n onFunnelBindingKeyChange?: (bindingKey: FunnelBindingKey | null) => void\n}\n\n/**\n * Props for the AnalysisResultsPanel component\n */\nexport interface AnalysisResultsPanelProps {\n /** Current execution status */\n executionStatus: ExecutionStatus\n /** Execution results (raw data) */\n executionResults: any[] | null\n /** Execution error message */\n executionError: string | null\n /** Total row count (before limit) */\n totalRowCount: number | null\n /** Whether results are stale (query changed) */\n resultsStale: boolean\n\n /** Chart type for visualization */\n chartType: ChartType\n /** Chart axis configuration */\n chartConfig: ChartAxisConfig\n /** Chart display configuration */\n displayConfig: ChartDisplayConfig\n /** Color palette for charts */\n colorPalette?: ColorPalette\n /** Current palette name (for selector) */\n currentPaletteName?: string\n /** Callback when color palette changes (shows selector when provided) */\n onColorPaletteChange?: (paletteName: string) => void\n\n /** All queries for multi-query mode (used for table column headers per-query) */\n allQueries?: CubeQuery[]\n /**\n * In funnel mode, the actually executed queries with:\n * - Binding key dimension auto-added\n * - IN filter applied for steps 2+\n * Use these for debug display instead of allQueries.\n */\n funnelExecutedQueries?: CubeQuery[]\n /** Schema metadata */\n schema: MetaResponse | null\n\n /** Active view (table or chart) */\n activeView: 'table' | 'chart'\n /** Callback when active view changes */\n onActiveViewChange: (view: 'table' | 'chart') => void\n\n /** Display limit for table */\n displayLimit: number\n /** Callback when display limit changes */\n onDisplayLimitChange: (limit: number) => void\n\n /** Whether the query has metrics (measures) - needed to enable/disable chart view */\n hasMetrics: boolean\n\n // Debug information (from dry-run) - per-query for multi-query mode\n /** Debug data for each query (SQL, analysis, loading/error state) */\n debugDataPerQuery?: Array<{\n sql: { sql: string; params: unknown[] } | null\n analysis: QueryAnalysis | null\n loading: boolean\n error: Error | null\n }>\n\n // Share functionality\n onShareClick?: () => void\n canShare?: boolean\n shareButtonState?: 'idle' | 'copied' | 'copied-no-chart'\n\n // Refresh functionality\n onRefreshClick?: () => void\n canRefresh?: boolean\n isRefreshing?: boolean\n\n // Clear functionality\n onClearClick?: () => void\n canClear?: boolean\n\n // AI functionality\n enableAI?: boolean\n isAIOpen?: boolean\n onAIToggle?: () => void\n\n // Multi-query support\n /** Number of queries (for showing Table 1, Table 2 tabs) */\n queryCount?: number\n /** Per-query results (for table view in multi-query mode) */\n perQueryResults?: (any[] | null)[]\n /** Active table index in multi-query mode */\n activeTableIndex?: number\n /** Callback when active table changes */\n onActiveTableChange?: (index: number) => void\n}\n\n// ============================================================================\n// Section Component Props\n// ============================================================================\n\n/**\n * Props for the MetricsSection component\n */\nexport interface MetricsSectionProps {\n /** Selected metrics */\n metrics: MetricItem[]\n /** Schema for resolving field titles */\n schema: MetaResponse | null\n /** Add metric handler */\n onAdd: () => void\n /** Remove metric handler */\n onRemove: (id: string) => void\n /** Whether the section is expanded */\n isExpanded?: boolean\n /** Toggle expansion */\n onToggleExpanded?: () => void\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n /** Callback when metrics are reordered via drag/drop */\n onReorder?: (fromIndex: number, toIndex: number) => void\n /** Callback when a metric is dragged to the filter section */\n onDragToFilter?: (field: string) => void\n}\n\n/**\n * Props for the BreakdownSection component\n */\nexport interface BreakdownSectionProps {\n /** Selected breakdowns */\n breakdowns: BreakdownItem[]\n /** Schema for resolving field titles */\n schema: MetaResponse | null\n /** Add breakdown handler */\n onAdd: () => void\n /** Remove breakdown handler */\n onRemove: (id: string) => void\n /** Change granularity for time dimension */\n onGranularityChange: (id: string, granularity: string) => void\n /** Toggle comparison for time dimension */\n onComparisonToggle?: (id: string) => void\n /** Whether the section is expanded */\n isExpanded?: boolean\n /** Toggle expansion */\n onToggleExpanded?: () => void\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n /** Callback when breakdowns are reordered via drag/drop */\n onReorder?: (fromIndex: number, toIndex: number) => void\n /** Callback when a breakdown is dragged to the filter section */\n onDragToFilter?: (field: string) => void\n}\n\n/**\n * Props for MetricItemCard component\n */\nexport interface MetricItemCardProps {\n /** Metric item data */\n metric: MetricItem\n /** Field metadata (for title, description) */\n fieldMeta: MetaField | null\n /** Remove handler */\n onRemove: () => void\n /** Current sort direction for this field */\n sortDirection?: 'asc' | 'desc' | null\n /** Sort priority (1, 2, 3...) if sorted */\n sortPriority?: number\n /** Toggle sort handler */\n onToggleSort?: () => void\n /** Index in the list (for drag/drop) */\n index?: number\n /** Whether this item is being dragged */\n isDragging?: boolean\n /** Whether dragging over this item */\n isDragOver?: boolean\n /** Drag start handler */\n onDragStart?: (e: DragEvent, index: number) => void\n /** Drag over handler */\n onDragOver?: (e: DragEvent, index: number) => void\n /** Drop handler */\n onDrop?: (e: DragEvent, index: number) => void\n /** Drag end handler */\n onDragEnd?: () => void\n}\n\n/**\n * Props for BreakdownItemCard component\n */\nexport interface BreakdownItemCardProps {\n /** Breakdown item data */\n breakdown: BreakdownItem\n /** Field metadata (for title, description) */\n fieldMeta: MetaField | null\n /** Remove handler */\n onRemove: () => void\n /** Granularity change handler (for time dimensions) */\n onGranularityChange?: (granularity: string) => void\n /** Toggle comparison for time dimensions */\n onComparisonToggle?: () => void\n /** Whether another time dimension already has comparison enabled */\n comparisonDisabled?: boolean\n /** Current sort direction for this field */\n sortDirection?: 'asc' | 'desc' | null\n /** Sort priority (1, 2, 3...) if sorted */\n sortPriority?: number\n /** Toggle sort handler */\n onToggleSort?: () => void\n /** Index in the list (for drag/drop) */\n index?: number\n /** Whether this item is being dragged */\n isDragging?: boolean\n /** Whether dragging over this item */\n isDragOver?: boolean\n /** Drag start handler */\n onDragStart?: (e: DragEvent, index: number) => void\n /** Drag over handler */\n onDragOver?: (e: DragEvent, index: number) => void\n /** Drop handler */\n onDrop?: (e: DragEvent, index: number) => void\n /** Drag end handler */\n onDragEnd?: () => void\n}\n\n// ============================================================================\n// Main Component Props\n// ============================================================================\n\n/**\n * Props for the main AnalysisBuilder component\n */\nexport interface AnalysisBuilderProps {\n /** Additional CSS classes */\n className?: string\n /** Maximum height for the component (e.g., '800px', '100vh', 'calc(100vh - 64px)') */\n maxHeight?: string\n /**\n * Initial query configuration to load.\n * Accepts either a single CubeQuery or a MultiQueryConfig - the component handles both internally.\n * This keeps multi-query complexity contained within AnalysisBuilder.\n */\n initialQuery?: CubeQuery | MultiQueryConfig\n /** Initial chart configuration (for editing existing portlets) */\n initialChartConfig?: {\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n }\n /** Initial data to display (avoids re-fetching when editing existing portlets) */\n initialData?: any[]\n /** Color palette for chart visualization */\n colorPalette?: ColorPalette\n /** Disable localStorage persistence */\n disableLocalStorage?: boolean\n /** Hide settings button */\n hideSettings?: boolean\n /** Callback when query changes (for modal integration) */\n onQueryChange?: (query: CubeQuery) => void\n /** Callback when chart config changes */\n onChartConfigChange?: (config: { chartType: ChartType; chartConfig: ChartAxisConfig; displayConfig: ChartDisplayConfig }) => void\n}\n\n/**\n * Ref interface for AnalysisBuilder (for external access)\n */\nexport interface AnalysisBuilderRef {\n /**\n * Get the current query configuration.\n * Returns either a CubeQuery (single query) or MultiQueryConfig (multiple queries).\n * Consumers should just JSON.stringify the result - no need to check the type.\n */\n getQueryConfig: () => CubeQuery | MultiQueryConfig\n /** Get current chart configuration */\n getChartConfig: () => { chartType: ChartType; chartConfig: ChartAxisConfig; displayConfig: ChartDisplayConfig }\n /** Execute the current query */\n executeQuery: () => void\n /** Clear the current query */\n clearQuery: () => void\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Local storage state shape for persistence\n */\nexport interface AnalysisBuilderStorageState {\n // Legacy single-query format (for backward compatibility)\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n order?: Record<string, 'asc' | 'desc'>\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n activeView: 'table' | 'chart'\n\n // Multi-query format (when multiple queries are configured)\n queryStates?: AnalysisBuilderState[]\n activeQueryIndex?: number\n mergeStrategy?: QueryMergeStrategy\n /** Dimension keys used for merging in 'merge' strategy */\n mergeKeys?: string[]\n}\n\n/**\n * Recent fields storage shape\n */\nexport interface RecentFieldsStorage {\n metrics: string[]\n breakdowns: string[]\n}\n\n/**\n * Time granularity options\n */\nexport const TIME_GRANULARITIES = [\n { value: 'hour', label: 'Hour' },\n { value: 'day', label: 'Day' },\n { value: 'week', label: 'Week' },\n { value: 'month', label: 'Month' },\n { value: 'quarter', label: 'Quarter' },\n { value: 'year', label: 'Year' }\n] as const\n\nexport type TimeGranularity = typeof TIME_GRANULARITIES[number]['value']\n","/**\n * BreakdownItemCard Component\n *\n * Displays a single breakdown (dimension) item with optional granularity selector.\n */\n\nimport { memo } from 'react'\nimport type { BreakdownItemCardProps, TimeGranularity } from './types'\nimport { TIME_GRANULARITIES } from './types'\nimport { getIcon } from '../../icons'\n\n/**\n * BreakdownItemCard displays a selected breakdown with:\n * - Field icon (dimension or time dimension)\n * - Field title or full name\n * - Granularity dropdown (for time dimensions)\n * - Sort toggle button (visible on hover, or always visible when sorted)\n * - Remove button (visible on hover)\n * - Drag handle for reordering\n */\nconst BreakdownItemCard = memo(function BreakdownItemCard({\n breakdown,\n fieldMeta,\n onRemove,\n onGranularityChange,\n onComparisonToggle,\n comparisonDisabled,\n sortDirection,\n sortPriority,\n onToggleSort,\n index,\n isDragging,\n onDragStart,\n onDragEnd\n}: BreakdownItemCardProps) {\n const DimensionIcon = getIcon('dimension')\n const TimeIcon = getIcon('timeDimension')\n const CloseIcon = getIcon('close')\n const ChevronUpIcon = getIcon('chevronUp')\n const ChevronDownIcon = getIcon('chevronDown')\n const ChevronUpDownIcon = getIcon('chevronUpDown')\n\n // Get display title - prefer shortTitle, then title, then field name\n const displayTitle = fieldMeta?.shortTitle || fieldMeta?.title || breakdown.field.split('.').pop() || breakdown.field\n\n // Get the cube name from the field\n const cubeName = breakdown.field.split('.')[0]\n\n // Choose icon based on dimension type\n const Icon = breakdown.isTimeDimension ? TimeIcon : DimensionIcon\n\n // Get sort icon based on direction\n const getSortIcon = () => {\n switch (sortDirection) {\n case 'asc':\n return ChevronUpIcon ? <ChevronUpIcon className=\"w-4 h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"w-4 h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"w-4 h-4\" /> : '⇅'\n }\n }\n\n // Get sort tooltip\n const getSortTooltip = () => {\n switch (sortDirection) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n }\n\n // Check if drag/drop is enabled\n const isDraggable = typeof index === 'number' && onDragStart && onDragEnd\n\n return (\n <div\n className={`flex items-center gap-2 p-2 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-all duration-150 ${\n isDraggable ? 'cursor-grab active:cursor-grabbing' : ''\n } ${isDragging ? 'opacity-30' : ''}`}\n draggable={isDraggable ? true : undefined}\n onDragStart={isDraggable ? (e) => onDragStart(e, index) : undefined}\n onDragEnd={isDraggable ? onDragEnd : undefined}\n >\n {/* Icon - colored background matching field selector */}\n <span className={`w-6 h-6 flex items-center justify-center rounded flex-shrink-0 ${\n breakdown.isTimeDimension\n ? 'bg-dc-time-dimension text-dc-time-dimension-text'\n : 'bg-dc-dimension text-dc-dimension-text'\n }`}>\n <Icon className=\"w-4 h-4\" />\n </span>\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={breakdown.field}>\n {displayTitle}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Granularity Selector (for time dimensions) */}\n {breakdown.isTimeDimension && onGranularityChange && (\n <select\n value={breakdown.granularity || 'day'}\n onChange={(e) => onGranularityChange(e.target.value as TimeGranularity)}\n onClick={(e) => e.stopPropagation()}\n className=\"text-xs bg-dc-surface border border-dc-border rounded px-2 py-1 text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary flex-shrink-0\"\n >\n {TIME_GRANULARITIES.map((g) => (\n <option key={g.value} value={g.value}>\n {g.label}\n </option>\n ))}\n </select>\n )}\n\n {/* Comparison Toggle (for time dimensions) */}\n {breakdown.isTimeDimension && onComparisonToggle && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onComparisonToggle()\n }}\n disabled={comparisonDisabled && !breakdown.enableComparison}\n className={`text-xs px-2 py-1 rounded flex-shrink-0 transition-colors ${\n breakdown.enableComparison\n ? 'bg-dc-accent text-white'\n : 'bg-dc-surface border border-dc-border text-dc-text-muted hover:text-dc-text hover:bg-dc-surface-hover'\n } ${comparisonDisabled && !breakdown.enableComparison ? 'opacity-50 cursor-not-allowed' : ''}`}\n title={\n comparisonDisabled && !breakdown.enableComparison\n ? 'Another time dimension already has comparison enabled'\n : breakdown.enableComparison\n ? 'Click to disable comparison'\n : 'Compare with previous period'\n }\n >\n vs prior\n </button>\n )}\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`p-1 transition-opacity flex-shrink-0 flex items-center gap-0.5 ${\n sortDirection\n ? 'opacity-100 text-dc-primary'\n : 'opacity-100 sm:opacity-0 sm:group-hover:opacity-100 text-dc-text-muted hover:text-dc-primary'\n }`}\n title={getSortTooltip()}\n >\n {getSortIcon()}\n {sortDirection && sortPriority && (\n <span className=\"text-xs font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title=\"Remove breakdown\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )\n})\n\nexport default BreakdownItemCard\n","/**\n * BreakdownSection Component\n *\n * Displays the Breakdown section in the query panel with expandable list of breakdowns.\n */\n\nimport { useMemo, useState, useCallback, useRef, memo, DragEvent } from 'react'\nimport type { BreakdownSectionProps } from './types'\nimport type { MetaField } from '../../shared/types'\nimport BreakdownItemCard from './BreakdownItemCard'\nimport SectionHeading from './SectionHeading'\nimport { getIcon } from '../../icons'\n\n// Get icon once at module level to avoid recreating\nconst AddIcon = getIcon('add')\n\n/**\n * Find field metadata by field name\n */\nfunction findFieldMeta(fieldName: string, schema: BreakdownSectionProps['schema']): MetaField | null {\n if (!schema?.cubes) return null\n\n const [cubeName] = fieldName.split('.')\n const cube = schema.cubes.find((c) => c.name === cubeName)\n if (!cube) return null\n\n // Check dimensions first, then try to find in other arrays\n return cube.dimensions?.find((d) => d.name === fieldName) || null\n}\n\n/**\n * Get next sort direction in the cycle: null -> asc -> desc -> null\n */\nfunction getNextSortDirection(current: 'asc' | 'desc' | null): 'asc' | 'desc' | null {\n switch (current) {\n case null:\n return 'asc'\n case 'asc':\n return 'desc'\n case 'desc':\n return null\n default:\n return 'asc'\n }\n}\n\n/**\n * BreakdownSection displays a collapsible section with:\n * - Header with title and add button\n * - List of selected breakdowns (using BreakdownItemCard)\n * - Drag/drop reordering support\n */\nconst BreakdownSection = memo(function BreakdownSection({\n breakdowns,\n schema,\n onAdd,\n onRemove,\n onGranularityChange,\n onComparisonToggle,\n order,\n onOrderChange,\n onReorder\n}: BreakdownSectionProps) {\n\n // Drag/drop state\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null)\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null) // Index where item will be inserted\n\n // Use refs to track current values for use in drop handler (avoids stale closure issues)\n const draggedIndexRef = useRef<number | null>(null)\n const dropTargetIndexRef = useRef<number | null>(null)\n\n // Get the ordered keys to calculate priority\n const orderKeys = useMemo(() => order ? Object.keys(order) : [], [order])\n\n // Calculate which breakdown has comparison enabled (only one allowed at a time)\n const activeComparisonId = useMemo(() => {\n const withComparison = breakdowns.find(b => b.isTimeDimension && b.enableComparison)\n return withComparison?.id || null\n }, [breakdowns])\n\n // Resolve field metadata for all breakdowns with sort info\n const breakdownsWithMeta = useMemo(() => {\n return breakdowns.map((breakdown, index) => {\n const sortDirection = order?.[breakdown.field] || null\n const sortPriority = sortDirection ? orderKeys.indexOf(breakdown.field) + 1 : undefined\n return {\n breakdown,\n fieldMeta: findFieldMeta(breakdown.field, schema),\n sortDirection,\n sortPriority,\n index\n }\n })\n }, [breakdowns, schema, order, orderKeys])\n\n // Track drag clone for cleanup\n const dragCloneRef = useRef<HTMLElement | null>(null)\n\n // Drag handlers\n const handleDragStart = useCallback((e: DragEvent, index: number) => {\n setDraggedIndex(index)\n draggedIndexRef.current = index\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', JSON.stringify({ type: 'breakdown', index, field: breakdowns[index].field }))\n\n // Create a semi-transparent, slightly tilted drag image\n const target = e.currentTarget as HTMLElement\n const clone = target.cloneNode(true) as HTMLElement\n clone.style.cssText = `\n position: absolute;\n top: -9999px;\n left: -9999px;\n width: ${target.offsetWidth}px;\n opacity: 0.7;\n transform: rotate(2deg);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n pointer-events: none;\n `\n document.body.appendChild(clone)\n dragCloneRef.current = clone\n\n // Calculate offset from click position\n const rect = target.getBoundingClientRect()\n const offsetX = e.clientX - rect.left\n const offsetY = e.clientY - rect.top\n e.dataTransfer.setDragImage(clone, offsetX, offsetY)\n }, [breakdowns])\n\n const handleDragEnd = useCallback(() => {\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n // Clean up the drag clone\n if (dragCloneRef.current) {\n document.body.removeChild(dragCloneRef.current)\n dragCloneRef.current = null\n }\n }, [])\n\n // Handle drag over an item - determine drop position based on mouse position\n const handleItemDragOver = useCallback((e: DragEvent, itemIndex: number) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Only process if we're dragging from this section\n const currentDraggedIndex = draggedIndexRef.current\n if (currentDraggedIndex === null) return\n\n // Determine if we're in the top or bottom half of the item\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseY = e.clientY - rect.top\n const isTopHalf = mouseY < rect.height / 2\n\n // Calculate target index based on position\n let targetIndex = isTopHalf ? itemIndex : itemIndex + 1\n\n // Don't set drop target if it would result in no movement\n if (targetIndex === currentDraggedIndex || targetIndex === currentDraggedIndex + 1) {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n } else {\n setDropTargetIndex(targetIndex)\n dropTargetIndexRef.current = targetIndex\n }\n }, [])\n\n // Handle drop on an item\n const handleItemDrop = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Use refs to get current values (avoids stale closure issues)\n const currentDraggedIndex = draggedIndexRef.current\n const currentDropTargetIndex = dropTargetIndexRef.current\n\n // Reset visual state immediately\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n\n // Validate and reorder - use refs directly, no dataTransfer parsing needed\n if (currentDraggedIndex === null || currentDropTargetIndex === null || !onReorder) {\n return\n }\n\n // Adjust target index when dragging down (after splice, indices shift)\n const adjustedTarget = currentDropTargetIndex > currentDraggedIndex\n ? currentDropTargetIndex - 1\n : currentDropTargetIndex\n\n if (adjustedTarget !== currentDraggedIndex) {\n onReorder(currentDraggedIndex, adjustedTarget)\n }\n }, [onReorder])\n\n // Clear drop target when leaving the section\n const handleSectionDragLeave = useCallback((e: DragEvent) => {\n const relatedTarget = e.relatedTarget as HTMLElement | null\n if (!relatedTarget || !e.currentTarget.contains(relatedTarget)) {\n setDropTargetIndex(null)\n }\n }, [])\n\n // Calculate if an item should be shifted to make room for the drop\n const getItemTransform = useCallback((itemIndex: number): string => {\n if (draggedIndex === null || dropTargetIndex === null) return ''\n\n // Gap size in pixels\n const gapSize = 40\n\n // If this is the dragged item, no transform needed (it's already faded)\n if (itemIndex === draggedIndex) return ''\n\n // Items at or after drop target need to shift down\n // But we need to account for the dragged item's position\n if (draggedIndex < dropTargetIndex) {\n // Dragging down: items between dragged+1 and dropTarget-1 shift up\n if (itemIndex > draggedIndex && itemIndex < dropTargetIndex) {\n return '' // No gap needed, item stays in place\n }\n // Item at dropTarget-1 position should show gap after it\n if (itemIndex === dropTargetIndex - 1) {\n return `translateY(-${gapSize / 2}px)` // Shift up to make room\n }\n if (itemIndex >= dropTargetIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down\n }\n } else {\n // Dragging up: items from dropTarget to draggedIndex-1 shift down\n if (itemIndex >= dropTargetIndex && itemIndex < draggedIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down to make room\n }\n }\n\n return ''\n }, [draggedIndex, dropTargetIndex])\n\n // Determine if gap indicator should show at a position\n const shouldShowGapIndicator = useCallback((itemIndex: number): boolean => {\n if (draggedIndex === null || dropTargetIndex === null) return false\n\n // Show indicator before the item that matches dropTargetIndex\n return itemIndex === dropTargetIndex\n }, [draggedIndex, dropTargetIndex])\n\n return (\n <div>\n {/* Section Header - entire row is clickable */}\n <button\n onClick={onAdd}\n className=\"flex items-center justify-between mb-3 w-full py-1 px-2 -ml-2 rounded-lg hover:bg-dc-primary/10 transition-colors group\"\n title=\"Add breakdown\"\n >\n <SectionHeading>Breakdown</SectionHeading>\n <AddIcon className=\"w-5 h-5 text-dc-text-secondary group-hover:text-dc-primary transition-colors\" />\n </button>\n\n {/* Breakdowns List */}\n <div\n className=\"space-y-2\"\n onDragLeave={onReorder ? handleSectionDragLeave : undefined}\n onDragOver={onReorder ? (e) => e.preventDefault() : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {breakdownsWithMeta.map(({ breakdown, fieldMeta, sortDirection, sortPriority, index }) => {\n const transform = getItemTransform(index)\n const showGapBefore = shouldShowGapIndicator(index)\n\n return (\n <div\n key={breakdown.id}\n className=\"relative\"\n style={{\n transform,\n transition: draggedIndex !== null ? 'transform 0.15s ease-out' : 'none'\n }}\n onDragOver={onReorder ? (e) => handleItemDragOver(e, index) : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {/* Gap indicator line - shows where item will be inserted */}\n {showGapBefore && (\n <div className=\"absolute -top-5 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n )}\n <BreakdownItemCard\n breakdown={breakdown}\n fieldMeta={fieldMeta}\n onRemove={() => onRemove(breakdown.id)}\n onGranularityChange={\n breakdown.isTimeDimension\n ? (granularity) => onGranularityChange(breakdown.id, granularity)\n : undefined\n }\n onComparisonToggle={\n breakdown.isTimeDimension && onComparisonToggle\n ? () => onComparisonToggle(breakdown.id)\n : undefined\n }\n comparisonDisabled={activeComparisonId !== null && activeComparisonId !== breakdown.id}\n sortDirection={sortDirection}\n sortPriority={sortPriority}\n onToggleSort={onOrderChange ? () => {\n const nextDirection = getNextSortDirection(sortDirection)\n onOrderChange(breakdown.field, nextDirection)\n } : undefined}\n index={index}\n isDragging={draggedIndex === index}\n onDragStart={onReorder ? handleDragStart : undefined}\n onDragEnd={onReorder ? handleDragEnd : undefined}\n />\n </div>\n )\n })}\n {/* Gap indicator after the last item - shows when dropping at end */}\n {onReorder && draggedIndex !== null && dropTargetIndex === breakdowns.length && (\n <div className=\"relative h-2\">\n <div className=\"absolute top-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n </div>\n )}\n {/* Handle drop at the end of the list */}\n {onReorder && breakdowns.length > 0 && draggedIndex !== null && (\n <div\n className=\"h-8\"\n onDragOver={(e) => {\n e.preventDefault()\n // Set drop target to end of list\n const lastIndex = breakdowns.length\n const currentDraggedIndex = draggedIndexRef.current\n if (dropTargetIndexRef.current !== lastIndex && currentDraggedIndex !== lastIndex - 1) {\n setDropTargetIndex(lastIndex)\n dropTargetIndexRef.current = lastIndex\n }\n }}\n onDrop={handleItemDrop}\n />\n )}\n </div>\n </div>\n )\n})\n\nexport default BreakdownSection\n","/**\n * FilterConfigModal Component\n *\n * Modal for configuring filter settings with full UI for:\n * - Field selection with search\n * - Operator selection\n * - Value input (varies by operator and field type)\n * - Date range selection\n * - Multi-value support\n */\n\nimport React, { useState, useRef, useEffect, useCallback, ChangeEvent } from 'react'\nimport { getIcon } from '../../icons'\nimport type { SimpleFilter, FilterOperator } from '../../types'\nimport type { MetaResponse, DateRangeType } from '../../shared/types'\nimport {\n FILTER_OPERATORS,\n DATE_RANGE_OPTIONS\n} from '../../shared/types'\nimport {\n getAvailableOperators,\n convertDateRangeTypeToValue,\n requiresNumberInput\n} from '../../shared/utils'\nimport { findFieldInSchema, getFieldTitle } from './utils'\nimport { useFilterValues } from '../../hooks/useFilterValues'\nimport { useDebounce } from '../../hooks/useDebounce'\n\nconst CloseIcon = getIcon('close')\nconst ChevronDownIcon = getIcon('chevronDown')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\n\ninterface FilterConfigModalProps {\n /** The filter being edited */\n filter: SimpleFilter\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback when user saves changes */\n onSave: (filter: SimpleFilter) => void\n /** Callback when user cancels */\n onCancel: () => void\n /** Element to position the modal near */\n anchorElement?: HTMLElement | null\n}\n\nexport default function FilterConfigModal({\n filter: initialFilter,\n schema,\n onSave,\n onCancel,\n anchorElement\n}: FilterConfigModalProps) {\n const [filter, setFilter] = useState<SimpleFilter>(initialFilter)\n const [isOperatorDropdownOpen, setIsOperatorDropdownOpen] = useState(false)\n const [isValueDropdownOpen, setIsValueDropdownOpen] = useState(false)\n const [isDateRangeDropdownOpen, setIsDateRangeDropdownOpen] = useState(false)\n const [rangeType, setRangeType] = useState<DateRangeType>('this_month')\n const [numberValue, setNumberValue] = useState(1)\n const [searchText, setSearchText] = useState('')\n const [modalPosition, setModalPosition] = useState<{ top?: number; bottom?: number; left: number } | null>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n // Debounce search text for API calls\n const debouncedSearchText = useDebounce(searchText, 300)\n\n // Get field info\n const fieldInfo = findFieldInSchema(filter.member, schema)\n const fieldType = fieldInfo?.field.type || 'string'\n const isTimeField = fieldType === 'time'\n const isMeasureField = fieldInfo?.fieldType === 'measure'\n const isDimensionField = fieldInfo?.fieldType === 'dimension'\n\n // Get display title for field\n const fieldTitle = getFieldTitle(filter.member, schema)\n\n // Get operator metadata\n const operatorMeta = FILTER_OPERATORS[filter.operator as FilterOperator]\n\n // Get available operators for this field type\n const availableOperators = getAvailableOperators(fieldType)\n\n // Should show date range selector\n const shouldShowDateRange = isTimeField && filter.operator === 'inDateRange'\n\n // Should use combo box for value selection\n const shouldShowComboBox = useCallback(() => {\n const comboOperators = ['equals', 'notEquals', 'in', 'notIn']\n return comboOperators.includes(filter.operator) && isDimensionField && !isTimeField\n }, [filter.operator, isDimensionField, isTimeField])()\n\n // Fetch distinct values for combo box\n const {\n values: distinctValues,\n loading: valuesLoading,\n error: valuesError,\n searchValues\n } = useFilterValues(filter.member, shouldShowComboBox)\n\n // Calculate modal position relative to anchor element\n useEffect(() => {\n if (!anchorElement) {\n setModalPosition(null)\n return\n }\n\n const rect = anchorElement.getBoundingClientRect()\n const modalHeight = 500 // Approximate modal height\n const spaceAbove = rect.top\n const spaceBelow = window.innerHeight - rect.bottom\n const modalWidth = 400 // Modal max-width\n\n // Determine if modal should appear above or below\n const shouldAppearAbove = spaceAbove > modalHeight || spaceAbove > spaceBelow\n\n // Calculate left position (try to align with anchor, but keep within viewport)\n const left = Math.max(16, Math.min(rect.left, window.innerWidth - modalWidth - 16))\n\n if (shouldAppearAbove) {\n // Position above the anchor\n setModalPosition({\n bottom: window.innerHeight - rect.top + 8,\n left\n })\n } else {\n // Position below the anchor\n setModalPosition({\n top: rect.bottom + 8,\n left\n })\n }\n }, [anchorElement])\n\n // Close dropdowns when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n }\n }\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [])\n\n // Load values when dropdown opens\n useEffect(() => {\n if (isValueDropdownOpen && shouldShowComboBox && searchValues) {\n searchValues('', true)\n }\n }, [isValueDropdownOpen, shouldShowComboBox, searchValues])\n\n // Search when debounced text changes\n useEffect(() => {\n if (isValueDropdownOpen && shouldShowComboBox && searchValues && debouncedSearchText !== undefined) {\n searchValues(debouncedSearchText)\n }\n }, [debouncedSearchText, isValueDropdownOpen, shouldShowComboBox, searchValues])\n\n // Sync rangeType state with filter.dateRange\n useEffect(() => {\n if (!shouldShowDateRange || !filter.dateRange) return\n\n if (Array.isArray(filter.dateRange)) {\n setRangeType('custom')\n } else {\n // Find matching range type - prioritize \"last N\" patterns\n // Match \"last N days/weeks/months/quarters/years\"\n const flexMatch = filter.dateRange.match(/^last (\\d+) (days|weeks|months|quarters|years)$/)\n // Match singular forms: \"last day/week/month/quarter/year\" (when N=1)\n const singularMatch = !flexMatch && filter.dateRange.match(/^last (day|week|month|quarter|year)$/)\n\n if (flexMatch) {\n const [, num, unit] = flexMatch\n setRangeType(`last_n_${unit}` as DateRangeType)\n setNumberValue(parseInt(num) || 1)\n } else if (singularMatch) {\n // Handle singular forms as \"last_n_*\" with value of 1\n const [, unit] = singularMatch\n const pluralUnit = unit === 'day' ? 'days' :\n unit === 'week' ? 'weeks' :\n unit === 'month' ? 'months' :\n unit === 'quarter' ? 'quarters' : 'years'\n setRangeType(`last_n_${pluralUnit}` as DateRangeType)\n setNumberValue(1)\n } else {\n // Check predefined ranges (only if not a \"last N\" pattern)\n let found = false\n for (const option of DATE_RANGE_OPTIONS) {\n if (option.value !== 'custom' && !requiresNumberInput(option.value)) {\n if (convertDateRangeTypeToValue(option.value) === filter.dateRange) {\n setRangeType(option.value)\n found = true\n break\n }\n }\n }\n if (!found) setRangeType('custom')\n }\n }\n }, [filter.dateRange, shouldShowDateRange])\n\n // Handle operator change\n const handleOperatorChange = useCallback((operator: FilterOperator) => {\n setFilter({\n member: filter.member,\n operator,\n values: []\n })\n setIsOperatorDropdownOpen(false)\n }, [filter.member])\n\n // Handle value selection from combo box\n const handleValueSelect = useCallback((value: unknown) => {\n const values = filter.values || []\n if (operatorMeta?.supportsMultipleValues) {\n if (!values.includes(value)) {\n setFilter({ ...filter, values: [...values, value] })\n }\n } else {\n setFilter({ ...filter, values: [value] })\n setIsValueDropdownOpen(false)\n }\n setSearchText('')\n }, [filter, operatorMeta?.supportsMultipleValues])\n\n // Handle value removal\n const handleValueRemove = useCallback((valueToRemove: unknown) => {\n const values = (filter.values || []).filter((v: unknown) => v !== valueToRemove)\n setFilter({ ...filter, values })\n }, [filter])\n\n // Handle direct text/number input\n const handleDirectInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n if (operatorMeta?.valueType === 'number') {\n const numValue = parseFloat(value)\n if (!isNaN(numValue)) {\n setFilter({ ...filter, values: [numValue] })\n } else if (value === '' || value === '-') {\n setFilter({ ...filter, values: [] })\n }\n } else {\n setFilter({ ...filter, values: value ? [value] : [] })\n }\n }, [filter, operatorMeta?.valueType])\n\n // Handle between range inputs\n const handleBetweenStartInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = filter.values?.length >= 2 ? filter.values : ['', '']\n const newValues = [!isNaN(value) ? value : '', currentValues[1]].filter(v => v !== '')\n setFilter({ ...filter, values: newValues })\n }, [filter])\n\n const handleBetweenEndInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = filter.values?.length >= 2 ? filter.values : ['', '']\n const newValues = [currentValues[0], !isNaN(value) ? value : ''].filter(v => v !== '')\n setFilter({ ...filter, values: newValues })\n }, [filter])\n\n // Handle date input\n const handleDateInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setFilter({ ...filter, values: value ? [value] : [] })\n }, [filter])\n\n // Handle date range type change\n const handleRangeTypeChange = useCallback((newRangeType: DateRangeType) => {\n setRangeType(newRangeType)\n setIsDateRangeDropdownOpen(false)\n\n let dateRange: string | string[]\n if (newRangeType === 'custom') {\n const today = new Date().toISOString().split('T')[0]\n dateRange = [today, today]\n } else if (requiresNumberInput(newRangeType)) {\n dateRange = convertDateRangeTypeToValue(newRangeType, numberValue)\n } else {\n dateRange = convertDateRangeTypeToValue(newRangeType)\n }\n\n setFilter({ ...filter, dateRange } as SimpleFilter)\n }, [filter, numberValue])\n\n // Handle number value change for \"last N days/weeks/etc\"\n const handleNumberValueChange = useCallback((value: number) => {\n setNumberValue(value)\n if (requiresNumberInput(rangeType)) {\n const dateRange = convertDateRangeTypeToValue(rangeType, value)\n setFilter({ ...filter, dateRange } as SimpleFilter)\n }\n }, [filter, rangeType])\n\n // Handle custom date range inputs\n const handleCustomStartDate = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const start = e.target.value\n const currentRange = Array.isArray(filter.dateRange) ? filter.dateRange : [filter.dateRange || '', '']\n const end = currentRange[1] || start\n setFilter({ ...filter, dateRange: [start, end] } as SimpleFilter)\n }, [filter])\n\n const handleCustomEndDate = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const end = e.target.value\n const currentRange = Array.isArray(filter.dateRange) ? filter.dateRange : ['', filter.dateRange || '']\n const start = currentRange[0] || end\n setFilter({ ...filter, dateRange: [start, end] } as SimpleFilter)\n }, [filter])\n\n // Get current operator label\n const operatorLabel = availableOperators.find(op => op.operator === filter.operator)?.label || filter.operator\n\n // Get current date range label\n const dateRangeLabel = DATE_RANGE_OPTIONS.find(opt => opt.value === rangeType)?.label || 'Select range'\n\n // Get icon for field type\n const FieldIcon = isTimeField ? TimeDimensionIcon : isMeasureField ? MeasureIcon : DimensionIcon\n\n // Render value input based on operator type\n const renderValueInput = () => {\n // No value required for set/notSet\n if (!operatorMeta?.requiresValues) {\n return (\n <div className=\"text-sm text-dc-text-muted italic py-2\">\n No value required\n </div>\n )\n }\n\n // Date range selector for inDateRange on time fields\n if (shouldShowDateRange) {\n return (\n <div className=\"space-y-2\">\n {/* Range type dropdown */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(!isDateRangeDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{dateRangeLabel}</span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isDateRangeDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isDateRangeDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-y-auto\">\n {DATE_RANGE_OPTIONS.map((option) => (\n <button\n key={option.value}\n onClick={() => handleRangeTypeChange(option.value)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n option.value === rangeType ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {option.label}\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Number input for \"last N\" ranges */}\n {requiresNumberInput(rangeType) && (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min=\"1\"\n max=\"1000\"\n value={numberValue}\n onChange={(e) => handleNumberValueChange(Math.max(1, parseInt(e.target.value) || 1))}\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text w-20\"\n />\n <span className=\"text-sm text-dc-text-muted\">\n {rangeType.replace('last_n_', '')}\n </span>\n </div>\n )}\n\n {/* Custom date inputs */}\n {rangeType === 'custom' && (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[0] : ''}\n onChange={handleCustomStartDate}\n className=\"flex-1 text-sm border border-dc-border rounded px-2 py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[1] : ''}\n onChange={handleCustomEndDate}\n className=\"flex-1 text-sm border border-dc-border rounded px-2 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n )}\n </div>\n )\n }\n\n // Between/notBetween range inputs\n if (filter.operator === 'between' || filter.operator === 'notBetween') {\n return (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"number\"\n value={filter.values?.[1] ?? ''}\n onChange={handleBetweenEndInput}\n placeholder=\"Max\"\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n )\n }\n\n // Date picker for date operators\n if (operatorMeta?.valueType === 'date') {\n return (\n <input\n type=\"date\"\n value={filter.values?.[0] || ''}\n onChange={handleDateInput}\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Number input\n if (operatorMeta?.valueType === 'number') {\n return (\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter number\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Combo box for equals/notEquals/in/notIn on dimensions\n if (shouldShowComboBox) {\n return (\n <div className=\"space-y-2\">\n {/* Selected values as tags */}\n {filter.values && filter.values.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {filter.values.map((value: unknown, index: number) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 bg-dc-primary/10 text-dc-primary text-sm px-2 py-1 rounded\"\n >\n <span className=\"max-w-[150px] truncate\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"hover:text-dc-danger\"\n >\n <CloseIcon className=\"w-3.5 h-3.5\" />\n </button>\n </span>\n ))}\n </div>\n )}\n\n {/* Dropdown trigger */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsValueDropdownOpen(!isValueDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"text-dc-text-muted truncate\">\n {valuesLoading ? 'Loading...' : 'Select value...'}\n </span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isValueDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isValueDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-56 overflow-hidden\">\n {/* Search input */}\n <div className=\"p-2 border-b border-dc-border\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search...\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div className=\"max-h-40 overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"px-3 py-2 text-sm text-dc-text-muted\">Loading...</div>\n ) : valuesError ? (\n <div className=\"px-3 py-2 text-sm text-dc-error\">Error: {valuesError}</div>\n ) : distinctValues.length === 0 ? (\n <div className=\"px-3 py-2 text-sm text-dc-text-muted\">No values found</div>\n ) : (\n distinctValues.map((value, index) => {\n const isSelected = filter.values?.includes(value)\n return (\n <button\n key={`${value}-${index}`}\n onClick={() => handleValueSelect(value)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n isSelected ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {String(value)}\n {isSelected && <span className=\"float-right\">✓</span>}\n </button>\n )\n })\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n }\n\n // Default: text input\n return (\n <input\n type=\"text\"\n value={filter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter value...\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n />\n )\n }\n\n // Determine modal positioning style\n const getModalStyle = (): React.CSSProperties => {\n if (modalPosition) {\n return {\n position: 'fixed',\n ...modalPosition,\n maxWidth: '400px',\n width: '100%'\n }\n }\n return {}\n }\n\n const modalClassName = modalPosition\n ? 'bg-dc-surface rounded-lg shadow-xl'\n : 'bg-dc-surface rounded-lg shadow-xl max-w-md w-full'\n\n return (\n <>\n {/* Modal overlay */}\n <div\n className={`fixed inset-0 bg-dc-overlay z-50 ${modalPosition ? '' : 'flex items-center justify-center p-4'}`}\n onClick={onCancel}\n >\n <div\n ref={containerRef}\n className={modalClassName}\n style={getModalStyle()}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-4 border-b border-dc-border\">\n <h2 className=\"text-lg font-semibold text-dc-text\">Edit Filter</h2>\n <button\n onClick={onCancel}\n className=\"p-1 text-dc-text-muted hover:text-dc-text transition-colors\"\n >\n <CloseIcon className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"p-4 space-y-4\">\n {/* Field display */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Field\n </label>\n <div className=\"flex items-center gap-2 p-3 bg-dc-surface-secondary rounded\">\n <FieldIcon className=\"w-5 h-5 text-dc-filter-text\" />\n <span className=\"text-sm font-medium text-dc-text\">{fieldTitle}</span>\n </div>\n </div>\n\n {/* Operator selector */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Operator\n </label>\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsOperatorDropdownOpen(!isOperatorDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{operatorLabel}</span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isOperatorDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isOperatorDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-y-auto\">\n {availableOperators.map((op) => (\n <button\n key={op.operator}\n onClick={() => handleOperatorChange(op.operator as FilterOperator)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n op.operator === filter.operator ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {op.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Value input */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Value\n </label>\n {renderValueInput()}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-2 p-4 border-t border-dc-border\">\n <button\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-dc-text-secondary hover:text-dc-text transition-colors\"\n >\n Cancel\n </button>\n <button\n onClick={() => onSave(filter)}\n className=\"px-4 py-2 text-sm font-medium text-dc-primary-content bg-dc-primary hover:bg-dc-primary-hover rounded transition-colors\"\n >\n Save\n </button>\n </div>\n </div>\n </div>\n </>\n )\n}\n","/**\n * AnalysisFilterItem Component\n *\n * Compact filter chip for the AnalysisBuilder's narrow column layout.\n * Displays filter as a chip with icon, field name, operator, and value.\n * Clicking the chip opens a modal for editing the filter configuration.\n */\n\nimport { useState, useRef } from 'react'\nimport { getIcon } from '../../icons'\nimport type { SimpleFilter } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\nimport { FILTER_OPERATORS } from '../../shared/types'\nimport { getFieldTitle, findFieldInSchema } from './utils'\nimport FilterConfigModal from './FilterConfigModal'\n\nconst CloseIcon = getIcon('close')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\n\ninterface AnalysisFilterItemProps {\n /** The filter to display */\n filter: SimpleFilter\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback to remove this filter */\n onRemove: () => void\n /** Callback to update this filter */\n onUpdate: (filter: SimpleFilter) => void\n}\n\nexport default function AnalysisFilterItem({\n filter,\n schema,\n onRemove,\n onUpdate\n}: AnalysisFilterItemProps) {\n const [isModalOpen, setIsModalOpen] = useState(false)\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n // Get field info to determine icon\n const fieldInfo = findFieldInSchema(filter.member, schema)\n const fieldType = fieldInfo?.field.type || 'string'\n const isTimeField = fieldType === 'time'\n const isMeasureField = fieldInfo?.fieldType === 'measure'\n\n // Get display title for field\n const fieldTitle = getFieldTitle(filter.member, schema)\n\n // Get operator metadata\n const operatorMeta = FILTER_OPERATORS[filter.operator]\n const operatorLabel = operatorMeta?.label || filter.operator\n\n // Format value display\n const valueDisplay = formatValueDisplay(filter, operatorMeta)\n\n // Get appropriate icon and colors based on field type\n const FieldIcon = isTimeField ? TimeDimensionIcon : isMeasureField ? MeasureIcon : DimensionIcon\n const iconBgClass = isTimeField ? 'bg-dc-time-dimension' : isMeasureField ? 'bg-dc-measure' : 'bg-dc-dimension'\n const iconTextClass = isTimeField ? 'text-dc-time-dimension-text' : isMeasureField ? 'text-dc-measure-text' : 'text-dc-dimension-text'\n\n return (\n <>\n <div\n className=\"flex items-start gap-2 px-2 py-1.5 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-all duration-150 w-full\"\n >\n {/* Field type icon with appropriate background color */}\n <span className={`w-6 h-6 flex items-center justify-center rounded ${iconBgClass} ${iconTextClass} flex-shrink-0 mt-0.5`}>\n {FieldIcon && <FieldIcon className=\"w-4 h-4\" />}\n </span>\n\n {/* Filter description - clickable to edit */}\n <button\n ref={buttonRef}\n onClick={() => setIsModalOpen(true)}\n className=\"flex-1 min-w-0 text-left\"\n title={`${fieldTitle} ${operatorLabel} ${valueDisplay}`}\n >\n <div className=\"text-sm text-dc-text break-words\">\n <span className=\"font-medium\">{fieldTitle}</span>\n <span className=\"text-dc-text-muted mx-1\">{operatorLabel}</span>\n <span className=\"text-dc-primary\">{valueDisplay}</span>\n </div>\n </button>\n\n {/* Remove button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0 mt-0.5\"\n title=\"Remove filter\"\n >\n {CloseIcon && <CloseIcon className=\"w-4 h-4\" />}\n </button>\n </div>\n\n {/* Filter configuration modal */}\n {isModalOpen && (\n <FilterConfigModal\n filter={filter}\n schema={schema}\n onSave={(updatedFilter) => {\n onUpdate(updatedFilter)\n setIsModalOpen(false)\n }}\n onCancel={() => setIsModalOpen(false)}\n anchorElement={buttonRef.current}\n />\n )}\n </>\n )\n}\n\n/**\n * Formats the filter value(s) for display in the chip.\n * Handles various value types and multiple values.\n */\nfunction formatValueDisplay(filter: SimpleFilter, operatorMeta: any): string {\n // No value required for set/notSet operators\n if (!operatorMeta?.requiresValues) {\n return ''\n }\n\n // Handle date range\n if (filter.dateRange) {\n if (Array.isArray(filter.dateRange)) {\n return `${filter.dateRange[0]} to ${filter.dateRange[1]}`\n }\n return filter.dateRange\n }\n\n const values = filter.values || []\n\n // No values selected\n if (values.length === 0) {\n return '(empty)'\n }\n\n // Single value\n if (values.length === 1) {\n return String(values[0])\n }\n\n // Two values\n if (values.length === 2) {\n return `${values[0]}, ${values[1]}`\n }\n\n // More than two values - show first two plus count\n return `${values[0]}, ${values[1]}, +${values.length - 2} more`\n}\n","/**\n * AnalysisFilterGroup Component\n *\n * Renders a group of filters with AND/OR logic.\n * Supports infinite nesting for complex filter conditions.\n * Compact design for the AnalysisBuilder's narrow column.\n */\n\nimport { useState, useRef, useEffect, useCallback } from 'react'\nimport { getIcon } from '../../icons'\nimport type { Filter, SimpleFilter, GroupFilter } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\nimport AnalysisFilterItem from './AnalysisFilterItem'\n\nconst AddIcon = getIcon('add')\nconst CloseIcon = getIcon('close')\n\ninterface AnalysisFilterGroupProps {\n /** The group filter to render */\n group: GroupFilter\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback when group changes */\n onUpdate: (group: GroupFilter) => void\n /** Callback to remove this group */\n onRemove: () => void\n /** Callback to add a new filter - receives path relative to this group */\n onAddFilter: (relativePath?: number[]) => void\n /** Depth level for styling */\n depth?: number\n /** Whether to hide the remove button (for top-level groups) */\n hideRemoveButton?: boolean\n}\n\n/**\n * Check if a filter is a simple filter\n */\nfunction isSimpleFilter(filter: Filter): filter is SimpleFilter {\n return 'member' in filter && typeof (filter as SimpleFilter).member === 'string'\n}\n\n/**\n * Check if a filter is a group filter\n */\nfunction isGroupFilter(filter: Filter): filter is GroupFilter {\n return 'type' in filter && ((filter as GroupFilter).type === 'and' || (filter as GroupFilter).type === 'or')\n}\n\nexport default function AnalysisFilterGroup({\n group,\n schema,\n onUpdate,\n onRemove,\n onAddFilter,\n depth = 0,\n hideRemoveButton = false\n}: AnalysisFilterGroupProps) {\n const [isAddMenuOpen, setIsAddMenuOpen] = useState(false)\n const addMenuRef = useRef<HTMLDivElement>(null)\n\n // Close add menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (addMenuRef.current && !addMenuRef.current.contains(event.target as Node)) {\n setIsAddMenuOpen(false)\n }\n }\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [])\n\n // Toggle group type (AND <-> OR)\n const handleToggleType = useCallback(() => {\n const newType = group.type === 'and' ? 'or' : 'and'\n onUpdate({ ...group, type: newType })\n }, [group, onUpdate])\n\n // Update a nested filter at a specific index\n const handleUpdateFilter = useCallback((index: number, newFilter: Filter) => {\n const newFilters = [...group.filters]\n newFilters[index] = newFilter\n onUpdate({ ...group, filters: newFilters })\n }, [group, onUpdate])\n\n // Remove a filter at a specific index\n const handleRemoveFilter = useCallback((index: number) => {\n const newFilters = group.filters.filter((_, i) => i !== index)\n\n // If only one filter remains, we might want to unwrap\n // But for now, just update with remaining filters\n if (newFilters.length === 0) {\n // If group is empty, remove the group itself\n onRemove()\n } else if (newFilters.length === 1 && depth > 0) {\n // Unwrap single-filter groups at non-root level by updating parent\n // This is handled by the parent component\n onUpdate({ ...group, filters: newFilters })\n } else {\n onUpdate({ ...group, filters: newFilters })\n }\n }, [group, onUpdate, onRemove, depth])\n\n // Add a nested group at a specific index\n const handleAddNestedGroup = useCallback((type: 'and' | 'or') => {\n const newGroup: GroupFilter = { type, filters: [] }\n onUpdate({ ...group, filters: [...group.filters, newGroup] })\n setIsAddMenuOpen(false)\n }, [group, onUpdate])\n\n // Handle add filter button - add to this group\n const handleAddFilterClick = useCallback(() => {\n onAddFilter([]) // Empty path means add to this group\n setIsAddMenuOpen(false)\n }, [onAddFilter])\n\n // Create handler for nested group to add filters\n const createNestedAddFilterHandler = useCallback((nestedIndex: number) => {\n return (relativePath: number[] = []) => {\n // Prepend this nested index to the relative path\n onAddFilter([nestedIndex, ...relativePath])\n }\n }, [onAddFilter])\n\n // Get border color based on depth\n const getBorderColor = () => {\n if (depth % 2 === 0) {\n return 'border-dc-border'\n }\n return 'border-dc-border dark:border-dc-border'\n }\n\n // Get background color based on group type\n const getGroupBgColor = () => {\n return group.type === 'and' ? 'bg-dc-info-bg/50' : 'bg-dc-warning-bg/50'\n }\n\n const conditionCount = group.filters.length\n const conditionLabel = conditionCount === 1 ? 'condition' : 'conditions'\n\n return (\n <div className={`border ${getBorderColor()} rounded-lg bg-dc-surface w-full`}>\n {/* Group Header */}\n <div className={`flex items-center justify-between px-2 py-1.5 border-b border-dc-border/50 rounded-t-lg ${getGroupBgColor()}`}>\n <div className=\"flex items-center gap-2\">\n {/* AND/OR Toggle Button */}\n <button\n onClick={handleToggleType}\n className={`px-2 py-0.5 text-xs font-semibold rounded transition-colors ${\n group.type === 'and'\n ? 'bg-dc-info-bg text-dc-info hover:opacity-80'\n : 'bg-dc-warning-bg text-dc-warning hover:opacity-80'\n }`}\n title={`Click to switch to ${group.type === 'and' ? 'OR' : 'AND'}`}\n >\n {group.type.toUpperCase()}\n </button>\n\n {/* Condition Count */}\n <span className=\"text-xs text-dc-text-muted\">\n {conditionCount} {conditionLabel}\n </span>\n </div>\n\n <div className=\"flex items-center gap-1\">\n {/* Add Button with Dropdown */}\n <div className=\"relative\" ref={addMenuRef}>\n <button\n onClick={() => setIsAddMenuOpen(!isAddMenuOpen)}\n className=\"p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-hover rounded transition-colors\"\n title=\"Add condition\"\n >\n <AddIcon className=\"w-4 h-4\" />\n </button>\n\n {isAddMenuOpen && (\n <div className=\"absolute right-0 mt-1 z-40 bg-dc-surface border border-dc-border rounded shadow-lg py-1 min-w-[120px]\">\n <button\n onClick={handleAddFilterClick}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add Filter\n </button>\n <button\n onClick={() => handleAddNestedGroup('and')}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add AND Group\n </button>\n <button\n onClick={() => handleAddNestedGroup('or')}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add OR Group\n </button>\n </div>\n )}\n </div>\n\n {/* Remove Group Button */}\n {!hideRemoveButton && (\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger transition-colors\"\n title=\"Remove group\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Group Body - Filter List */}\n <div className=\"p-1.5 flex flex-wrap gap-2\">\n {group.filters.length === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-xs text-dc-text-muted mb-1\">No conditions in this group</p>\n <button\n onClick={() => onAddFilter([])}\n className=\"text-xs text-dc-primary hover:underline\"\n >\n Add a filter\n </button>\n </div>\n ) : (\n group.filters.map((filter, index) => {\n if (isSimpleFilter(filter)) {\n return (\n <AnalysisFilterItem\n key={`filter-${index}`}\n filter={filter}\n schema={schema}\n onUpdate={(newFilter) => handleUpdateFilter(index, newFilter)}\n onRemove={() => handleRemoveFilter(index)}\n />\n )\n } else if (isGroupFilter(filter)) {\n return (\n <AnalysisFilterGroup\n key={`group-${index}`}\n group={filter}\n schema={schema}\n onUpdate={(newGroup) => handleUpdateFilter(index, newGroup)}\n onRemove={() => handleRemoveFilter(index)}\n onAddFilter={createNestedAddFilterHandler(index)}\n depth={depth + 1}\n />\n )\n }\n return null\n })\n )}\n </div>\n </div>\n )\n}\n","/**\n * AnalysisFilterSection Component\n *\n * Compact filter section for the AnalysisBuilder's narrow column layout.\n * Renders hierarchical filter structure with AND/OR groups.\n * Uses FieldSearchModal for field selection.\n */\n\nimport { useState, useCallback, useRef, DragEvent } from 'react'\nimport { getIcon } from '../../icons'\nimport SectionHeading from './SectionHeading'\nimport type { Filter, SimpleFilter, GroupFilter } from '../../types'\nimport type { MetaResponse, MetaField } from '../../shared/types'\nimport FieldSearchModal from './FieldSearchModal'\nimport AnalysisFilterItem from './AnalysisFilterItem'\nimport AnalysisFilterGroup from './AnalysisFilterGroup'\nimport { convertDateRangeTypeToValue } from '../../shared/utils'\n\nconst AddIcon = getIcon('add')\n\ninterface AnalysisFilterSectionProps {\n /** Current filters */\n filters: Filter[]\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback when filters change */\n onFiltersChange: (filters: Filter[]) => void\n /** Callback when a field is dropped from another section */\n onFieldDropped?: (field: string) => void\n}\n\n/**\n * Check if a filter is a simple filter (has member property)\n */\nfunction isSimpleFilter(filter: Filter): filter is SimpleFilter {\n return 'member' in filter && typeof (filter as SimpleFilter).member === 'string'\n}\n\n/**\n * Check if a filter is a group filter\n */\nfunction isGroupFilter(filter: Filter): filter is GroupFilter {\n return 'type' in filter && ((filter as GroupFilter).type === 'and' || (filter as GroupFilter).type === 'or')\n}\n\n/**\n * Count all simple filters in a filter tree\n */\nfunction countFilters(filters: Filter[]): number {\n let count = 0\n for (const filter of filters) {\n if (isSimpleFilter(filter)) {\n count++\n } else if (isGroupFilter(filter)) {\n count += countFilters(filter.filters)\n }\n }\n return count\n}\n\n/**\n * Get all simple filter member names from a filter tree\n */\nfunction getSelectedFields(filters: Filter[]): string[] {\n const fields: string[] = []\n for (const filter of filters) {\n if (isSimpleFilter(filter)) {\n fields.push(filter.member)\n } else if (isGroupFilter(filter)) {\n fields.push(...getSelectedFields(filter.filters))\n }\n }\n return fields\n}\n\n/**\n * Add a filter at a specific path in the filter tree\n * Path is an array of indices, e.g., [0, 2] means filters[0].filters[2]\n */\nfunction addFilterAtPath(filters: Filter[], path: number[], newFilter: SimpleFilter): Filter[] {\n if (path.length === 0) {\n // Add to root level\n if (filters.length === 0) {\n return [newFilter]\n } else if (filters.length === 1 && isSimpleFilter(filters[0])) {\n // Wrap in AND group\n return [{ type: 'and', filters: [filters[0], newFilter] }]\n } else if (filters.length === 1 && isGroupFilter(filters[0])) {\n // Add to existing group\n return [{\n ...filters[0],\n filters: [...filters[0].filters, newFilter]\n }]\n } else {\n // Wrap all in AND group\n return [{ type: 'and', filters: [...filters, newFilter] }]\n }\n }\n\n // Navigate to the target group and add\n const [firstIndex, ...restPath] = path\n const newFilters = [...filters]\n const targetFilter = newFilters[firstIndex]\n\n if (isGroupFilter(targetFilter)) {\n if (restPath.length === 0) {\n // Add to this group\n newFilters[firstIndex] = {\n ...targetFilter,\n filters: [...targetFilter.filters, newFilter]\n }\n } else {\n // Recurse deeper\n newFilters[firstIndex] = {\n ...targetFilter,\n filters: addFilterAtPath(targetFilter.filters, restPath, newFilter)\n }\n }\n }\n\n return newFilters\n}\n\nexport default function AnalysisFilterSection({\n filters,\n schema,\n onFiltersChange,\n onFieldDropped\n}: AnalysisFilterSectionProps) {\n const [showFieldModal, setShowFieldModal] = useState(false)\n const [isDragOver, setIsDragOver] = useState(false)\n // Track which group we're adding a filter to (path of indices, empty = root)\n const pendingAddPath = useRef<number[]>([])\n\n // Get total filter count for display\n const totalFilterCount = countFilters(filters)\n\n // Handle drag over for drop zone\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDragOver(true)\n }, [])\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDragOver(false)\n }, [])\n\n const handleDrop = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDragOver(false)\n\n try {\n const data = JSON.parse(e.dataTransfer.getData('text/plain'))\n if (data.field && onFieldDropped) {\n onFieldDropped(data.field)\n }\n } catch {\n // Ignore invalid drop data\n }\n }, [onFieldDropped])\n\n // Get selected field names for the modal\n const selectedFields = getSelectedFields(filters)\n\n // Handle adding a new filter via field selection\n const handleFieldSelected = useCallback(\n (field: MetaField, _fieldType: 'measure' | 'dimension' | 'timeDimension', _cubeName: string) => {\n // Determine default operator based on field type\n const isTime = field.type === 'time'\n const defaultOperator = isTime ? 'inDateRange' : 'equals'\n\n // Create new filter with appropriate defaults\n const newFilter: SimpleFilter = {\n member: field.name,\n operator: defaultOperator,\n values: []\n }\n\n // For time fields with inDateRange, set a default dateRange so the filter is immediately active\n if (isTime && defaultOperator === 'inDateRange') {\n (newFilter as any).dateRange = convertDateRangeTypeToValue('this_month')\n }\n\n // Add filter at the pending path\n const updatedFilters = addFilterAtPath(filters, pendingAddPath.current, newFilter)\n onFiltersChange(updatedFilters)\n\n setShowFieldModal(false)\n pendingAddPath.current = []\n },\n [filters, onFiltersChange]\n )\n\n // Handle updating a top-level filter\n const handleUpdateTopLevelFilter = useCallback(\n (index: number, newFilter: Filter) => {\n const newFilters = [...filters]\n newFilters[index] = newFilter\n onFiltersChange(newFilters)\n },\n [filters, onFiltersChange]\n )\n\n // Handle removing a top-level filter\n const handleRemoveTopLevelFilter = useCallback(\n (index: number) => {\n const newFilters = filters.filter((_, i) => i !== index)\n\n // If we have a single group with one filter, unwrap it\n if (newFilters.length === 1 && isGroupFilter(newFilters[0])) {\n const group = newFilters[0]\n if (group.filters.length === 1) {\n onFiltersChange([group.filters[0]])\n return\n }\n }\n\n onFiltersChange(newFilters)\n },\n [filters, onFiltersChange]\n )\n\n // Handle clearing all filters\n const handleClearAll = useCallback(() => {\n onFiltersChange([])\n }, [onFiltersChange])\n\n // Handle add filter button at root level\n const handleAddFilterClick = useCallback(() => {\n pendingAddPath.current = []\n setShowFieldModal(true)\n }, [])\n\n // Create a handler for adding filters at a specific path\n // The handler receives an optional relativePath from nested groups\n const createAddFilterHandler = useCallback((basePath: number[]) => {\n return (relativePath: number[] = []) => {\n pendingAddPath.current = [...basePath, ...relativePath]\n setShowFieldModal(true)\n }\n }, [])\n\n // Render a single filter (SimpleFilter or GroupFilter)\n const renderFilter = (filter: Filter, index: number, parentPath: number[] = []) => {\n const currentPath = [...parentPath, index]\n\n if (isSimpleFilter(filter)) {\n return (\n <AnalysisFilterItem\n key={`filter-${currentPath.join('-')}`}\n filter={filter}\n schema={schema}\n onUpdate={(newFilter) => handleUpdateTopLevelFilter(index, newFilter)}\n onRemove={() => handleRemoveTopLevelFilter(index)}\n />\n )\n } else if (isGroupFilter(filter)) {\n return (\n <AnalysisFilterGroup\n key={`group-${currentPath.join('-')}`}\n group={filter}\n schema={schema}\n onUpdate={(newGroup) => handleUpdateTopLevelFilter(index, newGroup)}\n onRemove={() => handleRemoveTopLevelFilter(index)}\n onAddFilter={createAddFilterHandler(currentPath)}\n hideRemoveButton={filters.length === 1}\n />\n )\n }\n return null\n }\n\n return (\n <div>\n {/* Header - entire row is clickable to add filter */}\n <button\n onClick={handleAddFilterClick}\n className=\"flex items-center justify-between mb-3 w-full py-1 px-2 -ml-2 rounded-lg hover:bg-dc-primary/10 transition-colors group\"\n title=\"Add filter\"\n >\n <SectionHeading>\n Filter\n {totalFilterCount > 0 && (\n <span className=\"ml-1.5 text-xs font-normal text-dc-text-muted normal-case tracking-normal\">\n ({totalFilterCount})\n </span>\n )}\n </SectionHeading>\n <div className=\"flex items-center gap-2\">\n {totalFilterCount > 0 && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation()\n handleClearAll()\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.stopPropagation()\n handleClearAll()\n }\n }}\n className=\"text-xs text-dc-text-muted hover:text-dc-error underline cursor-pointer\"\n >\n Clear all\n </span>\n )}\n <AddIcon className=\"w-5 h-5 text-dc-text-secondary group-hover:text-dc-primary transition-colors\" />\n </div>\n </button>\n\n {/* Drop Zone Container - Only wraps content, not header */}\n <div\n onDragOver={onFieldDropped ? handleDragOver : undefined}\n onDragLeave={onFieldDropped ? handleDragLeave : undefined}\n onDrop={onFieldDropped ? handleDrop : undefined}\n className={`p-2 -mx-2 rounded-lg border-2 border-dashed transition-all ${\n isDragOver\n ? 'border-dc-primary bg-dc-primary/5'\n : 'border-transparent'\n }`}\n >\n {/* Filter List - Hierarchical Rendering */}\n {filters.length === 0 ? (\n <p className={`text-sm ${isDragOver ? 'text-dc-primary font-medium' : 'text-dc-text-muted'}`}>\n {isDragOver ? 'Drop to add filter' : 'No filters applied'}\n </p>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {filters.map((filter, index) => renderFilter(filter, index))}\n </div>\n )}\n </div>\n\n {/* Field Search Modal - mode 'filter' shows all fields (measures + dimensions) */}\n <FieldSearchModal\n isOpen={showFieldModal}\n onClose={() => {\n setShowFieldModal(false)\n pendingAddPath.current = []\n }}\n onSelect={handleFieldSelected}\n mode=\"filter\"\n schema={schema}\n selectedFields={selectedFields}\n />\n </div>\n )\n}\n","/**\n * AnalysisAxisDropZone Component\n *\n * A styled version of AxisDropZone that matches the Query Panel card styling.\n * Used in the Analysis Builder's Chart tab for configuring chart axes.\n *\n * Key differences from AxisDropZone:\n * - Vertical card layout instead of inline chips\n * - Two-line display (title + cube name)\n * - Colored icon boxes for measures, plain icons for dimensions\n * - Hidden-on-hover remove buttons\n */\n\nimport { useState, useCallback, useRef, useEffect, DragEvent } from 'react'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\nimport type { AxisDropZoneConfig } from '../../charts/chartConfigs'\n\nconst CloseIcon = getIcon('close')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\n\ninterface FieldMeta {\n title?: string\n shortTitle?: string\n cubeName: string\n type: 'measure' | 'dimension' | 'timeDimension'\n measureType?: string\n}\n\ninterface AnalysisAxisDropZoneProps {\n config: AxisDropZoneConfig\n fields: string[]\n onDrop: (e: DragEvent<HTMLDivElement>, toKey: string) => void\n onRemove: (field: string, fromKey: string) => void\n onDragStart: (\n e: DragEvent<HTMLDivElement>,\n field: string,\n fromKey: string,\n fromIndex?: number\n ) => void\n onDragEnd?: (e: DragEvent<HTMLDivElement>) => void\n onDragOver: (e: DragEvent<HTMLDivElement>) => void\n onReorder?: (fromIndex: number, toIndex: number, axisKey: string) => void\n draggedItem?: { field: string; fromAxis: string; fromIndex?: number } | null\n getFieldMeta?: (field: string) => FieldMeta\n // Dual Y-axis support\n yAxisAssignment?: Record<string, 'left' | 'right'>\n onYAxisAssignmentChange?: (field: string, axis: 'left' | 'right') => void\n}\n\nexport default function AnalysisAxisDropZone({\n config,\n fields,\n onDrop,\n onRemove,\n onDragStart,\n onDragEnd,\n onDragOver,\n onReorder,\n draggedItem,\n getFieldMeta,\n yAxisAssignment,\n onYAxisAssignmentChange\n}: AnalysisAxisDropZoneProps) {\n const { key, label, description, mandatory, maxItems, emptyText } = config\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null)\n const [isDraggedOver, setIsDraggedOver] = useState(false)\n const [isReorderDraggedOver, setIsReorderDraggedOver] = useState(false)\n\n // Track the field being dragged from this axis for drag-out-to-remove\n const draggingFieldRef = useRef<string | null>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n // Keep fields in a ref to avoid stale closure issues\n const fieldsRef = useRef(fields)\n fieldsRef.current = fields\n // Keep dropTargetIndex in a ref to avoid stale closure issues in drop handler\n const dropTargetIndexRef = useRef<number | null>(null)\n\n // Calculate acceptance considering what's being dragged\n const getCanAcceptMore = () => {\n let effectiveCount = fields.length\n\n // If we're dragging FROM this axis, we effectively have one less item\n if (draggedItem && draggedItem.fromAxis === key) {\n effectiveCount = Math.max(0, fields.length - 1)\n }\n\n return !maxItems || effectiveCount < maxItems\n }\n\n const getIsFull = () => {\n let effectiveCount = fields.length\n\n // If we're dragging FROM this axis, we effectively have one less item\n if (draggedItem && draggedItem.fromAxis === key) {\n effectiveCount = Math.max(0, fields.length - 1)\n }\n\n return maxItems && effectiveCount >= maxItems\n }\n\n const canAcceptMore = getCanAcceptMore()\n const isFull = getIsFull()\n\n // Add a global drag end listener to reset visual state\n useEffect(() => {\n const handleGlobalDragEnd = () => {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n draggingFieldRef.current = null\n }\n\n document.addEventListener('dragend', handleGlobalDragEnd)\n return () => {\n document.removeEventListener('dragend', handleGlobalDragEnd)\n }\n }, [])\n\n // Clear states when transitioning between different drag operations\n useEffect(() => {\n if (draggedItem) {\n // If we have a dragged item but it's not from this axis, clear reorder state\n if (draggedItem.fromAxis !== key) {\n setIsReorderDraggedOver(false)\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n }\n // If we have a dragged item from this axis, clear regular drag state\n else if (draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n setIsDraggedOver(false)\n }\n } else {\n // No dragged item, clear all states\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }\n }, [draggedItem, key])\n\n // Handle drag over an item - determine drop position based on mouse position\n const handleItemDragOver = useCallback((e: DragEvent<HTMLDivElement>, itemIndex: number) => {\n // Check if this is a reorder operation (same axis)\n if (!draggedItem || draggedItem.fromAxis !== key || draggedItem.fromIndex === undefined) return\n\n e.preventDefault()\n e.stopPropagation()\n\n // Determine if we're in the top or bottom half of the item\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseY = e.clientY - rect.top\n const isTopHalf = mouseY < rect.height / 2\n\n // Calculate target index based on position\n const fromIndex = draggedItem.fromIndex\n let targetIndex = isTopHalf ? itemIndex : itemIndex + 1\n\n // Don't set drop target if it would result in no movement\n if (targetIndex === fromIndex || targetIndex === fromIndex + 1) {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n } else {\n setDropTargetIndex(targetIndex)\n dropTargetIndexRef.current = targetIndex\n setIsReorderDraggedOver(true)\n }\n }, [draggedItem, key])\n\n // Handle drop on an item for reordering\n const handleItemDrop = useCallback((e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n // DON'T stopPropagation here yet - only stop if this is a reorder operation\n\n // Use ref to get current dropTargetIndex (avoids stale closure)\n const currentDropTargetIndex = dropTargetIndexRef.current\n\n // Check if this is a reorder operation (same axis with valid indices)\n const isReorderOperation = draggedItem &&\n draggedItem.fromAxis === key &&\n draggedItem.fromIndex !== undefined &&\n currentDropTargetIndex !== null\n\n if (!isReorderOperation) {\n // Let the event bubble up to container for external drops\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsReorderDraggedOver(false)\n return // Don't stop propagation - container will handle external drops\n }\n\n // This IS a reorder operation - stop propagation and handle it\n e.stopPropagation()\n\n // Adjust target index when dragging down (after splice, indices shift)\n const fromIndex = draggedItem!.fromIndex!\n const adjustedTarget = currentDropTargetIndex > fromIndex\n ? currentDropTargetIndex - 1\n : currentDropTargetIndex\n\n if (onReorder && adjustedTarget !== fromIndex) {\n onReorder(fromIndex, adjustedTarget, key)\n }\n\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsReorderDraggedOver(false)\n }, [draggedItem, key, onReorder])\n\n // Handle drag end - check if dropped outside container to remove\n const handleFieldDragEnd = useCallback((e: DragEvent<HTMLDivElement>, field: string) => {\n const container = containerRef.current\n if (container && draggingFieldRef.current === field) {\n const rect = container.getBoundingClientRect()\n const isInside =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom\n\n // If dropped outside the container\n if (!isInside) {\n // Use a small delay to let other drop handlers fire first\n // Then check if the field is still in this axis (wasn't moved elsewhere)\n setTimeout(() => {\n // Check using ref to get current fields, avoiding stale closure\n if (fieldsRef.current.includes(field)) {\n onRemove(field, key)\n }\n }, 0)\n }\n }\n\n draggingFieldRef.current = null\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsReorderDraggedOver(false)\n\n onDragEnd?.(e)\n }, [key, onRemove, onDragEnd])\n\n // Calculate transform for gap animation\n const getItemTransform = useCallback((itemIndex: number): string => {\n if (!draggedItem || draggedItem.fromAxis !== key || draggedItem.fromIndex === undefined || dropTargetIndex === null) {\n return ''\n }\n\n const fromIndex = draggedItem.fromIndex\n const gapSize = 40\n\n // If this is the dragged item, no transform needed\n if (itemIndex === fromIndex) return ''\n\n if (fromIndex < dropTargetIndex) {\n // Dragging down\n if (itemIndex >= dropTargetIndex) {\n return `translateY(${gapSize / 2}px)`\n }\n } else {\n // Dragging up\n if (itemIndex >= dropTargetIndex && itemIndex < fromIndex) {\n return `translateY(${gapSize / 2}px)`\n }\n }\n\n return ''\n }, [draggedItem, key, dropTargetIndex])\n\n // Determine if gap indicator should show\n const shouldShowGapIndicator = useCallback((itemIndex: number): boolean => {\n if (!draggedItem || draggedItem.fromAxis !== key || dropTargetIndex === null) return false\n return itemIndex === dropTargetIndex\n }, [draggedItem, key, dropTargetIndex])\n\n // Get default field meta from field name\n const getDefaultFieldMeta = (field: string): FieldMeta => {\n const parts = field.split('.')\n const cubeName = parts[0] || field\n const fieldName = parts[1] || field\n\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: 'dimension' // Default assumption\n }\n }\n\n // Render icon based on field type\n const renderFieldIcon = (meta: FieldMeta) => {\n if (meta.type === 'measure') {\n // Measures get colored icon box with type-specific icon\n const IconComponent = getMeasureTypeIcon(meta.measureType || 'count') || MeasureIcon\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-measure text-dc-measure-text flex-shrink-0\">\n <IconComponent className=\"w-4 h-4\" />\n </span>\n )\n } else if (meta.type === 'timeDimension') {\n // Time dimensions get colored background matching field selector\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-time-dimension text-dc-time-dimension-text flex-shrink-0\">\n <TimeDimensionIcon className=\"w-4 h-4\" />\n </span>\n )\n } else {\n // Regular dimensions get colored background matching field selector\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-dimension text-dc-dimension-text flex-shrink-0\">\n <DimensionIcon className=\"w-4 h-4\" />\n </span>\n )\n }\n }\n\n return (\n <div className=\"mb-3\">\n {/* Header */}\n <div className=\"mb-2\">\n <h4 className=\"text-sm font-medium text-dc-text flex items-center\">\n {label}\n {mandatory && <span className=\"text-dc-error ml-1\">*</span>}\n </h4>\n {description && <div className=\"text-xs text-dc-text-muted mt-0.5\">{description}</div>}\n </div>\n\n {/* Drop Zone Container */}\n <div\n ref={containerRef}\n data-axis-container={key}\n className={`min-h-[48px] border-2 border-dashed rounded-lg p-2 transition-all duration-200 ${\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'shadow-sm border-solid'\n : isFull\n ? 'bg-dc-surface-secondary'\n : 'bg-dc-surface-secondary hover:bg-dc-surface-hover'\n }`}\n style={{\n borderColor:\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'var(--dc-primary)'\n : 'var(--dc-border)',\n backgroundColor:\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'rgba(var(--dc-primary-rgb), 0.1)'\n : undefined\n }}\n onDragOver={(e) => {\n // Check if this is a reorder operation (same axis) - if so, don't interfere\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n return\n }\n\n // Simple acceptance check - either we have space OR it's a single-item replacement\n const canAccept = canAcceptMore || maxItems === 1\n\n if (canAccept) {\n setIsDraggedOver(true)\n onDragOver(e)\n } else {\n e.preventDefault()\n e.dataTransfer.dropEffect = 'none'\n }\n }}\n onDragLeave={(e) => {\n // Check if we're truly leaving the container\n const rect = e.currentTarget.getBoundingClientRect()\n const isLeavingContainer =\n e.clientX < rect.left ||\n e.clientX > rect.right ||\n e.clientY < rect.top ||\n e.clientY > rect.bottom\n\n // Also check if the related target is outside this container\n const relatedTarget = e.relatedTarget as Element | null\n const isRelatedTargetOutside = relatedTarget && !e.currentTarget.contains(relatedTarget)\n\n if (isLeavingContainer || isRelatedTargetOutside || e.currentTarget === e.target) {\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }\n }}\n onDrop={(e) => {\n // Check if this is a reorder operation (same axis) - if so, don't interfere\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n return\n }\n\n // Simple acceptance check - either we have space OR it's a single-item replacement\n const shouldAcceptDrop = canAcceptMore || maxItems === 1\n\n if (shouldAcceptDrop) {\n onDrop(e, key)\n } else {\n e.preventDefault()\n }\n\n // Reset drag state on drop\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }}\n >\n {fields.length === 0 ? (\n <div className=\"text-sm text-dc-text-muted text-center py-2\">\n {isFull ? 'Maximum items reached' : emptyText || `Drop fields here`}\n </div>\n ) : (\n <div\n className=\"space-y-2\"\n onDragOver={(e) => {\n // Allow dropping for reorder operations\n if (draggedItem && draggedItem.fromAxis === key) {\n e.preventDefault()\n }\n }}\n onDrop={(e) => {\n // Handle reorder drops at container level\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n handleItemDrop(e)\n }\n }}\n >\n {fields.map((field, index) => {\n const meta = getFieldMeta ? getFieldMeta(field) : getDefaultFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === key\n const transform = getItemTransform(index)\n const showGapBefore = shouldShowGapIndicator(index)\n\n return (\n <div\n key={`${field}-${index}`}\n className=\"relative\"\n style={{\n transform,\n transition: draggedItem && draggedItem.fromAxis === key ? 'transform 0.15s ease-out' : 'none'\n }}\n >\n {/* Gap indicator line - shows where item will be inserted */}\n {showGapBefore && (\n <div className=\"absolute -top-5 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n )}\n\n <div\n draggable\n onDragStart={(e) => {\n draggingFieldRef.current = field\n onDragStart(e, field, key, index)\n }}\n onDragEnd={(e) => handleFieldDragEnd(e, field)}\n onDragOver={(e) => handleItemDragOver(e, index)}\n onDrop={handleItemDrop}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg group hover:bg-dc-surface-tertiary transition-colors cursor-move ${\n isBeingDragged ? 'opacity-30 cursor-grabbing' : ''\n }`}\n >\n {/* Icon */}\n {renderFieldIcon(meta)}\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={field}>\n {meta.shortTitle || meta.title || field.split('.').pop()}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n\n {/* L/R Axis Toggle - only for yAxis with dual axis enabled */}\n {config.enableDualAxis && onYAxisAssignmentChange && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n const currentAxis = yAxisAssignment?.[field] || 'left'\n onYAxisAssignmentChange(field, currentAxis === 'left' ? 'right' : 'left')\n }}\n className={`px-1.5 py-0.5 text-xs font-medium rounded transition-colors flex-shrink-0 ${\n (yAxisAssignment?.[field] || 'left') === 'left'\n ? 'bg-dc-info-bg text-dc-info hover:opacity-80'\n : 'bg-dc-accent-bg text-dc-accent hover:opacity-80'\n }`}\n title={`Y-Axis: ${(yAxisAssignment?.[field] || 'left') === 'left' ? 'Left' : 'Right'} (click to toggle)`}\n >\n {(yAxisAssignment?.[field] || 'left') === 'left' ? 'L' : 'R'}\n </button>\n )}\n\n {/* Remove Button - hidden until hover */}\n <button\n type=\"button\"\n onClick={() => onRemove(field, key)}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title={`Remove from ${label}`}\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n )\n })}\n {/* Gap indicator after the last item - shows when dropping at end */}\n {draggedItem && draggedItem.fromAxis === key && dropTargetIndex === fields.length && (\n <div className=\"relative h-2\">\n <div className=\"absolute top-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n </div>\n )}\n {/* Handle drop at the end of the list for reordering */}\n {draggedItem && draggedItem.fromAxis === key && fields.length > 1 && (\n <div\n className=\"h-6\"\n onDragOver={(e) => {\n if (draggedItem.fromIndex !== undefined) {\n e.preventDefault()\n const lastIndex = fields.length\n if (dropTargetIndexRef.current !== lastIndex && draggedItem.fromIndex !== lastIndex - 1) {\n setDropTargetIndex(lastIndex)\n dropTargetIndexRef.current = lastIndex\n setIsReorderDraggedOver(true)\n }\n }\n }}\n onDrop={handleItemDrop}\n />\n )}\n </div>\n )}\n </div>\n\n {mandatory && fields.length === 0 && (\n <div className=\"text-xs text-dc-error mt-1\">This field is required</div>\n )}\n </div>\n )\n}\n","import { barChartConfig } from '../components/charts/BarChart.config'\nimport { lineChartConfig } from '../components/charts/LineChart.config'\nimport { areaChartConfig } from '../components/charts/AreaChart.config'\nimport { pieChartConfig } from '../components/charts/PieChart.config'\nimport { scatterChartConfig } from '../components/charts/ScatterChart.config'\nimport { bubbleChartConfig } from '../components/charts/BubbleChart.config'\nimport { radarChartConfig } from '../components/charts/RadarChart.config'\nimport { radialBarChartConfig } from '../components/charts/RadialBarChart.config'\nimport { treemapChartConfig } from '../components/charts/TreeMapChart.config'\nimport { dataTableConfig } from '../components/charts/DataTable.config'\nimport { activityGridChartConfig } from '../components/charts/ActivityGridChart.config'\nimport { kpiNumberConfig } from '../components/charts/KpiNumber.config'\nimport { kpiDeltaConfig } from '../components/charts/KpiDelta.config'\nimport { kpiTextConfig } from '../components/charts/KpiText.config'\nimport { markdownConfig } from '../components/charts/MarkdownChart.config'\nimport { funnelChartConfig } from '../components/charts/FunnelChart.config'\nimport type { ChartConfigRegistry } from './chartConfigs'\n\n/**\n * Registry of all chart type configurations\n */\nexport const chartConfigRegistry: ChartConfigRegistry = {\n bar: barChartConfig,\n line: lineChartConfig,\n area: areaChartConfig,\n pie: pieChartConfig,\n scatter: scatterChartConfig,\n bubble: bubbleChartConfig,\n radar: radarChartConfig,\n radialBar: radialBarChartConfig,\n treemap: treemapChartConfig,\n table: dataTableConfig,\n activityGrid: activityGridChartConfig,\n kpiNumber: kpiNumberConfig,\n kpiDelta: kpiDeltaConfig,\n kpiText: kpiTextConfig,\n markdown: markdownConfig,\n funnel: funnelChartConfig,\n}","import { useState } from 'react'\nimport { chartConfigRegistry } from '../charts/chartConfigRegistry'\nimport type { ChartType } from '../types'\nimport type { ChartAvailabilityMap } from '../shared/chartDefaults'\n\ninterface ChartTypeSelectorProps {\n selectedType: ChartType\n onTypeChange: (type: ChartType) => void\n className?: string\n /** Compact mode for narrow containers - uses 2 columns and constrains width */\n compact?: boolean\n /** Map of chart type availability - when provided, unavailable charts are disabled */\n availability?: ChartAvailabilityMap\n}\n\n// Chart type display names (defined outside component to avoid recreation)\nconst chartTypeLabels: Record<ChartType, string> = {\n activityGrid: 'Activity Grid',\n area: 'Area Chart',\n bar: 'Bar Chart',\n bubble: 'Bubble Chart',\n funnel: 'Funnel Chart',\n kpiDelta: 'KPI Delta',\n kpiNumber: 'KPI Number',\n kpiText: 'KPI Text',\n line: 'Line Chart',\n markdown: 'Markdown',\n pie: 'Pie Chart',\n radar: 'Radar Chart',\n radialBar: 'Radial Bar Chart',\n scatter: 'Scatter Plot',\n table: 'Data Table',\n treemap: 'TreeMap'\n}\n\nexport default function ChartTypeSelector({\n selectedType,\n onTypeChange,\n className = '',\n compact = false,\n availability\n}: ChartTypeSelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n\n // Get chart types and sort alphabetically by label\n const chartTypes = (Object.entries(chartConfigRegistry) as [ChartType, typeof chartConfigRegistry[keyof typeof chartConfigRegistry]][])\n .sort((a, b) => {\n const labelA = chartTypeLabels[a[0]] || a[0]\n const labelB = chartTypeLabels[b[0]] || b[0]\n return labelA.localeCompare(labelB)\n })\n\n const selectedConfig = chartConfigRegistry[selectedType]\n const SelectedIcon = selectedConfig?.icon\n const selectedLabel = chartTypeLabels[selectedType]\n\n return (\n <div className={`${className} relative`}>\n {/* Dropdown Button */}\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"w-full flex items-center justify-between px-3 py-2 border border-dc-border rounded-md bg-dc-surface hover:bg-dc-surface-hover focus:outline-hidden focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n >\n <div className=\"flex items-center space-x-2\">\n {SelectedIcon && (\n <SelectedIcon className=\"h-5 w-5 text-dc-text-secondary\" />\n )}\n <span className=\"text-sm font-medium text-dc-text\">{selectedLabel}</span>\n </div>\n <svg\n className={`h-4 w-4 text-dc-text-muted transform transition-transform ${isOpen ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n\n {/* Dropdown Menu - Grid Layout */}\n {isOpen && (\n <div className={`absolute z-10 mt-1 w-full bg-dc-surface border border-dc-border rounded-md shadow-lg max-h-80 overflow-auto ${compact ? '' : 'min-w-max'}`}>\n <div className=\"p-2\">\n <div className={`grid gap-1.5 ${compact ? 'grid-cols-2' : 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-4'}`}>\n {chartTypes.map(([type, config]) => {\n const IconComponent = config.icon\n const label = chartTypeLabels[type]\n const isSelected = selectedType === type\n const description = config.description\n const useCase = config.useCase\n\n // Check availability if provided\n const chartAvailability = availability?.[type]\n const isAvailable = chartAvailability?.available ?? true\n const unavailableReason = chartAvailability?.reason\n\n // Build tooltip text - show unavailable reason if not available, otherwise show description\n const tooltipText = !isAvailable && unavailableReason\n ? unavailableReason\n : [description, useCase].filter(Boolean).join('. ')\n\n return (\n <button\n key={type}\n type=\"button\"\n onClick={() => {\n if (!isAvailable) return // Don't allow clicking disabled charts\n onTypeChange(type)\n setIsOpen(false)\n }}\n disabled={!isAvailable}\n className={`\n relative p-1.5 rounded border transition-colors duration-150\n text-left group min-h-[30px] flex items-center justify-start\n ${!isAvailable\n ? 'opacity-50 cursor-not-allowed bg-dc-surface'\n : isSelected\n ? 'bg-dc-surface-secondary'\n : 'bg-dc-surface hover:bg-dc-surface-hover'\n }\n `}\n style={{\n borderColor: isSelected && isAvailable ? 'var(--dc-primary)' : 'var(--dc-border)'\n }}\n title={tooltipText}\n >\n <div className=\"flex items-center space-x-1.5\">\n {/* Icon */}\n {IconComponent && (\n <IconComponent\n className={`h-4 w-4 shrink-0 ${\n !isAvailable\n ? 'text-dc-text-muted'\n : isSelected\n ? 'text-dc-text'\n : 'text-dc-text-secondary'\n }`}\n />\n )}\n\n {/* Chart name */}\n <span className={`text-xs font-medium leading-tight truncate ${\n !isAvailable\n ? 'text-dc-text-muted'\n : isSelected\n ? ''\n : 'text-dc-text'\n }`}\n style={isSelected && isAvailable ? { color: 'var(--dc-primary)' } : undefined}>\n {label}\n </span>\n </div>\n\n {/* Selected indicator - smaller dot */}\n {isSelected && isAvailable && (\n <div className=\"absolute top-0.5 right-0.5\">\n <div className=\"w-1.5 h-1.5 rounded-full\" style={{ backgroundColor: 'var(--dc-primary)' }}></div>\n </div>\n )}\n </button>\n )\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n )\n}","/**\n * AnalysisChartConfigPanel Component\n *\n * A single-column chart configuration panel for the AnalysisBuilder.\n * Uses fields from the Query tab (metrics/breakdowns) as available fields.\n * Renders axis drop zones and display options based on chart type.\n */\n\nimport { useMemo, useEffect, useState, useCallback, DragEvent } from 'react'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\nimport SectionHeading from './SectionHeading'\nimport AnalysisAxisDropZone from './AnalysisAxisDropZone'\nimport ChartTypeSelector from '../ChartTypeSelector'\nimport { chartConfigRegistry } from '../../charts/chartConfigRegistry'\nimport { getChartConfig } from '../../charts/chartConfigs'\nimport type { ChartType, ChartAxisConfig } from '../../types'\nimport type { MetricItem, BreakdownItem } from './types'\nimport type { ChartAvailabilityMap } from '../../shared/chartDefaults'\nimport type { MetaResponse } from '../../shared/types'\n\nconst MeasureIcon = getIcon('measure')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\n\ninterface AnalysisChartConfigPanelProps {\n chartType: ChartType\n chartConfig: ChartAxisConfig\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n /** Schema metadata for resolving field titles */\n schema?: MetaResponse | null\n /** Map of chart type availability for disabling unavailable chart types */\n chartAvailability?: ChartAvailabilityMap\n onChartTypeChange: (type: ChartType) => void\n onChartConfigChange: (config: ChartAxisConfig) => void\n}\n\nexport default function AnalysisChartConfigPanel({\n chartType,\n chartConfig,\n metrics,\n breakdowns,\n schema,\n chartAvailability,\n onChartTypeChange,\n onChartConfigChange\n}: AnalysisChartConfigPanelProps) {\n // Track currently dragging item for immediate state updates\n const [draggedItem, setDraggedItem] = useState<{\n field: string\n fromAxis: string\n fromIndex?: number\n } | null>(null)\n\n // Derive available fields from metrics and breakdowns\n const availableFields = useMemo(\n () => ({\n measures: metrics.map((m) => m.field),\n dimensions: breakdowns.filter((b) => !b.isTimeDimension).map((b) => b.field),\n timeDimensions: breakdowns.filter((b) => b.isTimeDimension).map((b) => b.field)\n }),\n [metrics, breakdowns]\n )\n\n // Get configuration for current chart type\n const chartTypeConfig = useMemo(\n () => getChartConfig(chartType, chartConfigRegistry),\n [chartType]\n )\n\n // Check if this chart type skips queries\n const shouldSkipQuery = chartTypeConfig.skipQuery === true\n\n // Get fields for each drop zone\n const getFieldsForDropZone = useCallback((key: string): string[] => {\n const value = chartConfig[key as keyof ChartAxisConfig]\n const result = Array.isArray(value)\n ? value\n : typeof value === 'string'\n ? [value]\n : []\n return result\n }, [chartConfig])\n\n // Clean up chart config when available fields change\n useEffect(() => {\n const allAvailableFields = [\n ...availableFields.dimensions,\n ...availableFields.timeDimensions,\n ...availableFields.measures\n ]\n\n let hasChanges = false\n const newConfig = { ...chartConfig }\n\n // Check each axis and remove fields that are no longer available\n chartTypeConfig.dropZones.forEach((dropZone) => {\n const currentFields = getFieldsForDropZone(dropZone.key)\n const validFields = currentFields.filter((field) => allAvailableFields.includes(field))\n\n if (validFields.length !== currentFields.length) {\n hasChanges = true\n if (validFields.length === 0) {\n // Remove the axis property entirely if no valid fields remain\n delete newConfig[dropZone.key as keyof ChartAxisConfig]\n } else if (dropZone.maxItems === 1) {\n // Single field axis - always store as string\n newConfig[dropZone.key as keyof ChartAxisConfig] = validFields[0] as any\n } else {\n // Multi-field axis - always store as array\n newConfig[dropZone.key as keyof ChartAxisConfig] = validFields as any\n }\n }\n })\n\n if (hasChanges) {\n onChartConfigChange(newConfig)\n }\n }, [availableFields, chartConfig, chartTypeConfig.dropZones, onChartConfigChange, getFieldsForDropZone])\n\n // Helper to determine field type and styling\n const getFieldType = (field: string): 'dimension' | 'timeDimension' | 'measure' => {\n if (availableFields.measures.includes(field)) return 'measure'\n if (availableFields.timeDimensions.includes(field)) return 'timeDimension'\n return 'dimension'\n }\n\n // Helper to find field metadata from schema\n const findFieldMeta = (fieldName: string) => {\n if (!schema?.cubes) return null\n\n const [cubeName] = fieldName.split('.')\n const cube = schema.cubes.find((c) => c.name === cubeName)\n if (!cube) return null\n\n // Check measures first, then dimensions\n const measure = cube.measures?.find((m) => m.name === fieldName)\n if (measure) return { ...measure, fieldType: 'measure' as const }\n\n const dimension = cube.dimensions?.find((d) => d.name === fieldName)\n if (dimension) return { ...dimension, fieldType: dimension.type === 'time' ? 'timeDimension' as const : 'dimension' as const }\n\n return null\n }\n\n // Get field metadata for display in AnalysisAxisDropZone\n const getFieldMeta = (field: string) => {\n const fieldType = getFieldType(field)\n const parts = field.split('.')\n const cubeName = parts[0] || field\n const fieldName = parts[1] || field\n\n // Look up field metadata from schema\n const schemaMeta = findFieldMeta(field)\n\n // Try to find the field in breakdowns for isTimeDimension flag\n const breakdownItem = breakdowns.find((b) => b.field === field)\n\n if (schemaMeta) {\n return {\n title: schemaMeta.title || fieldName,\n shortTitle: schemaMeta.shortTitle || schemaMeta.title || fieldName,\n cubeName,\n type: schemaMeta.fieldType,\n measureType: schemaMeta.fieldType === 'measure' ? schemaMeta.type : undefined\n }\n }\n\n // Fallback when schema lookup fails\n if (breakdownItem) {\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: breakdownItem.isTimeDimension ? ('timeDimension' as const) : ('dimension' as const)\n }\n }\n\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: fieldType\n }\n }\n\n // Drag and drop handlers\n const handleDragStart = (\n e: DragEvent<HTMLDivElement>,\n field: string,\n fromAxis: string,\n fromIndex?: number\n ) => {\n e.dataTransfer.setData('text/plain', JSON.stringify({ field, fromAxis, fromIndex }))\n setDraggedItem({ field, fromAxis, fromIndex })\n }\n\n const handleDragOver = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n }\n\n const handleDragEnd = () => {\n setDraggedItem(null)\n }\n\n const handleDrop = (e: DragEvent<HTMLDivElement>, toAxis: string) => {\n e.preventDefault()\n const data = JSON.parse(e.dataTransfer.getData('text/plain'))\n const { field, fromAxis } = data\n\n const newConfig = { ...chartConfig }\n\n // Remove from old location if moving between axes\n if (fromAxis !== 'available' && fromAxis !== toAxis) {\n const fromValue = newConfig[fromAxis as keyof ChartAxisConfig]\n if (Array.isArray(fromValue)) {\n const filteredValue = fromValue.filter((f) => f !== field)\n if (filteredValue.length === 0) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n } else {\n newConfig[fromAxis as keyof ChartAxisConfig] = filteredValue as any\n }\n } else if (fromValue === field) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n }\n }\n\n // Add to new location\n const toValue = newConfig[toAxis as keyof ChartAxisConfig]\n const dropZoneConfig = chartTypeConfig.dropZones.find((dz) => dz.key === toAxis)\n\n if (dropZoneConfig?.maxItems === 1) {\n // Single field - always store as string\n newConfig[toAxis as keyof ChartAxisConfig] = field as any\n } else {\n // Multiple fields - always store as array\n if (Array.isArray(toValue)) {\n if (!toValue.includes(field)) {\n newConfig[toAxis as keyof ChartAxisConfig] = [...toValue, field] as any\n }\n } else {\n newConfig[toAxis as keyof ChartAxisConfig] = [field] as any\n }\n }\n\n // Apply default yAxisAssignment when adding to yAxis with dual axis enabled\n if (toAxis === 'yAxis' && dropZoneConfig?.enableDualAxis) {\n const currentYAxisFields = Array.isArray(newConfig.yAxis) ? newConfig.yAxis : [field]\n const fieldIndex = currentYAxisFields.indexOf(field)\n // Default: 1st field = left, 2nd field = right, 3rd+ = left\n if (!newConfig.yAxisAssignment?.[field]) {\n newConfig.yAxisAssignment = {\n ...newConfig.yAxisAssignment,\n [field]: fieldIndex === 1 ? 'right' : 'left'\n }\n }\n }\n\n setDraggedItem(null)\n onChartConfigChange(newConfig)\n }\n\n const handleRemoveFromAxis = (field: string, fromAxis: string) => {\n const newConfig = { ...chartConfig }\n const value = newConfig[fromAxis as keyof ChartAxisConfig]\n\n if (Array.isArray(value)) {\n const filteredValue = value.filter((f) => f !== field)\n if (filteredValue.length === 0) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n } else {\n newConfig[fromAxis as keyof ChartAxisConfig] = filteredValue as any\n }\n } else if (value === field) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n }\n\n // Clean up yAxisAssignment when removing from yAxis\n if (fromAxis === 'yAxis' && newConfig.yAxisAssignment?.[field]) {\n const { [field]: _removed, ...rest } = newConfig.yAxisAssignment\n newConfig.yAxisAssignment = Object.keys(rest).length > 0 ? rest : undefined\n }\n\n onChartConfigChange(newConfig)\n }\n\n const handleReorder = (fromIndex: number, toIndex: number, axisKey: string) => {\n const newConfig = { ...chartConfig }\n const value = newConfig[axisKey as keyof ChartAxisConfig]\n\n // Only reorder if we have an array with multiple items\n if (Array.isArray(value) && value.length > 1 && fromIndex !== toIndex) {\n const newArray = [...value]\n const [movedItem] = newArray.splice(fromIndex, 1)\n newArray.splice(toIndex, 0, movedItem)\n newConfig[axisKey as keyof ChartAxisConfig] = newArray as any\n\n setDraggedItem(null)\n onChartConfigChange(newConfig)\n }\n }\n\n // Handler for Y-axis assignment changes (dual Y-axis support)\n const handleYAxisAssignmentChange = useCallback(\n (field: string, axis: 'left' | 'right') => {\n onChartConfigChange({\n ...chartConfig,\n yAxisAssignment: {\n ...chartConfig.yAxisAssignment,\n [field]: axis\n }\n })\n },\n [chartConfig, onChartConfigChange]\n )\n\n // Get unassigned fields (fields selected in Query tab but not yet assigned to chart axes)\n const getUnassignedFields = () => {\n const assignedFields = new Set<string>()\n chartTypeConfig.dropZones.forEach((dz) => {\n getFieldsForDropZone(dz.key).forEach((field) => assignedFields.add(field))\n })\n\n // Exclude the currently dragged field only if it's being dragged FROM a configured axis\n if (draggedItem && draggedItem.fromAxis !== 'available') {\n assignedFields.add(draggedItem.field)\n }\n\n return {\n dimensions: availableFields.dimensions.filter((f) => !assignedFields.has(f)),\n timeDimensions: availableFields.timeDimensions.filter((f) => !assignedFields.has(f)),\n measures: availableFields.measures.filter((f) => !assignedFields.has(f))\n }\n }\n\n const unassignedFields = getUnassignedFields()\n const hasUnassignedFields =\n unassignedFields.dimensions.length > 0 ||\n unassignedFields.timeDimensions.length > 0 ||\n unassignedFields.measures.length > 0\n\n return (\n <div className=\"space-y-6\">\n {/* Chart Type Selector */}\n <div>\n <SectionHeading className=\"mb-2\">Chart Type</SectionHeading>\n <ChartTypeSelector\n selectedType={chartType}\n onTypeChange={onChartTypeChange}\n availability={chartAvailability}\n compact\n />\n </div>\n\n {/* Chart Axis Configuration - Dynamic Drop Zones */}\n {!shouldSkipQuery && chartTypeConfig.dropZones.length > 0 && (\n <div>\n <SectionHeading className=\"mb-2\">\n Chart Configuration\n </SectionHeading>\n <div className=\"space-y-1\">\n {chartTypeConfig.dropZones.map((dropZone) => (\n <AnalysisAxisDropZone\n key={dropZone.key}\n config={dropZone}\n fields={getFieldsForDropZone(dropZone.key)}\n onDrop={handleDrop}\n onRemove={handleRemoveFromAxis}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onReorder={handleReorder}\n draggedItem={draggedItem}\n getFieldMeta={getFieldMeta}\n yAxisAssignment={chartConfig.yAxisAssignment}\n onYAxisAssignmentChange={\n dropZone.enableDualAxis ? handleYAxisAssignmentChange : undefined\n }\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Unassigned Fields - Show fields from Query tab that haven't been assigned yet */}\n {!shouldSkipQuery && hasUnassignedFields && (\n <div>\n <div className=\"mb-2\">\n <SectionHeading>Unassigned Fields</SectionHeading>\n <div className=\"text-xs text-dc-text-muted mt-0.5\">\n Drag fields to chart axes above\n </div>\n </div>\n <div className=\"border-2 border-dashed border-dc-border rounded-lg p-2 bg-dc-surface-secondary\">\n <div className=\"space-y-2\">\n {/* Measures */}\n {unassignedFields.measures.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n const IconComponent = getMeasureTypeIcon(meta.measureType || 'count') || MeasureIcon\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-measure text-dc-measure-text flex-shrink-0\">\n <IconComponent className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n\n {/* Dimensions */}\n {unassignedFields.dimensions.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-dimension text-dc-dimension-text flex-shrink-0\">\n <DimensionIcon className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n\n {/* Time Dimensions */}\n {unassignedFields.timeDimensions.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-time-dimension text-dc-time-dimension-text flex-shrink-0\">\n <TimeDimensionIcon className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )}\n\n {/* Help text when no fields are available */}\n {!shouldSkipQuery &&\n availableFields.measures.length === 0 &&\n availableFields.dimensions.length === 0 &&\n availableFields.timeDimensions.length === 0 && (\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n <p>Add metrics and breakdowns in the Query tab to configure your chart.</p>\n </div>\n )}\n </div>\n )\n}\n","/**\n * AnalysisDisplayConfigPanel Component\n *\n * A panel for configuring chart display options (legend, grid, tooltip, etc.)\n * Extracted from AnalysisChartConfigPanel to be shown in its own tab.\n */\n\nimport { useMemo, useState, useCallback, useEffect } from 'react'\nimport SectionHeading from './SectionHeading'\nimport { chartConfigRegistry } from '../../charts/chartConfigRegistry'\nimport { getChartConfig } from '../../charts/chartConfigs'\nimport type { ChartType, ChartDisplayConfig, ColorPalette, AxisFormatConfig } from '../../types'\nimport { AxisFormatControls } from '../charts/AxisFormatControls'\n\ninterface AnalysisDisplayConfigPanelProps {\n chartType: ChartType\n displayConfig: ChartDisplayConfig\n colorPalette?: ColorPalette\n onDisplayConfigChange: (config: ChartDisplayConfig) => void\n}\n\n/**\n * StringArrayInput - A textarea that edits an array of strings\n * Uses local state while editing and only updates on blur\n */\nfunction StringArrayInput({\n label,\n value,\n onChange,\n placeholder,\n description,\n}: {\n label: string\n value: string[]\n onChange: (value: string[]) => void\n placeholder?: string\n description?: string\n}) {\n // Local state for textarea editing\n const [localText, setLocalText] = useState(() => value.join('\\n'))\n\n // Sync local state when external value changes (e.g., from undo/redo or load)\n useEffect(() => {\n const externalText = value.join('\\n')\n setLocalText(externalText)\n }, [value])\n\n const handleBlur = useCallback(() => {\n // Convert text to array, filtering empty strings\n const arrayValue = localText\n .split('\\n')\n .map(s => s.trim())\n .filter(s => s.length > 0)\n onChange(arrayValue)\n }, [localText, onChange])\n\n return (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{label}</label>\n <textarea\n value={localText}\n onChange={(e) => setLocalText(e.target.value)}\n onBlur={handleBlur}\n placeholder={placeholder}\n rows={4}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text resize-y\"\n />\n {description && (\n <p className=\"text-xs text-dc-text-muted\">{description}</p>\n )}\n </div>\n )\n}\n\nexport default function AnalysisDisplayConfigPanel({\n chartType,\n displayConfig,\n colorPalette,\n onDisplayConfigChange\n}: AnalysisDisplayConfigPanelProps) {\n // Get configuration for current chart type\n const chartTypeConfig = useMemo(\n () => getChartConfig(chartType, chartConfigRegistry),\n [chartType]\n )\n\n // Check if we have any display options to show\n const hasDisplayOptions =\n (chartTypeConfig.displayOptions && chartTypeConfig.displayOptions.length > 0) ||\n (chartTypeConfig.displayOptionsConfig && chartTypeConfig.displayOptionsConfig.length > 0)\n\n if (!hasDisplayOptions) {\n return (\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n <p>No display options available for this chart type.</p>\n </div>\n )\n }\n\n return (\n <div className=\"space-y-6\">\n <div>\n <SectionHeading className=\"mb-2\">Display Options</SectionHeading>\n <div className=\"space-y-2\">\n {/* Backward compatibility: Simple boolean display options */}\n {chartTypeConfig.displayOptions?.includes('showLegend') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showLegend ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showLegend: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Legend</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('showGrid') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showGrid ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showGrid: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Grid</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('showTooltip') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showTooltip ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showTooltip: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Tooltip</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('stacked') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.stacked ?? false}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n stacked: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Stacked</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('hideHeader') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.hideHeader ?? false}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n hideHeader: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Hide Header</span>\n </label>\n )}\n\n {/* New structured display options */}\n {chartTypeConfig.displayOptionsConfig?.map((option) => (\n <div key={option.key} className={`space-y-1 ${option.type === 'axisFormat' ? 'mt-6 pt-2' : ''}`}>\n {option.type === 'boolean' && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={\n (displayConfig[option.key as keyof ChartDisplayConfig] as boolean) ??\n option.defaultValue ??\n false\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">{option.label}</span>\n </label>\n )}\n\n {option.type === 'string' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">\n {option.label}\n {option.key === 'content' && (\n <span className=\"text-xs text-dc-text-muted ml-1\">\n (only headers, lists and links)\n </span>\n )}\n </label>\n {option.key === 'content' ? (\n <textarea\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder}\n rows={8}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent font-mono resize-y bg-dc-surface text-dc-text\"\n />\n ) : (\n <input\n type=\"text\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n )}\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'paletteColor' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex flex-wrap gap-2\">\n {colorPalette?.colors.map((color, index) => {\n const isSelected =\n ((displayConfig[option.key as keyof ChartDisplayConfig] as number) ??\n option.defaultValue ??\n 0) === index\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: index\n })\n }\n className={`w-8 h-8 rounded border-2 transition-all duration-200 hover:scale-110 focus:outline-hidden focus:ring-2 focus:ring-dc-accent focus:ring-offset-1 ${\n isSelected\n ? 'ring-2 ring-offset-1 scale-110'\n : 'hover:border-dc-text-muted'\n }`}\n style={{\n backgroundColor: color,\n borderColor: isSelected ? 'var(--dc-primary)' : 'var(--dc-border)'\n }}\n title={`Color ${index + 1}: ${color}`}\n />\n )\n }) || [\n // Fallback if no palette available\n <button\n key={0}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: 0\n })\n }\n className=\"w-8 h-8 rounded-sm border-2 ring-2 ring-offset-1\"\n style={{\n backgroundColor: '#8884d8',\n borderColor: 'var(--dc-primary)',\n boxShadow: '0 0 0 2px var(--dc-primary)'\n }}\n title=\"Default Color\"\n />\n ]}\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'number' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <input\n type=\"number\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as number) ??\n option.defaultValue ??\n 0\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value === '' ? undefined : Number(e.target.value)\n })\n }\n placeholder={option.placeholder}\n min={option.min}\n max={option.max}\n step={option.step}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'select' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <select\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n >\n {option.options?.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'color' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"color\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n '#8884d8'\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n className=\"w-12 h-8 border border-dc-border rounded-sm cursor-pointer\"\n />\n <input\n type=\"text\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n '#8884d8'\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder || '#8884d8'}\n className=\"flex-1 px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'axisFormat' && (\n <AxisFormatControls\n axisLabel={option.label}\n value={(displayConfig[option.key as keyof ChartDisplayConfig] as AxisFormatConfig) || {}}\n onChange={(config) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: Object.keys(config).length > 0 ? config : undefined\n })\n }\n />\n )}\n\n {option.type === 'stringArray' && (\n <StringArrayInput\n label={option.label}\n value={(displayConfig[option.key as keyof ChartDisplayConfig] as string[]) ?? []}\n onChange={(arrayValue) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: arrayValue.length > 0 ? arrayValue : undefined\n })\n }\n placeholder={option.placeholder}\n description={option.description}\n />\n )}\n\n {option.type === 'buttonGroup' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex border border-dc-border rounded-sm overflow-hidden\">\n {option.options?.map((opt) => {\n const isSelected = (displayConfig[option.key as keyof ChartDisplayConfig] ?? option.defaultValue) === opt.value\n return (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: opt.value\n })\n }\n className={`flex-1 px-3 py-1.5 text-sm font-medium transition-colors ${\n isSelected\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n {opt.label}\n </button>\n )\n })}\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n}\n","/**\n * Funnel Validation Utilities\n *\n * Provides validation for funnel configurations including:\n * - Binding key validation\n * - Step query validation\n * - Cross-cube compatibility checks\n */\n\nimport type { CubeQuery, CubeMeta } from '../types'\nimport type {\n FunnelBindingKey,\n FunnelConfig,\n FunnelStep,\n FunnelValidationError,\n FunnelValidationResult,\n} from '../types/funnel'\nimport { getCubeNameFromQuery } from './funnelExecution'\n\n/**\n * Validate that a binding key dimension exists in the given cubes\n */\nexport function validateBindingKeyExists(\n bindingKey: FunnelBindingKey,\n meta: CubeMeta | null\n): FunnelValidationError[] {\n const errors: FunnelValidationError[] = []\n\n if (!meta?.cubes) {\n return errors // Can't validate without metadata\n }\n\n if (typeof bindingKey.dimension === 'string') {\n // Simple dimension - check it exists\n const [cubeName, dimName] = bindingKey.dimension.split('.')\n const cube = meta.cubes.find((c) => c.name === cubeName)\n\n if (!cube) {\n errors.push({\n type: 'binding_key',\n message: `Cube \"${cubeName}\" not found for binding key`,\n })\n } else {\n const dim = cube.dimensions?.find((d) => d.name === bindingKey.dimension)\n if (!dim) {\n errors.push({\n type: 'binding_key',\n message: `Dimension \"${dimName}\" not found in cube \"${cubeName}\"`,\n })\n }\n }\n } else {\n // Cross-cube mappings - validate each\n for (const mapping of bindingKey.dimension) {\n const cube = meta.cubes.find((c) => c.name === mapping.cube)\n\n if (!cube) {\n errors.push({\n type: 'cross_cube',\n message: `Cube \"${mapping.cube}\" not found for binding key mapping`,\n })\n } else {\n const dim = cube.dimensions?.find((d) => d.name === mapping.dimension)\n if (!dim) {\n errors.push({\n type: 'cross_cube',\n message: `Dimension \"${mapping.dimension}\" not found in cube \"${mapping.cube}\"`,\n })\n }\n }\n }\n }\n\n return errors\n}\n\n/**\n * Validate that each step has a valid query\n */\nexport function validateStepQueries(\n steps: FunnelStep[]\n): FunnelValidationError[] {\n const errors: FunnelValidationError[] = []\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]\n const query = step.query\n\n // Check that query has at least one field\n const hasFields =\n (query.measures && query.measures.length > 0) ||\n (query.dimensions && query.dimensions.length > 0) ||\n (query.timeDimensions && query.timeDimensions.length > 0)\n\n if (!hasFields) {\n errors.push({\n type: 'step_query',\n message: `Step ${i + 1} \"${step.name}\" has no measures, dimensions, or time dimensions`,\n stepIndex: i,\n })\n }\n }\n\n return errors\n}\n\n/**\n * Check if binding key can be resolved for a given query\n */\nexport function canResolveBindingKey(\n bindingKey: FunnelBindingKey,\n query: CubeQuery\n): boolean {\n if (typeof bindingKey.dimension === 'string') {\n // Simple case - binding key applies universally\n return true\n }\n\n // Cross-cube case - check if query's cube has a mapping\n const cubeName = getCubeNameFromQuery(query)\n if (!cubeName) return false\n\n return bindingKey.dimension.some((m) => m.cube === cubeName)\n}\n\n/**\n * Validate binding key for all funnel steps\n */\nexport function validateBindingKeyForSteps(\n bindingKey: FunnelBindingKey,\n steps: FunnelStep[]\n): FunnelValidationError[] {\n const errors: FunnelValidationError[] = []\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]\n if (!canResolveBindingKey(bindingKey, step.query)) {\n const cubeName = getCubeNameFromQuery(step.query) || 'unknown'\n errors.push({\n type: 'cross_cube',\n message: `Step ${i + 1} uses cube \"${cubeName}\" but no binding key mapping exists for it`,\n stepIndex: i,\n })\n }\n }\n\n return errors\n}\n\n/**\n * Validate time window format (ISO 8601 duration)\n */\nexport function validateTimeWindow(\n duration: string | undefined\n): FunnelValidationError | null {\n if (!duration) return null\n\n // Basic ISO 8601 duration validation\n // Formats: P1D, P7D, PT1H, PT30M, P1DT12H, etc.\n const durationRegex = /^P(?:\\d+Y)?(?:\\d+M)?(?:\\d+W)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+S)?)?$/\n\n if (!durationRegex.test(duration)) {\n return {\n type: 'time_window',\n message: `Invalid time window format \"${duration}\". Expected ISO 8601 duration (e.g., P7D, PT1H)`,\n }\n }\n\n return null\n}\n\n/**\n * Validate complete funnel configuration\n */\nexport function validateFunnelConfig(\n config: FunnelConfig,\n meta: CubeMeta | null\n): FunnelValidationResult {\n const errors: FunnelValidationError[] = []\n const warnings: FunnelValidationError[] = []\n\n // Check minimum steps\n if (config.steps.length < 2) {\n errors.push({\n type: 'general',\n message: 'Funnel requires at least 2 steps',\n })\n }\n\n // Validate binding key\n if (!config.bindingKey?.dimension) {\n errors.push({\n type: 'binding_key',\n message: 'Binding key dimension is required',\n })\n } else {\n // Check binding key exists in cubes\n errors.push(...validateBindingKeyExists(config.bindingKey, meta))\n\n // Check binding key can be resolved for all steps\n errors.push(...validateBindingKeyForSteps(config.bindingKey, config.steps))\n }\n\n // Validate step queries\n errors.push(...validateStepQueries(config.steps))\n\n // Validate time windows\n for (let i = 0; i < config.steps.length; i++) {\n const step = config.steps[i]\n const timeError = validateTimeWindow(step.timeToConvert)\n if (timeError) {\n timeError.stepIndex = i\n errors.push(timeError)\n }\n }\n\n // Validate global time window\n const globalTimeError = validateTimeWindow(config.globalTimeWindow)\n if (globalTimeError) {\n errors.push(globalTimeError)\n }\n\n // Add warnings for potential issues\n if (config.steps.length > 5) {\n warnings.push({\n type: 'general',\n message: 'Funnels with more than 5 steps may have reduced performance',\n })\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n }\n}\n\n/**\n * Quick check if minimum funnel requirements are met\n */\nexport function isMinimumFunnelConfigValid(\n bindingKey: FunnelBindingKey | null,\n queryCount: number\n): { isValid: boolean; message?: string } {\n if (queryCount < 2) {\n return { isValid: false, message: 'Add at least 2 steps for funnel' }\n }\n\n if (!bindingKey?.dimension) {\n return { isValid: false, message: 'Select a binding key dimension' }\n }\n\n if (typeof bindingKey.dimension === 'string' && !bindingKey.dimension) {\n return { isValid: false, message: 'Select a binding key dimension' }\n }\n\n if (Array.isArray(bindingKey.dimension) && bindingKey.dimension.length === 0) {\n return { isValid: false, message: 'Select a binding key dimension' }\n }\n\n return { isValid: true }\n}\n\n/**\n * Get available dimensions that can serve as binding keys\n * These should be dimensions that identify entities (e.g., user IDs, order IDs)\n */\nexport function getAvailableBindingKeyDimensions(\n meta: CubeMeta | null\n): Array<{ cube: string; dimension: string; label: string }> {\n if (!meta?.cubes) return []\n\n const dimensions: Array<{ cube: string; dimension: string; label: string }> = []\n\n for (const cube of meta.cubes) {\n if (!cube.dimensions) continue\n\n for (const dim of cube.dimensions) {\n // Only include string/number dimensions (not time dimensions)\n // as potential binding keys\n if (dim.type === 'string' || dim.type === 'number') {\n dimensions.push({\n cube: cube.name,\n dimension: dim.name,\n label: dim.title || dim.shortTitle || dim.name.split('.')[1] || dim.name,\n })\n }\n }\n }\n\n return dimensions\n}\n\n/**\n * Get the display label for a binding key\n */\nexport function getBindingKeyLabel(\n bindingKey: FunnelBindingKey | null\n): string {\n if (!bindingKey?.dimension) return 'Select binding key...'\n\n if (typeof bindingKey.dimension === 'string') {\n const parts = bindingKey.dimension.split('.')\n return parts[1] || bindingKey.dimension\n }\n\n // Cross-cube - show first mapping\n if (bindingKey.dimension.length > 0) {\n const first = bindingKey.dimension[0]\n const parts = first.dimension.split('.')\n return `${parts[1] || first.dimension} (${bindingKey.dimension.length} cubes)`\n }\n\n return 'Select binding key...'\n}\n","/**\n * FunnelBindingKeySelector Component\n *\n * Dimension picker for selecting the binding key that links funnel steps together.\n * The binding key is typically a user ID, session ID, or order ID that exists\n * across all cubes in the funnel.\n */\n\nimport React, { memo, useMemo, useCallback, useState, useRef, useEffect } from 'react'\nimport type { CubeMeta, FunnelBindingKey } from '../../types'\nimport { getIcon } from '../../icons'\nimport { getAvailableBindingKeyDimensions, getBindingKeyLabel } from '../../utils/funnelValidation'\n\nconst ChevronDownIcon = getIcon('chevronDown')\nconst CheckIcon = getIcon('check')\nconst SearchIcon = getIcon('search')\n\nexport interface FunnelBindingKeySelectorProps {\n /** Current binding key value */\n bindingKey: FunnelBindingKey | null\n /** Callback when binding key changes */\n onChange: (bindingKey: FunnelBindingKey | null) => void\n /** Cube metadata for available dimensions */\n schema: CubeMeta | null\n /** Whether the selector is disabled */\n disabled?: boolean\n /** Optional class name */\n className?: string\n}\n\n/**\n * FunnelBindingKeySelector allows users to select a dimension that links\n * funnel steps together. It shows available dimensions from all cubes\n * and supports search filtering.\n */\nconst FunnelBindingKeySelector = memo(function FunnelBindingKeySelector({\n bindingKey,\n onChange,\n schema,\n disabled = false,\n className = '',\n}: FunnelBindingKeySelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const [searchQuery, setSearchQuery] = useState('')\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Get available dimensions\n const availableDimensions = useMemo(() => {\n return getAvailableBindingKeyDimensions(schema)\n }, [schema])\n\n // Group dimensions by cube\n const groupedDimensions = useMemo(() => {\n const groups: Record<string, typeof availableDimensions> = {}\n for (const dim of availableDimensions) {\n if (!groups[dim.cube]) {\n groups[dim.cube] = []\n }\n groups[dim.cube].push(dim)\n }\n return groups\n }, [availableDimensions])\n\n // Filter dimensions based on search\n const filteredGroups = useMemo(() => {\n if (!searchQuery.trim()) return groupedDimensions\n\n const query = searchQuery.toLowerCase()\n const filtered: Record<string, typeof availableDimensions> = {}\n\n for (const [cube, dims] of Object.entries(groupedDimensions)) {\n const matchingDims = dims.filter(\n (d) =>\n d.label.toLowerCase().includes(query) ||\n d.dimension.toLowerCase().includes(query) ||\n cube.toLowerCase().includes(query)\n )\n if (matchingDims.length > 0) {\n filtered[cube] = matchingDims\n }\n }\n\n return filtered\n }, [groupedDimensions, searchQuery])\n\n // Handle selecting a dimension\n const handleSelect = useCallback(\n (dimension: string) => {\n onChange({ dimension })\n setIsOpen(false)\n setSearchQuery('')\n },\n [onChange]\n )\n\n // Handle clearing the binding key\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n onChange(null)\n },\n [onChange]\n )\n\n // Close dropdown on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n setSearchQuery('')\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n // Focus search input when dropdown opens\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n // Check if a dimension is currently selected\n const isSelected = useCallback(\n (dimension: string) => {\n if (!bindingKey) return false\n if (typeof bindingKey.dimension === 'string') {\n return bindingKey.dimension === dimension\n }\n return bindingKey.dimension.some((m) => m.dimension === dimension)\n },\n [bindingKey]\n )\n\n const label = getBindingKeyLabel(bindingKey)\n const hasSelection = bindingKey?.dimension !== null && bindingKey?.dimension !== undefined\n\n return (\n <div className={className}>\n <div ref={dropdownRef} className=\"relative\">\n {/* Trigger Button - compact to match select dropdown */}\n <button\n type=\"button\"\n onClick={() => !disabled && setIsOpen(!isOpen)}\n disabled={disabled}\n className={`\n flex items-center justify-between w-full px-2 py-1 text-xs\n bg-dc-surface border border-dc-border rounded\n transition-colors\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-dc-primary cursor-pointer'}\n ${isOpen ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`truncate ${hasSelection ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {label}\n </span>\n <span className=\"flex items-center gap-1\">\n {hasSelection && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={handleClear}\n onKeyDown={(e) => e.key === 'Enter' && handleClear(e as unknown as React.MouseEvent)}\n className=\"p-0.5 rounded hover:bg-dc-surface-hover text-dc-text-muted hover:text-dc-text\"\n title=\"Clear binding key\"\n >\n ×\n </span>\n )}\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ${isOpen ? 'rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"absolute z-50 mt-1 right-0 w-[280px] bg-dc-surface border border-dc-border rounded-md shadow-lg\">\n {/* Search Input */}\n <div className=\"p-2 border-b border-dc-border\">\n <div className=\"relative\">\n {SearchIcon && (\n <SearchIcon className=\"absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-dc-text-muted\" />\n )}\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder=\"Search dimensions...\"\n className=\"w-full pl-8 pr-3 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text placeholder:text-dc-text-muted focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Dimension List */}\n <div className=\"max-h-64 overflow-y-auto p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"px-3 py-4 text-sm text-dc-text-muted text-center\">\n No matching dimensions found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"mb-2 last:mb-0\">\n {/* Cube Header */}\n <div className=\"px-2 py-1 text-xs font-medium text-dc-text-muted uppercase tracking-wide\">\n {cubeName}\n </div>\n {/* Dimensions */}\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n flex items-center justify-between w-full px-3 py-1.5 text-sm\n rounded transition-colors\n ${isSelected(dim.dimension)\n ? 'bg-dc-primary-bg text-dc-primary'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }\n `}\n >\n <span>{dim.label}</span>\n {isSelected(dim.dimension) && CheckIcon && (\n <CheckIcon className=\"w-4 h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"px-3 py-2 border-t border-dc-border text-xs text-dc-text-muted\">\n Select a dimension that identifies entities across funnel steps (e.g., user ID, order ID)\n </div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default FunnelBindingKeySelector\n","/**\n * AnalysisQueryPanel Component\n *\n * Right-side panel containing Query and Chart tabs with sections for\n * Metrics, Filters, and Breakdowns.\n */\n\nimport React, { useEffect, memo, useCallback, useMemo } from 'react'\nimport type { AnalysisQueryPanelProps, BreakdownItem } from './types'\nimport type { MetaField } from '../../shared/types'\nimport type { QueryMergeStrategy } from '../../types'\nimport { getIcon } from '../../icons'\nimport MetricsSection from './MetricsSection'\nimport BreakdownSection from './BreakdownSection'\nimport BreakdownItemCard from './BreakdownItemCard'\nimport AnalysisFilterSection from './AnalysisFilterSection'\nimport AnalysisChartConfigPanel from './AnalysisChartConfigPanel'\nimport AnalysisDisplayConfigPanel from './AnalysisDisplayConfigPanel'\nimport FunnelBindingKeySelector from './FunnelBindingKeySelector'\n\nconst AddIcon = getIcon('add')\nconst CloseIcon = getIcon('close')\nconst InfoIcon = getIcon('info')\nconst WarningIcon = getIcon('warning')\nconst LinkIcon = getIcon('link')\n\n/**\n * AnalysisQueryPanel displays the right-side query builder with:\n * - Query/Chart tab switcher (with multi-query support)\n * - Metrics section (measures)\n * - Filter section\n * - Breakdown section (dimensions)\n * - Chart configuration (in Chart tab)\n */\nconst AnalysisQueryPanel = memo(function AnalysisQueryPanel({\n metrics,\n breakdowns,\n filters,\n schema,\n activeTab,\n onActiveTabChange,\n onAddMetric,\n onRemoveMetric,\n onReorderMetrics,\n onAddBreakdown,\n onRemoveBreakdown,\n onBreakdownGranularityChange,\n onBreakdownComparisonToggle,\n onReorderBreakdowns,\n onFiltersChange,\n onDropFieldToFilter,\n // Sorting\n order,\n onOrderChange,\n // Chart configuration\n chartType,\n chartConfig,\n displayConfig,\n colorPalette,\n chartAvailability,\n onChartTypeChange,\n onChartConfigChange,\n onDisplayConfigChange,\n // Validation\n validationStatus: _validationStatus,\n validationError: _validationError,\n // Multi-query props\n queryCount = 1,\n activeQueryIndex = 0,\n mergeStrategy = 'concat',\n onActiveQueryChange,\n onAddQuery,\n onRemoveQuery,\n onMergeStrategyChange,\n breakdownsLocked = false,\n combinedMetrics,\n combinedBreakdowns,\n multiQueryValidation,\n // Funnel props\n funnelBindingKey,\n onFunnelBindingKeyChange,\n}: AnalysisQueryPanelProps) {\n // Mark unused props\n void _validationStatus\n void _validationError\n\n const isMultiQuery = queryCount > 1\n const isFunnelMode = mergeStrategy === 'funnel'\n\n // Helper to find field metadata for a breakdown\n const getFieldMeta = useCallback((breakdown: BreakdownItem): MetaField | null => {\n if (!schema?.cubes) return null\n const [cubeName] = breakdown.field.split('.')\n const cube = schema.cubes.find(c => c.name === cubeName)\n if (!cube) return null\n // Check dimensions first, then time dimensions (which are in dimensions array)\n return cube.dimensions?.find(d => d.name === breakdown.field) || null\n }, [schema])\n\n // Check if another breakdown already has comparison enabled\n const comparisonEnabledBreakdown = useMemo(() => {\n return breakdowns.find(b => b.isTimeDimension && b.enableComparison)\n }, [breakdowns])\n\n // Force query tab when no metrics are selected\n useEffect(() => {\n if (metrics.length === 0 && (activeTab === 'chart' || activeTab === 'display')) {\n onActiveTabChange('query')\n }\n }, [metrics.length, activeTab, onActiveTabChange])\n\n // Handle query tab click\n const handleQueryTabClick = useCallback((index: number) => {\n onActiveQueryChange?.(index)\n // Ensure we're on the query tab when switching queries\n if (activeTab !== 'query') {\n onActiveTabChange('query')\n }\n }, [onActiveQueryChange, activeTab, onActiveTabChange])\n\n // Handle remove query\n const handleRemoveQuery = useCallback((e: React.MouseEvent, index: number) => {\n e.stopPropagation()\n onRemoveQuery?.(index)\n }, [onRemoveQuery])\n\n // Get tab label for query tabs\n const getQueryTabLabel = (index: number) => {\n if (!isMultiQuery) return 'Query'\n // In funnel mode, show \"S1\", \"S2\", etc.\n if (isFunnelMode) return `S${index + 1}`\n return `Q${index + 1}`\n }\n\n return (\n <div className=\"h-full flex flex-col bg-dc-surface\">\n {/* Tab Bar */}\n <div className=\"flex border-b border-dc-border flex-shrink-0\">\n {/* Query Tabs - show Q1, Q2, etc. when multi-query, or single \"Query\" tab */}\n {isMultiQuery ? (\n <div className=\"flex min-w-0 overflow-x-auto scrollbar-thin\">\n {Array.from({ length: queryCount }).map((_, index) => {\n const isActiveQuery = index === activeQueryIndex && activeTab === 'query'\n return (\n <button\n key={`q${index}`}\n onClick={() => handleQueryTabClick(index)}\n className={`flex items-center gap-1 px-3 py-3 text-sm font-medium transition-colors flex-shrink-0 ${\n isActiveQuery\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n {getQueryTabLabel(index)}\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => handleRemoveQuery(e, index)}\n onKeyDown={(e) => e.key === 'Enter' && handleRemoveQuery(e as unknown as React.MouseEvent, index)}\n className=\"p-0.5 rounded hover:bg-dc-danger-bg hover:text-dc-error transition-colors ml-0.5\"\n title=\"Remove query\"\n aria-label={`Remove ${getQueryTabLabel(index)}`}\n >\n <CloseIcon className=\"w-3 h-3\" />\n </span>\n </button>\n )\n })}\n {/* Add Query Button */}\n <button\n onClick={onAddQuery}\n className=\"flex items-center justify-center px-2 py-3 text-dc-text-secondary hover:text-dc-text transition-colors flex-shrink-0\"\n title=\"Add query\"\n aria-label=\"Add new query\"\n >\n <AddIcon className=\"w-4 h-4\" />\n </button>\n </div>\n ) : (\n <button\n onClick={() => onActiveTabChange('query')}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'query'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n Query\n {/* Add button to convert to multi-query */}\n {onAddQuery && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation()\n onAddQuery()\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.stopPropagation()\n onAddQuery()\n }\n }}\n className=\"ml-2 p-0.5 rounded hover:bg-dc-surface-hover transition-colors inline-flex items-center\"\n title=\"Add another query\"\n aria-label=\"Add another query\"\n >\n <AddIcon className=\"w-3 h-3\" />\n </span>\n )}\n </button>\n )}\n\n <button\n onClick={() => metrics.length > 0 && onActiveTabChange('chart')}\n disabled={metrics.length === 0}\n className={`px-4 py-3 text-sm font-medium transition-colors flex-shrink-0 ${\n isMultiQuery ? '' : 'flex-1'\n } ${\n activeTab === 'chart'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={metrics.length === 0 ? 'Add metrics to configure chart' : 'Chart configuration'}\n >\n Chart\n </button>\n <button\n onClick={() => metrics.length > 0 && onActiveTabChange('display')}\n disabled={metrics.length === 0}\n className={`px-4 py-3 text-sm font-medium transition-colors flex-shrink-0 ${\n isMultiQuery ? '' : 'flex-1'\n } ${\n activeTab === 'display'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={metrics.length === 0 ? 'Add metrics to configure display' : 'Display options'}\n >\n Display\n </button>\n </div>\n\n {/* Merge Strategy Controls (only shown when multiple queries and on query tab) */}\n {isMultiQuery && activeTab === 'query' && (\n <div className=\"flex items-center gap-2 px-4 py-1.5 text-sm bg-dc-surface-secondary border-b border-dc-border\">\n {LinkIcon && <LinkIcon className=\"w-3.5 h-3.5 text-dc-text-muted flex-shrink-0\" />}\n <select\n value={mergeStrategy}\n onChange={(e) => onMergeStrategyChange?.(e.target.value as QueryMergeStrategy)}\n className=\"px-2 py-1 text-xs bg-dc-surface border border-dc-border rounded text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n >\n <option value=\"concat\">Separate series</option>\n <option value=\"merge\">Merge by dimension</option>\n <option value=\"funnel\">Funnel</option>\n </select>\n\n {/* Funnel Binding Key Selector (inline, only shown in funnel mode) */}\n {isFunnelMode && onFunnelBindingKeyChange && (\n <FunnelBindingKeySelector\n bindingKey={funnelBindingKey ?? null}\n onChange={onFunnelBindingKeyChange}\n schema={schema}\n className=\"w-[180px] flex-shrink-0\"\n />\n )}\n </div>\n )}\n\n {/* Multi-Query Validation Warnings (hidden in funnel mode - funnels can have same metrics) */}\n {multiQueryValidation && !isFunnelMode && (multiQueryValidation.warnings.length > 0 || multiQueryValidation.errors.length > 0) && activeTab === 'query' && (\n <div className=\"px-4 py-2 border-b border-dc-border bg-dc-warning-bg\">\n {multiQueryValidation.errors.map((error, i) => (\n <div key={`error-${i}`} className=\"flex items-start gap-2 text-xs text-dc-error\">\n <WarningIcon className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>{error.message}</span>\n </div>\n ))}\n {multiQueryValidation.warnings.map((warning, i) => (\n <div key={`warning-${i}`} className=\"flex items-start gap-2 text-xs text-dc-warning\">\n <WarningIcon className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>{warning.message}</span>\n </div>\n ))}\n </div>\n )}\n\n {/* Tab Content */}\n <div className=\"flex-1 overflow-auto p-4\">\n {activeTab === 'query' ? (\n <div className=\"space-y-6\">\n {/* Metrics Section */}\n <MetricsSection\n metrics={metrics}\n schema={schema}\n onAdd={onAddMetric}\n onRemove={onRemoveMetric}\n order={order}\n onOrderChange={onOrderChange}\n onReorder={onReorderMetrics}\n />\n\n {/* Breakdown Section */}\n {breakdownsLocked ? (\n <div className=\"mb-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <h4 className=\"text-sm font-medium text-dc-text\">Dimensions</h4>\n </div>\n {/* Explanation with link to switch mode */}\n <div className=\"flex items-start gap-2 px-3 py-2 mb-3 bg-dc-surface-secondary rounded border border-dc-border text-xs\">\n {InfoIcon && <InfoIcon className=\"w-4 h-4 text-dc-text-muted flex-shrink-0 mt-0.5\" />}\n <span className=\"text-dc-text-muted\">\n In merge mode, dimensions are shared from Q1.\n {onMergeStrategyChange && (\n <button\n onClick={() => onMergeStrategyChange('concat')}\n className=\"text-dc-primary hover:underline ml-1\"\n >\n Switch to separate series\n </button>\n )}\n </span>\n </div>\n {/* Show breakdown cards with granularity controls (but no remove) */}\n {breakdowns.length > 0 && (\n <div className=\"space-y-1\">\n {breakdowns.map((breakdown) => (\n <BreakdownItemCard\n key={breakdown.id}\n breakdown={breakdown}\n fieldMeta={getFieldMeta(breakdown)}\n onRemove={() => {}} // No-op - can't remove in locked mode\n onGranularityChange={breakdown.isTimeDimension ? (granularity) => onBreakdownGranularityChange(breakdown.id, granularity) : undefined}\n onComparisonToggle={breakdown.isTimeDimension && onBreakdownComparisonToggle ? () => onBreakdownComparisonToggle(breakdown.id) : undefined}\n comparisonDisabled={!!comparisonEnabledBreakdown && comparisonEnabledBreakdown.id !== breakdown.id}\n />\n ))}\n </div>\n )}\n </div>\n ) : (\n <BreakdownSection\n breakdowns={breakdowns}\n schema={schema}\n onAdd={onAddBreakdown}\n onRemove={onRemoveBreakdown}\n onGranularityChange={onBreakdownGranularityChange}\n onComparisonToggle={onBreakdownComparisonToggle}\n order={order}\n onOrderChange={onOrderChange}\n onReorder={onReorderBreakdowns}\n />\n )}\n\n {/* Filter Section */}\n <AnalysisFilterSection\n filters={filters}\n schema={schema}\n onFiltersChange={onFiltersChange}\n onFieldDropped={onDropFieldToFilter}\n />\n </div>\n ) : activeTab === 'chart' ? (\n /* Chart Tab Content - use combined metrics/breakdowns in multi-query mode */\n <AnalysisChartConfigPanel\n chartType={chartType}\n chartConfig={chartConfig}\n metrics={isMultiQuery && combinedMetrics ? combinedMetrics : metrics}\n breakdowns={isMultiQuery && combinedBreakdowns ? combinedBreakdowns : breakdowns}\n schema={schema}\n chartAvailability={chartAvailability}\n onChartTypeChange={onChartTypeChange}\n onChartConfigChange={onChartConfigChange}\n />\n ) : activeTab === 'display' ? (\n /* Display Tab Content */\n <AnalysisDisplayConfigPanel\n chartType={chartType}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onDisplayConfigChange}\n />\n ) : null}\n </div>\n </div>\n )\n})\n\nexport default AnalysisQueryPanel\n","/**\n * AnalysisAIPanel Component\n *\n * A collapsible panel for AI-powered query generation.\n * Appears above the results panel when activated.\n */\n\nimport { useCallback, KeyboardEvent } from 'react'\nimport { getIcon } from '../../icons'\n\nconst SparklesIcon = getIcon('sparkles')\nconst ErrorIcon = getIcon('error')\n\nexport interface AnalysisAIPanelProps {\n /** User's natural language prompt */\n userPrompt: string\n /** Callback when prompt changes */\n onPromptChange: (prompt: string) => void\n /** Whether a query is being generated */\n isGenerating: boolean\n /** Error message from generation */\n error: string | null\n /** Whether the AI has generated a query */\n hasGeneratedQuery: boolean\n /** Callback to generate query */\n onGenerate: () => void\n /** Callback to accept the generated query */\n onAccept: () => void\n /** Callback to cancel and restore previous state */\n onCancel: () => void\n}\n\nexport default function AnalysisAIPanel({\n userPrompt,\n onPromptChange,\n isGenerating,\n error,\n hasGeneratedQuery,\n onGenerate,\n onAccept,\n onCancel\n}: AnalysisAIPanelProps) {\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n onGenerate()\n }\n },\n [onGenerate]\n )\n\n return (\n <div\n className=\"border-b border-dc-border\"\n style={{ background: 'linear-gradient(to right, var(--dc-ai-gradient-start), var(--dc-ai-gradient-end))' }}\n >\n {/* Header */}\n <div className=\"px-4 py-2 flex items-center justify-between border-b border-dc-border bg-dc-surface-secondary\">\n <div className=\"flex items-center gap-2\">\n <SparklesIcon className=\"w-4 h-4 text-dc-accent\" />\n <span className=\"text-sm font-medium text-dc-text\">AI Query Generator</span>\n {isGenerating && (\n <span className=\"text-xs text-dc-accent animate-pulse\">\n Generating...\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {hasGeneratedQuery && (\n <button\n onClick={onAccept}\n className=\"px-3 py-1 text-xs font-medium text-white bg-dc-success hover:opacity-80 rounded transition-colors\"\n >\n Accept\n </button>\n )}\n <button\n onClick={onCancel}\n className=\"px-3 py-1 text-xs font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover border border-dc-border rounded transition-colors\"\n >\n {hasGeneratedQuery ? 'Cancel' : 'Close'}\n </button>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n <div className=\"flex gap-3\">\n {/* Prompt input */}\n <div className=\"flex-1\">\n <textarea\n value={userPrompt}\n onChange={(e) => onPromptChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Describe your query in natural language... (e.g., 'Show total sales by month for the last year')\"\n className=\"w-full px-3 py-2 text-sm border border-dc-border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-dc-accent focus:border-dc-accent resize-none bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n rows={2}\n disabled={isGenerating}\n />\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n Press Enter to generate, Shift+Enter for new line\n </div>\n </div>\n\n {/* Generate button */}\n <div className=\"flex-shrink-0\">\n <button\n onClick={onGenerate}\n disabled={isGenerating || !userPrompt.trim()}\n className={`px-4 py-2 text-sm font-medium rounded-md transition-colors flex items-center gap-2 ${\n isGenerating || !userPrompt.trim()\n ? 'bg-dc-surface-tertiary text-dc-text-disabled cursor-not-allowed'\n : 'bg-dc-accent hover:bg-dc-accent-hover text-white'\n }`}\n >\n {isGenerating ? (\n <>\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin\" />\n <span>Generating...</span>\n </>\n ) : (\n <>\n <SparklesIcon className=\"w-4 h-4\" />\n <span>Generate</span>\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"mt-3 flex items-start gap-2 p-3 bg-dc-error-bg border border-dc-error-border rounded-md\">\n <ErrorIcon className=\"w-4 h-4 text-dc-error mt-0.5 flex-shrink-0\" />\n <div className=\"text-sm text-dc-error\">{error}</div>\n </div>\n )}\n\n {/* Success message */}\n {hasGeneratedQuery && !error && (\n <div className=\"mt-3 p-3 bg-dc-success-bg border border-dc-success-border rounded-md\">\n <div className=\"text-sm text-dc-success\">\n Query generated and loaded! Check the results below, then click{' '}\n <strong>Accept</strong> to keep or <strong>Cancel</strong> to revert.\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * AnalysisBuilder Component (Refactored)\n *\n * A redesigned query builder with a modern UX:\n * - Results panel on the left (large)\n * - Query builder panel on the right\n * - Search-based field selection via modal\n * - Sections: Metrics (measures), Breakdown (dimensions), Filters\n * - Auto-execute queries on field changes\n *\n * This refactored version uses:\n * - `useAnalysisBuilder` master hook for all state and data fetching\n * - `useAnalysisShare` for share URL functionality\n * - `useAnalysisAI` for AI query generation\n * - Zustand store (via Context) for state management\n * - TanStack Query (via the master hook) for data fetching\n *\n * ARCHITECTURE: Instance-based stores\n * - Each AnalysisBuilder gets its own Zustand store instance\n * - Standalone mode: Uses localStorage persistence\n * - Modal/portlet editing: No persistence, initializes from props\n */\n\nimport { forwardRef, useImperativeHandle, useMemo } from 'react'\nimport { useCubeFeatures, useCubeMeta } from '../../providers/CubeProvider'\nimport { AnalysisBuilderStoreProvider } from '../../stores/analysisBuilderStore'\nimport { useAnalysisBuilder } from '../../hooks/useAnalysisBuilderHook'\nimport { useAnalysisBuilderStoreApi } from '../../stores/analysisBuilderStore'\nimport { useAnalysisAI } from '../../hooks/useAnalysisAI'\nimport { useAnalysisShare } from '../../hooks/useAnalysisShare'\nimport { parseShareHash } from '../../utils/shareUtils'\nimport type {\n AnalysisBuilderProps,\n AnalysisBuilderRef,\n} from './types'\nimport FieldSearchModal from './FieldSearchModal'\nimport AnalysisResultsPanel from './AnalysisResultsPanel'\nimport AnalysisQueryPanel from './AnalysisQueryPanel'\nimport AnalysisAIPanel from './AnalysisAIPanel'\nimport type { MetaResponse } from '../../shared/types'\n\n/**\n * Inner component that uses the store (must be inside provider)\n */\ninterface AnalysisBuilderInnerProps extends Omit<AnalysisBuilderProps, 'initialQuery' | 'initialChartConfig' | 'disableLocalStorage'> {\n hideShare?: boolean\n}\n\nconst AnalysisBuilderInner = forwardRef<AnalysisBuilderRef, AnalysisBuilderInnerProps>(\n (\n {\n className = '',\n maxHeight,\n initialData,\n colorPalette: externalColorPalette,\n hideSettings: _hideSettings = false,\n hideShare = false,\n onQueryChange,\n onChartConfigChange\n },\n ref\n ) => {\n // Mark unused props for future use\n void _hideSettings\n\n // Get context\n const { meta } = useCubeMeta()\n const { features } = useCubeFeatures()\n\n // ========================================================================\n // Master Hook - Provides all state, data fetching, and actions\n // ========================================================================\n const analysis = useAnalysisBuilder({\n initialData,\n externalColorPalette,\n onQueryChange,\n onChartConfigChange,\n })\n\n // ========================================================================\n // AI Hook - Provides AI query generation functionality\n // ========================================================================\n\n // Get the store API for AI integration\n const storeApi = useAnalysisBuilderStoreApi()\n\n const {\n aiState,\n handleOpenAI,\n handleCloseAI,\n handleAIPromptChange,\n handleGenerateAI,\n handleAcceptAI,\n handleCancelAI\n } = useAnalysisAI({\n state: analysis.queryState,\n setState: (updater) => {\n // AI hook needs to update metrics, breakdowns, and filters all at once\n // Use the store's updateQueryState to apply the full state update\n const state = storeApi.getState()\n state.updateQueryState(analysis.activeQueryIndex, (prev) => {\n const newState = typeof updater === 'function' ? updater(prev) : updater\n return {\n ...prev,\n metrics: newState.metrics,\n breakdowns: newState.breakdowns,\n filters: newState.filters,\n }\n })\n },\n chartType: analysis.chartType,\n setChartType: analysis.actions.setChartType,\n chartConfig: analysis.chartConfig,\n setChartConfig: analysis.actions.setChartConfig,\n displayConfig: analysis.displayConfig,\n setDisplayConfig: analysis.actions.setDisplayConfig,\n setUserManuallySelectedChart: () => {\n // The store handles this internally via setChartTypeManual\n },\n setActiveView: analysis.actions.setActiveView,\n aiEndpoint: features?.aiEndpoint\n })\n\n // ========================================================================\n // Share Hook - Provides share URL functionality\n // ========================================================================\n const {\n shareButtonState,\n handleShare\n } = useAnalysisShare({\n isValidQuery: analysis.isValidQuery,\n getQueryConfig: analysis.getQueryConfig,\n chartType: analysis.chartType,\n chartConfig: analysis.chartConfig,\n displayConfig: analysis.displayConfig,\n activeView: analysis.activeView\n })\n\n // ========================================================================\n // Derived Values\n // ========================================================================\n\n // Check if query can be cleared\n const canClear = useMemo(() => {\n return (\n analysis.queryState.metrics.length > 0 ||\n analysis.queryState.breakdowns.length > 0 ||\n analysis.queryState.filters.length > 0\n )\n }, [analysis.queryState.metrics.length, analysis.queryState.breakdowns.length, analysis.queryState.filters.length])\n\n // ========================================================================\n // Expose API via ref\n // ========================================================================\n useImperativeHandle(\n ref,\n () => ({\n getQueryConfig: analysis.getQueryConfig,\n getChartConfig: analysis.getChartConfig,\n executeQuery: () => {\n // Manual execute would refetch - for now just invalidate cache\n // This could be enhanced to trigger a refetch\n },\n clearQuery: analysis.actions.clearQuery\n }),\n [analysis.getQueryConfig, analysis.getChartConfig, analysis.actions.clearQuery]\n )\n\n // ========================================================================\n // Render\n // ========================================================================\n return (\n <div\n className={`flex flex-col lg:flex-row bg-dc-surface border-x border-b border-dc-border ${maxHeight ? 'lg:h-[var(--dc-max-h)] lg:max-h-[var(--dc-max-h)] lg:overflow-hidden' : 'lg:h-full'} ${className}`}\n style={maxHeight ? { ['--dc-max-h' as string]: maxHeight } : undefined}\n >\n {/* Top/Left Panel - Results */}\n <div className=\"h-[60vh] lg:h-auto lg:flex-1 min-w-0 border-b lg:border-b-0 lg:border-r border-dc-border overflow-auto flex flex-col\">\n {/* AI Panel - expands above results when open */}\n {aiState.isOpen && (\n <AnalysisAIPanel\n userPrompt={aiState.userPrompt}\n onPromptChange={handleAIPromptChange}\n isGenerating={aiState.isGenerating}\n error={aiState.error}\n hasGeneratedQuery={aiState.hasGeneratedQuery}\n onGenerate={handleGenerateAI}\n onAccept={handleAcceptAI}\n onCancel={handleCancelAI}\n />\n )}\n\n {/* Results Panel */}\n <div className=\"flex-1 overflow-auto\">\n <AnalysisResultsPanel\n executionStatus={analysis.executionStatus}\n executionResults={analysis.executionResults}\n executionError={analysis.error?.message || null}\n totalRowCount={null}\n resultsStale={analysis.isLoading && analysis.executionResults !== null}\n chartType={analysis.chartType}\n chartConfig={analysis.chartConfig}\n displayConfig={analysis.displayConfig}\n colorPalette={analysis.colorPalette}\n // Only show palette selector in standalone mode (not when editing portlet)\n currentPaletteName={!externalColorPalette ? analysis.localPaletteName : undefined}\n onColorPaletteChange={!externalColorPalette ? analysis.actions.setLocalPaletteName : undefined}\n allQueries={analysis.allQueries}\n funnelExecutedQueries={analysis.funnelExecutedQueries ?? undefined}\n schema={meta as MetaResponse | null}\n activeView={analysis.activeView}\n onActiveViewChange={analysis.actions.setActiveView}\n displayLimit={analysis.displayLimit}\n onDisplayLimitChange={analysis.actions.setDisplayLimit}\n hasMetrics={analysis.queryState.metrics.length > 0}\n // Debug props - per-query debug data for multi-query mode\n debugDataPerQuery={analysis.debugDataPerQuery}\n // Share props (hidden when viewing shared analysis with initialQuery)\n onShareClick={hideShare ? undefined : handleShare}\n canShare={hideShare ? false : analysis.isValidQuery}\n shareButtonState={shareButtonState}\n // Refresh props\n onRefreshClick={analysis.actions.refetch}\n canRefresh={analysis.isValidQuery}\n isRefreshing={analysis.isFetching}\n // Clear props\n onClearClick={analysis.actions.clearQuery}\n canClear={canClear}\n // AI props\n enableAI={features?.enableAI !== false}\n isAIOpen={aiState.isOpen}\n onAIToggle={aiState.isOpen ? handleCloseAI : handleOpenAI}\n // Multi-query props\n queryCount={analysis.queryStates.length}\n perQueryResults={analysis.perQueryResults ?? undefined}\n activeTableIndex={analysis.activeTableIndex}\n onActiveTableChange={analysis.actions.setActiveTableIndex}\n />\n </div>\n </div>\n\n {/* Bottom/Right Panel - Query Builder */}\n <div className=\"w-full lg:w-96 flex-shrink-0 lg:h-full overflow-auto lg:overflow-hidden\">\n <AnalysisQueryPanel\n metrics={analysis.queryState.metrics}\n breakdowns={analysis.effectiveBreakdowns}\n filters={analysis.queryState.filters}\n schema={meta as MetaResponse | null}\n activeTab={analysis.activeTab}\n onActiveTabChange={analysis.actions.setActiveTab}\n onAddMetric={analysis.actions.openMetricsModal}\n onRemoveMetric={analysis.actions.removeMetric}\n onReorderMetrics={analysis.actions.reorderMetrics}\n onAddBreakdown={analysis.actions.openBreakdownsModal}\n onRemoveBreakdown={analysis.actions.removeBreakdown}\n onBreakdownGranularityChange={analysis.actions.setBreakdownGranularity}\n onBreakdownComparisonToggle={analysis.actions.toggleBreakdownComparison}\n onReorderBreakdowns={analysis.actions.reorderBreakdowns}\n onFiltersChange={analysis.actions.setFilters}\n onDropFieldToFilter={analysis.actions.dropFieldToFilter}\n order={analysis.queryState.order}\n onOrderChange={analysis.actions.setOrder}\n chartType={analysis.chartType}\n chartConfig={analysis.chartConfig}\n displayConfig={analysis.displayConfig}\n colorPalette={analysis.colorPalette}\n chartAvailability={analysis.chartAvailability}\n onChartTypeChange={analysis.actions.setChartType}\n onChartConfigChange={analysis.actions.setChartConfig}\n onDisplayConfigChange={analysis.actions.setDisplayConfig}\n validationStatus={analysis.queryState.validationStatus}\n validationError={analysis.queryState.validationError}\n // Multi-query props\n queryCount={analysis.queryStates.length}\n activeQueryIndex={analysis.activeQueryIndex}\n mergeStrategy={analysis.mergeStrategy}\n onActiveQueryChange={analysis.actions.setActiveQueryIndex}\n onAddQuery={analysis.actions.addQuery}\n onRemoveQuery={analysis.actions.removeQuery}\n onMergeStrategyChange={analysis.actions.setMergeStrategy}\n breakdownsLocked={analysis.mergeStrategy === 'merge' && analysis.activeQueryIndex > 0}\n combinedMetrics={analysis.combinedMetrics}\n combinedBreakdowns={analysis.combinedBreakdowns}\n multiQueryValidation={analysis.multiQueryValidation}\n // Funnel props\n funnelBindingKey={analysis.funnelBindingKey}\n onFunnelBindingKeyChange={analysis.actions.setFunnelBindingKey}\n />\n </div>\n\n {/* Field Search Modal */}\n <FieldSearchModal\n isOpen={analysis.showFieldModal}\n onClose={analysis.actions.closeFieldModal}\n onSelect={analysis.actions.handleFieldSelected}\n mode={analysis.fieldModalMode}\n schema={meta as MetaResponse | null}\n selectedFields={[\n ...analysis.queryState.metrics.map((m) => m.field),\n ...analysis.effectiveBreakdowns.map((b) => b.field)\n ]}\n />\n </div>\n )\n }\n)\n\nAnalysisBuilderInner.displayName = 'AnalysisBuilderInner'\n\n/**\n * AnalysisBuilder - Main exported component\n *\n * Wraps the inner component with the store provider to ensure\n * each AnalysisBuilder instance has its own isolated state.\n */\nconst AnalysisBuilder = forwardRef<AnalysisBuilderRef, AnalysisBuilderProps>(\n (props, ref) => {\n const {\n initialQuery,\n initialChartConfig,\n disableLocalStorage = false,\n ...innerProps\n } = props\n\n const hasShareHash = Boolean(parseShareHash())\n\n // Hide share button when using initialQuery (e.g., viewing a shared analysis)\n const hideShare = !!initialQuery\n\n return (\n <AnalysisBuilderStoreProvider\n initialQuery={initialQuery}\n initialChartConfig={initialChartConfig}\n disableLocalStorage={disableLocalStorage || !!initialQuery || hasShareHash}\n >\n <AnalysisBuilderInner ref={ref} {...innerProps} hideShare={hideShare} />\n </AnalysisBuilderStoreProvider>\n )\n }\n)\n\nAnalysisBuilder.displayName = 'AnalysisBuilder'\n\nexport default AnalysisBuilder\n","import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'\nimport Modal from './Modal'\nimport AnalysisBuilder from './AnalysisBuilder'\nimport type { AnalysisBuilderRef } from './AnalysisBuilder/types'\nimport type { PortletConfig, ColorPalette, CubeQuery, MultiQueryConfig, DashboardFilter } from '../types'\nimport {\n mergeDashboardAndPortletFilters,\n applyUniversalTimeFilters\n} from '../utils/filterUtils'\n\ninterface PortletAnalysisModalProps {\n isOpen: boolean\n onClose: () => void\n onSave: (portlet: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'>) => void\n portlet?: PortletConfig | null\n /** Initial data to display (avoids re-fetching when editing) */\n initialData?: any[]\n title: string\n submitText: string\n colorPalette?: ColorPalette\n /** Dashboard filters to apply to preview (when editing portlet in dashboard context) */\n dashboardFilters?: DashboardFilter[]\n}\n\n/**\n * PortletAnalysisModal - A modal wrapper around AnalysisBuilder for portlet editing\n *\n * This replaces PortletEditModal with the modern AnalysisBuilder interface.\n * Features:\n * - Two-panel layout with results and query builder\n * - Auto-execution of queries\n * - Smart chart defaults\n * - Title input in header\n * - Initial data support (no re-fetch when editing)\n */\nexport default function PortletAnalysisModal({\n isOpen,\n onClose,\n onSave,\n portlet,\n initialData,\n title: modalTitle,\n submitText,\n colorPalette,\n dashboardFilters\n}: PortletAnalysisModalProps) {\n\n // Ref to AnalysisBuilder for getting current query and chart config\n const builderRef = useRef<AnalysisBuilderRef>(null)\n\n // Title state\n const [formTitle, setFormTitle] = useState('')\n\n // Get applicable regular dashboard filters for this portlet\n // Universal time filters are handled separately - they apply to timeDimensions, not the filters array\n const applicableFilters = useMemo(() => {\n if (!dashboardFilters || !portlet?.dashboardFilterMapping) {\n return []\n }\n const mapping = portlet.dashboardFilterMapping\n // Only include regular filters (not universal time filters which use __universal_time__ placeholder)\n return dashboardFilters\n .filter(df => !df.isUniversalTime && mapping.includes(df.id))\n .map(df => df.filter)\n }, [dashboardFilters, portlet?.dashboardFilterMapping])\n\n // Parse initial query from portlet and merge dashboard filters\n // AnalysisBuilder handles both single CubeQuery and MultiQueryConfig internally\n const initialQuery = useMemo<CubeQuery | MultiQueryConfig | undefined>(() => {\n if (!portlet?.query) return undefined\n try {\n const parsed = JSON.parse(portlet.query)\n\n // Handle MultiQueryConfig\n if (parsed && 'queries' in parsed && Array.isArray(parsed.queries)) {\n return {\n ...parsed,\n queries: parsed.queries.map((q: CubeQuery) => ({\n ...q,\n // Merge regular dashboard filters (not universal time)\n filters: mergeDashboardAndPortletFilters(applicableFilters, q.filters, 'client'),\n // Apply universal time filter dateRange to all time dimensions\n timeDimensions: applyUniversalTimeFilters(\n dashboardFilters,\n portlet.dashboardFilterMapping,\n q.timeDimensions\n )\n }))\n }\n }\n\n // Handle single CubeQuery\n return {\n ...parsed,\n // Merge regular dashboard filters (not universal time)\n filters: mergeDashboardAndPortletFilters(applicableFilters, parsed.filters, 'client'),\n // Apply universal time filter dateRange to all time dimensions\n timeDimensions: applyUniversalTimeFilters(\n dashboardFilters,\n portlet?.dashboardFilterMapping,\n parsed.timeDimensions\n )\n }\n } catch {\n return undefined\n }\n }, [portlet?.query, applicableFilters, dashboardFilters, portlet?.dashboardFilterMapping])\n\n // Initial chart config from portlet\n const initialChartConfig = React.useMemo(() => {\n if (!portlet) return undefined\n return {\n chartType: portlet.chartType,\n chartConfig: portlet.chartConfig,\n displayConfig: portlet.displayConfig\n }\n }, [portlet])\n\n // Reset form state when modal opens/closes or portlet changes\n useEffect(() => {\n if (isOpen) {\n setFormTitle(portlet?.title || '')\n }\n }, [isOpen, portlet])\n\n // Handle save\n const handleSave = useCallback(() => {\n if (!formTitle.trim()) {\n alert('Please enter a title for the portlet.')\n return\n }\n\n // Get query config and chart config from AnalysisBuilder\n // AnalysisBuilder returns either CubeQuery or MultiQueryConfig - we just stringify it\n const queryConfig = builderRef.current?.getQueryConfig()\n const chartConfig = builderRef.current?.getChartConfig()\n\n if (!queryConfig) {\n alert('Please configure a query before saving.')\n return\n }\n\n // Check if config has content - works for both single and multi-query\n // For multi-query, check the first query; for single query, check directly\n const firstQuery = 'queries' in queryConfig ? queryConfig.queries[0] : queryConfig\n const hasContent =\n (firstQuery?.measures && firstQuery.measures.length > 0) ||\n (firstQuery?.dimensions && firstQuery.dimensions.length > 0) ||\n (firstQuery?.timeDimensions && firstQuery.timeDimensions.length > 0)\n\n if (!hasContent) {\n alert('Please add at least one metric or breakdown to your query.')\n return\n }\n\n // Build portlet config - just stringify whatever AnalysisBuilder returned\n const portletData: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'> = {\n ...(portlet || {}),\n title: formTitle.trim(),\n query: JSON.stringify(queryConfig),\n chartType: chartConfig?.chartType || 'line',\n chartConfig: chartConfig?.chartConfig || {},\n displayConfig: chartConfig?.displayConfig || {},\n // Preserve existing position or use defaults for new portlets\n w: portlet?.w || 5,\n h: portlet?.h || 4\n } as PortletConfig\n\n onSave(portletData)\n onClose()\n }, [formTitle, portlet, onSave, onClose])\n\n // Handle cancel\n const handleCancel = useCallback(() => {\n onClose()\n }, [onClose])\n\n // Footer with save/cancel buttons\n const footer = (\n <>\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"px-4 py-2 text-sm font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface border border-dc-border rounded-md hover:bg-dc-surface-hover transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n className=\"px-4 py-2 text-sm font-medium text-white bg-dc-accent hover:bg-dc-accent-hover rounded-md transition-colors\"\n >\n {submitText}\n </button>\n </>\n )\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n title={modalTitle}\n size=\"fullscreen-mobile\"\n showCloseButton={true}\n closeOnBackdropClick={false}\n closeOnEscape={true}\n noPadding={true}\n footer={footer}\n >\n {/* Custom content with title input */}\n <div className=\"flex flex-col h-full\">\n {/* Title input section */}\n <div className=\"shrink-0 px-4 py-3 border-b border-dc-border bg-dc-surface-secondary\">\n <div className=\"flex items-center gap-3\">\n <label htmlFor=\"portlet-title\" className=\"text-sm font-medium text-dc-text-secondary shrink-0\">\n Title\n </label>\n <input\n id=\"portlet-title\"\n type=\"text\"\n value={formTitle}\n onChange={(e) => setFormTitle(e.target.value)}\n placeholder=\"Enter portlet title...\"\n autoComplete=\"off\"\n className=\"flex-1 px-3 py-1.5 text-sm bg-dc-surface border border-dc-border rounded-md text-dc-text placeholder-dc-text-muted focus:outline-none focus:ring-2 focus:ring-dc-accent focus:border-transparent\"\n autoFocus\n />\n </div>\n </div>\n\n {/* AnalysisBuilder content */}\n <div className=\"flex-1 min-h-0\">\n <AnalysisBuilder\n ref={builderRef}\n maxHeight=\"100%\"\n initialQuery={initialQuery}\n initialChartConfig={initialChartConfig}\n initialData={initialData}\n colorPalette={colorPalette}\n disableLocalStorage={true}\n className=\"h-full\"\n />\n </div>\n </div>\n </Modal>\n )\n}\n","/**\n * Portlet Filter Configuration Modal\n * Allows users to configure which dashboard filters apply to a specific portlet\n */\n\nimport { useState, useEffect } from 'react'\nimport type { DashboardFilter } from '../types'\n\ninterface PortletFilterConfigModalProps {\n isOpen: boolean\n onClose: () => void\n dashboardFilters: DashboardFilter[]\n currentMapping: string[]\n onSave: (mapping: string[]) => void\n portletTitle: string\n}\n\nexport default function PortletFilterConfigModal({\n isOpen,\n onClose,\n dashboardFilters = [],\n currentMapping = [],\n onSave,\n portletTitle\n}: PortletFilterConfigModalProps) {\n const [selectedFilters, setSelectedFilters] = useState<string[]>(currentMapping)\n\n // Update local state when props change\n useEffect(() => {\n setSelectedFilters(currentMapping)\n }, [currentMapping, isOpen])\n\n const handleToggleFilter = (filterId: string) => {\n setSelectedFilters(prev => {\n if (prev.includes(filterId)) {\n return prev.filter(id => id !== filterId)\n } else {\n return [...prev, filterId]\n }\n })\n }\n\n const handleSave = () => {\n onSave(selectedFilters)\n onClose()\n }\n\n const handleCancel = () => {\n setSelectedFilters(currentMapping) // Reset to original\n onClose()\n }\n\n // Format filter preview text\n const formatFilterPreview = (filter: DashboardFilter): string => {\n if (!filter.filter) return ''\n\n // Handle simple filters\n if ('member' in filter.filter && filter.filter.member) {\n const values = filter.filter.values || []\n const valuesText = values.length > 0 ? values.join(', ') : 'no value'\n return `${filter.filter.member} ${filter.filter.operator} ${valuesText}`\n }\n\n // Handle group filters (AND/OR)\n if ('type' in filter.filter && filter.filter.type) {\n const filterCount = filter.filter.filters?.length || 0\n return `${filter.filter.type.toUpperCase()} group with ${filterCount} filter${filterCount !== 1 ? 's' : ''}`\n }\n\n return 'Complex filter'\n }\n\n if (!isOpen) return null\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50\" onClick={handleCancel}>\n <div\n className=\"bg-dc-surface border border-dc-border rounded-lg max-w-2xl w-full mx-4 max-h-[80vh] flex flex-col\"\n style={{ boxShadow: 'var(--dc-shadow-lg)' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"px-6 py-4 border-b border-dc-border bg-dc-surface-secondary rounded-t-lg\">\n <h2 className=\"text-lg font-semibold text-dc-text\">Configure Dashboard Filters</h2>\n <p className=\"text-sm text-dc-text-secondary mt-1\">\n Choose which dashboard filters apply to \"{portletTitle}\"\n </p>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto px-6 py-4\">\n {dashboardFilters.length === 0 ? (\n <div className=\"text-center py-8 text-dc-text-muted\">\n <svg\n className=\"mx-auto h-12 w-12 mb-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\"\n />\n </svg>\n <p className=\"text-sm font-medium\">No dashboard filters available</p>\n <p className=\"text-xs mt-1\">Add filters at the dashboard level first</p>\n </div>\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between mb-4 pb-2 border-b border-dc-border\">\n <span className=\"text-sm font-medium text-dc-text\">Available Filters</span>\n <span className=\"text-xs text-dc-text-secondary\">\n {selectedFilters.length} of {dashboardFilters.length} selected\n </span>\n </div>\n\n {dashboardFilters.map(filter => {\n const isSelected = selectedFilters.includes(filter.id)\n\n return (\n <label\n key={filter.id}\n className={`flex items-start p-3 rounded-md border cursor-pointer transition-colors ${\n isSelected\n ? 'border-dc-primary bg-dc-surface-secondary'\n : 'border-dc-border hover:bg-dc-surface-hover'\n }`}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={() => handleToggleFilter(filter.id)}\n className=\"mt-0.5 mr-3 h-4 w-4 rounded border-dc-border focus:ring-2 focus:ring-dc-primary\"\n style={{\n accentColor: 'var(--dc-primary)'\n }}\n />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm text-dc-text truncate\">\n {filter.label}\n </span>\n {isSelected && (\n <span\n className=\"px-2 py-0.5 text-xs rounded-full\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n Applied\n </span>\n )}\n </div>\n <div className=\"mt-1 text-xs text-dc-text-secondary break-words\">\n {formatFilterPreview(filter)}\n </div>\n </div>\n </label>\n )\n })}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"px-6 py-4 border-t border-dc-border bg-dc-surface-secondary rounded-b-lg flex justify-end gap-3\">\n <button\n onClick={handleCancel}\n className=\"px-4 py-2 text-sm font-medium rounded-md border border-dc-border bg-dc-surface hover:bg-dc-surface-hover transition-colors text-dc-text\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n className=\"px-4 py-2 text-sm font-medium rounded-md text-white transition-colors\"\n style={{\n backgroundColor: 'var(--dc-primary)'\n }}\n >\n Apply Filters\n </button>\n </div>\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport Modal from './Modal'\n\nexport interface ConfirmModalProps {\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void | Promise<void>\n title?: string\n message: React.ReactNode\n confirmText?: string\n cancelText?: string\n confirmVariant?: 'danger' | 'primary' | 'warning'\n isLoading?: boolean\n}\n\n/**\n * A reusable confirmation modal component.\n *\n * Usage:\n * ```tsx\n * <ConfirmModal\n * isOpen={showConfirm}\n * onClose={() => setShowConfirm(false)}\n * onConfirm={handleDelete}\n * title=\"Delete Portlet\"\n * message=\"Are you sure you want to delete this portlet? This action cannot be undone.\"\n * confirmText=\"Delete\"\n * confirmVariant=\"danger\"\n * />\n * ```\n */\nconst ConfirmModal: React.FC<ConfirmModalProps> = ({\n isOpen,\n onClose,\n onConfirm,\n title = 'Confirm',\n message,\n confirmText = 'Confirm',\n cancelText = 'Cancel',\n confirmVariant = 'primary',\n isLoading = false,\n}) => {\n const handleConfirm = async () => {\n await onConfirm()\n onClose()\n }\n\n const getConfirmButtonClasses = () => {\n const baseClasses = 'px-4 py-2 text-sm font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed'\n\n switch (confirmVariant) {\n case 'danger':\n return `${baseClasses} bg-dc-danger text-white hover:bg-dc-danger/90 focus:ring-dc-danger`\n case 'warning':\n return `${baseClasses} bg-dc-warning text-white hover:bg-dc-warning/90 focus:ring-dc-warning`\n case 'primary':\n default:\n return `${baseClasses} bg-dc-primary text-white hover:bg-dc-primary/90 focus:ring-dc-primary`\n }\n }\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n title={title}\n size=\"sm\"\n closeOnBackdropClick={!isLoading}\n closeOnEscape={!isLoading}\n footer={\n <>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isLoading}\n className=\"px-4 py-2 text-sm font-medium text-dc-text-secondary bg-dc-surface border border-dc-border rounded-md hover:bg-dc-surface-hover transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-dc-primary disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {cancelText}\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={isLoading}\n className={getConfirmButtonClasses()}\n >\n {isLoading ? (\n <span className=\"flex items-center gap-2\">\n <svg className=\"animate-spin h-4 w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n Processing...\n </span>\n ) : (\n confirmText\n )}\n </button>\n </>\n }\n >\n <div className=\"text-dc-text-secondary\">\n {message}\n </div>\n </Modal>\n )\n}\n\nexport default ConfirmModal\n","/**\n * DashboardFilterConfigModal Component\n *\n * Modal for editing dashboard filter configuration including:\n * - Filter label\n * - Field selection (via FieldSearchModal)\n * - Operator selection\n * - Value input (adapts to field/operator type)\n * - Date range selection for time dimensions\n *\n * Based on FilterConfigModal but adapted for DashboardFilter with:\n * - Label editing\n * - Clickable field section to change field\n * - \"Dashboard fields only\" toggle\n * - Delete action\n */\n\nimport { useState, useRef, useEffect, useCallback, ChangeEvent } from 'react'\nimport { getIcon } from '../../icons'\nimport type { DashboardFilter, SimpleFilter, FilterOperator } from '../../types'\nimport type { MetaResponse, DateRangeType, MetaField } from '../../shared/types'\nimport type { FieldType } from '../AnalysisBuilder/types'\nimport { FILTER_OPERATORS, DATE_RANGE_OPTIONS } from '../../shared/types'\nimport {\n getAvailableOperators,\n convertDateRangeTypeToValue,\n requiresNumberInput\n} from '../../shared/utils'\nimport { findFieldInSchema, getFieldTitle } from '../AnalysisBuilder/utils'\nimport { useFilterValues } from '../../hooks/useFilterValues'\nimport { useDebounce } from '../../hooks/useDebounce'\nimport FieldSearchModal from '../AnalysisBuilder/FieldSearchModal'\n\nconst CloseIcon = getIcon('close')\nconst ChevronDownIcon = getIcon('chevronDown')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\nconst EditIcon = getIcon('edit')\nconst EyeIcon = getIcon('eye')\nconst EyeOffIcon = getIcon('eyeOff')\n\ninterface DashboardFilterConfigModalProps {\n /** The dashboard filter being edited */\n filter: DashboardFilter\n /** Full schema (unfiltered) */\n fullSchema: MetaResponse | null\n /** Filtered schema (dashboard fields only) */\n filteredSchema: MetaResponse | null\n /** Whether the modal is open */\n isOpen: boolean\n /** Callback when user saves changes */\n onSave: (filter: DashboardFilter) => void\n /** Callback when user deletes the filter */\n onDelete: () => void\n /** Callback when user closes/cancels */\n onClose: () => void\n}\n\nexport default function DashboardFilterConfigModal({\n filter: initialFilter,\n fullSchema,\n filteredSchema,\n isOpen,\n onSave,\n onDelete,\n onClose\n}: DashboardFilterConfigModalProps) {\n // Local state for editing\n const [localLabel, setLocalLabel] = useState(initialFilter.label)\n const [localFilter, setLocalFilter] = useState<SimpleFilter>(initialFilter.filter as SimpleFilter)\n const [showAllFields, setShowAllFields] = useState(false)\n const [showFieldSearch, setShowFieldSearch] = useState(false)\n\n // Dropdown state\n const [isOperatorDropdownOpen, setIsOperatorDropdownOpen] = useState(false)\n const [isValueDropdownOpen, setIsValueDropdownOpen] = useState(false)\n const [isDateRangeDropdownOpen, setIsDateRangeDropdownOpen] = useState(false)\n\n // Date range state\n const [rangeType, setRangeType] = useState<DateRangeType>('this_month')\n const [numberValue, setNumberValue] = useState(1)\n const [searchText, setSearchText] = useState('')\n\n const containerRef = useRef<HTMLDivElement>(null)\n\n // Schema to use based on toggle\n const activeSchema = showAllFields ? fullSchema : filteredSchema\n\n // Sync state when filter changes or modal opens\n useEffect(() => {\n if (isOpen) {\n setLocalLabel(initialFilter.label)\n setLocalFilter(initialFilter.filter as SimpleFilter)\n }\n }, [initialFilter, isOpen])\n\n // Debounce search text for API calls\n const debouncedSearchText = useDebounce(searchText, 300)\n\n // Get field info\n const fieldInfo = findFieldInSchema(localFilter.member, activeSchema)\n const fieldType = fieldInfo?.field.type || 'string'\n const isTimeField = fieldType === 'time'\n const isMeasureField = fieldInfo?.fieldType === 'measure'\n const isDimensionField = fieldInfo?.fieldType === 'dimension'\n\n // Get display title for field\n const fieldTitle = getFieldTitle(localFilter.member, activeSchema)\n\n // Get operator metadata\n const operatorMeta = FILTER_OPERATORS[localFilter.operator as FilterOperator]\n\n // Get available operators for this field type\n const availableOperators = getAvailableOperators(fieldType)\n\n // Should show date range selector\n const shouldShowDateRange = isTimeField && localFilter.operator === 'inDateRange'\n\n // Should use combo box for value selection\n const shouldShowComboBox = (() => {\n const comboOperators = ['equals', 'notEquals', 'in', 'notIn']\n return comboOperators.includes(localFilter.operator) && isDimensionField && !isTimeField\n })()\n\n // Fetch distinct values for combo box\n const {\n values: distinctValues,\n loading: valuesLoading,\n error: valuesError,\n searchValues\n } = useFilterValues(localFilter.member, shouldShowComboBox)\n\n // Close dropdowns when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n }\n }\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [])\n\n // Load values when dropdown opens\n useEffect(() => {\n if (isValueDropdownOpen && shouldShowComboBox && searchValues) {\n searchValues('', true)\n }\n }, [isValueDropdownOpen, shouldShowComboBox, searchValues])\n\n // Search when debounced text changes\n useEffect(() => {\n if (isValueDropdownOpen && shouldShowComboBox && searchValues && debouncedSearchText !== undefined) {\n searchValues(debouncedSearchText)\n }\n }, [debouncedSearchText, isValueDropdownOpen, shouldShowComboBox, searchValues])\n\n // Sync rangeType state with filter.dateRange\n useEffect(() => {\n if (!shouldShowDateRange || !localFilter.dateRange) return\n\n if (Array.isArray(localFilter.dateRange)) {\n setRangeType('custom')\n } else {\n const flexMatch = localFilter.dateRange.match(/^last (\\d+) (days|weeks|months|quarters|years)$/)\n const singularMatch = !flexMatch && localFilter.dateRange.match(/^last (day|week|month|quarter|year)$/)\n\n if (flexMatch) {\n const [, num, unit] = flexMatch\n setRangeType(`last_n_${unit}` as DateRangeType)\n setNumberValue(parseInt(num) || 1)\n } else if (singularMatch) {\n const [, unit] = singularMatch\n const pluralUnit = unit === 'day' ? 'days' :\n unit === 'week' ? 'weeks' :\n unit === 'month' ? 'months' :\n unit === 'quarter' ? 'quarters' : 'years'\n setRangeType(`last_n_${pluralUnit}` as DateRangeType)\n setNumberValue(1)\n } else {\n let found = false\n for (const option of DATE_RANGE_OPTIONS) {\n if (option.value !== 'custom' && !requiresNumberInput(option.value)) {\n if (convertDateRangeTypeToValue(option.value) === localFilter.dateRange) {\n setRangeType(option.value)\n found = true\n break\n }\n }\n }\n if (!found) setRangeType('custom')\n }\n }\n }, [localFilter.dateRange, shouldShowDateRange])\n\n // Handle field selection from FieldSearchModal\n const handleFieldSelected = useCallback((field: MetaField, _fieldType: FieldType) => {\n // Reset operator and values when changing field\n const newFieldType = field.type\n const newOperators = getAvailableOperators(newFieldType)\n const defaultOperator = newOperators[0]?.operator || 'equals'\n\n setLocalFilter({\n member: field.name,\n operator: defaultOperator as FilterOperator,\n values: []\n })\n setShowFieldSearch(false)\n }, [])\n\n // Handle operator change\n const handleOperatorChange = useCallback((operator: FilterOperator) => {\n setLocalFilter({\n member: localFilter.member,\n operator,\n values: []\n })\n setIsOperatorDropdownOpen(false)\n }, [localFilter.member])\n\n // Handle value selection from combo box\n const handleValueSelect = useCallback((value: unknown) => {\n const values = localFilter.values || []\n if (operatorMeta?.supportsMultipleValues) {\n if (!values.includes(value)) {\n setLocalFilter({ ...localFilter, values: [...values, value] })\n }\n } else {\n setLocalFilter({ ...localFilter, values: [value] })\n setIsValueDropdownOpen(false)\n }\n setSearchText('')\n }, [localFilter, operatorMeta?.supportsMultipleValues])\n\n // Handle value removal\n const handleValueRemove = useCallback((valueToRemove: unknown) => {\n const values = (localFilter.values || []).filter((v: unknown) => v !== valueToRemove)\n setLocalFilter({ ...localFilter, values })\n }, [localFilter])\n\n // Handle direct text/number input\n const handleDirectInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n if (operatorMeta?.valueType === 'number') {\n const numValue = parseFloat(value)\n if (!isNaN(numValue)) {\n setLocalFilter({ ...localFilter, values: [numValue] })\n } else if (value === '' || value === '-') {\n setLocalFilter({ ...localFilter, values: [] })\n }\n } else {\n setLocalFilter({ ...localFilter, values: value ? [value] : [] })\n }\n }, [localFilter, operatorMeta?.valueType])\n\n // Handle between range inputs\n const handleBetweenStartInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = localFilter.values?.length >= 2 ? localFilter.values : ['', '']\n const newValues = [!isNaN(value) ? value : '', currentValues[1]].filter(v => v !== '')\n setLocalFilter({ ...localFilter, values: newValues })\n }, [localFilter])\n\n const handleBetweenEndInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = localFilter.values?.length >= 2 ? localFilter.values : ['', '']\n const newValues = [currentValues[0], !isNaN(value) ? value : ''].filter(v => v !== '')\n setLocalFilter({ ...localFilter, values: newValues })\n }, [localFilter])\n\n // Handle date input\n const handleDateInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setLocalFilter({ ...localFilter, values: value ? [value] : [] })\n }, [localFilter])\n\n // Handle date range type change\n const handleRangeTypeChange = useCallback((newRangeType: DateRangeType) => {\n setRangeType(newRangeType)\n setIsDateRangeDropdownOpen(false)\n\n let dateRange: string | string[]\n if (newRangeType === 'custom') {\n const today = new Date().toISOString().split('T')[0]\n dateRange = [today, today]\n } else if (requiresNumberInput(newRangeType)) {\n dateRange = convertDateRangeTypeToValue(newRangeType, numberValue)\n } else {\n dateRange = convertDateRangeTypeToValue(newRangeType)\n }\n\n setLocalFilter({ ...localFilter, dateRange } as SimpleFilter)\n }, [localFilter, numberValue])\n\n // Handle number value change for \"last N days/weeks/etc\"\n const handleNumberValueChange = useCallback((value: number) => {\n setNumberValue(value)\n if (requiresNumberInput(rangeType)) {\n const dateRange = convertDateRangeTypeToValue(rangeType, value)\n setLocalFilter({ ...localFilter, dateRange } as SimpleFilter)\n }\n }, [localFilter, rangeType])\n\n // Handle custom date range inputs\n const handleCustomStartDate = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const start = e.target.value\n const currentRange = Array.isArray(localFilter.dateRange) ? localFilter.dateRange : [localFilter.dateRange || '', '']\n const end = currentRange[1] || start\n setLocalFilter({ ...localFilter, dateRange: [start, end] } as SimpleFilter)\n }, [localFilter])\n\n const handleCustomEndDate = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const end = e.target.value\n const currentRange = Array.isArray(localFilter.dateRange) ? localFilter.dateRange : ['', localFilter.dateRange || '']\n const start = currentRange[0] || end\n setLocalFilter({ ...localFilter, dateRange: [start, end] } as SimpleFilter)\n }, [localFilter])\n\n // Handle save\n const handleSave = useCallback(() => {\n if (!localLabel.trim()) {\n alert('Filter label is required')\n return\n }\n\n // Don't require field selection for universal time filters\n if (!initialFilter.isUniversalTime && !localFilter.member) {\n alert('Please select a field for the filter')\n return\n }\n\n const updatedFilter: DashboardFilter = {\n id: initialFilter.id,\n label: localLabel,\n filter: localFilter,\n ...(initialFilter.isUniversalTime && { isUniversalTime: true })\n }\n\n onSave(updatedFilter)\n }, [initialFilter.id, initialFilter.isUniversalTime, localLabel, localFilter, onSave])\n\n // Get current operator label\n const operatorLabel = availableOperators.find(op => op.operator === localFilter.operator)?.label || localFilter.operator\n\n // Get current date range label\n const dateRangeLabel = DATE_RANGE_OPTIONS.find(opt => opt.value === rangeType)?.label || 'Select range'\n\n // Get icon for field type\n const FieldIcon = isTimeField ? TimeDimensionIcon : isMeasureField ? MeasureIcon : DimensionIcon\n const iconBgClass = isTimeField ? 'bg-dc-time-dimension' : isMeasureField ? 'bg-dc-measure' : 'bg-dc-dimension'\n const iconTextClass = isTimeField ? 'text-dc-time-dimension-text' : isMeasureField ? 'text-dc-measure-text' : 'text-dc-dimension-text'\n\n if (!isOpen) return null\n\n // Render value input based on operator type\n const renderValueInput = () => {\n // No value required for set/notSet\n if (!operatorMeta?.requiresValues) {\n return (\n <div className=\"text-sm text-dc-text-muted italic py-2\">\n No value required\n </div>\n )\n }\n\n // Date range selector for inDateRange on time fields\n if (shouldShowDateRange) {\n return (\n <div className=\"space-y-2\">\n {/* Range type dropdown */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(!isDateRangeDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{dateRangeLabel}</span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isDateRangeDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isDateRangeDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-y-auto\">\n {DATE_RANGE_OPTIONS.map((option) => (\n <button\n key={option.value}\n onClick={() => handleRangeTypeChange(option.value)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n option.value === rangeType ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {option.label}\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Number input for \"last N\" ranges */}\n {requiresNumberInput(rangeType) && (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min=\"1\"\n max=\"1000\"\n value={numberValue}\n onChange={(e) => handleNumberValueChange(Math.max(1, parseInt(e.target.value) || 1))}\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text w-20\"\n />\n <span className=\"text-sm text-dc-text-muted\">\n {rangeType.replace('last_n_', '')}\n </span>\n </div>\n )}\n\n {/* Custom date inputs */}\n {rangeType === 'custom' && (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"date\"\n value={Array.isArray(localFilter.dateRange) ? localFilter.dateRange[0] : ''}\n onChange={handleCustomStartDate}\n className=\"flex-1 text-sm border border-dc-border rounded px-2 py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"date\"\n value={Array.isArray(localFilter.dateRange) ? localFilter.dateRange[1] : ''}\n onChange={handleCustomEndDate}\n className=\"flex-1 text-sm border border-dc-border rounded px-2 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n )}\n </div>\n )\n }\n\n // Between/notBetween range inputs\n if (localFilter.operator === 'between' || localFilter.operator === 'notBetween') {\n return (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n value={localFilter.values?.[0] ?? ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"number\"\n value={localFilter.values?.[1] ?? ''}\n onChange={handleBetweenEndInput}\n placeholder=\"Max\"\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n )\n }\n\n // Date picker for date operators\n if (operatorMeta?.valueType === 'date') {\n return (\n <input\n type=\"date\"\n value={localFilter.values?.[0] || ''}\n onChange={handleDateInput}\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Number input\n if (operatorMeta?.valueType === 'number') {\n return (\n <input\n type=\"number\"\n value={localFilter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter number\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Combo box for equals/notEquals/in/notIn on dimensions\n if (shouldShowComboBox) {\n return (\n <div className=\"space-y-2\">\n {/* Selected values as tags */}\n {localFilter.values && localFilter.values.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {localFilter.values.map((value: unknown, index: number) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 bg-dc-primary/10 text-dc-primary text-sm px-2 py-1 rounded\"\n >\n <span className=\"max-w-[150px] truncate\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"hover:text-dc-danger\"\n >\n <CloseIcon className=\"w-3.5 h-3.5\" />\n </button>\n </span>\n ))}\n </div>\n )}\n\n {/* Dropdown trigger */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsValueDropdownOpen(!isValueDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"text-dc-text-muted truncate\">\n {valuesLoading ? 'Loading...' : 'Select value...'}\n </span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isValueDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isValueDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-56 overflow-hidden\">\n {/* Search input */}\n <div className=\"p-2 border-b border-dc-border\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search...\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div className=\"max-h-40 overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"px-3 py-2 text-sm text-dc-text-muted\">Loading...</div>\n ) : valuesError ? (\n <div className=\"px-3 py-2 text-sm text-dc-error\">Error: {valuesError}</div>\n ) : distinctValues.length === 0 ? (\n <div className=\"px-3 py-2 text-sm text-dc-text-muted\">No values found</div>\n ) : (\n distinctValues.map((value, index) => {\n const isSelected = localFilter.values?.includes(value)\n return (\n <button\n key={`${value}-${index}`}\n onClick={() => handleValueSelect(value)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n isSelected ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {String(value)}\n {isSelected && <span className=\"float-right\">✓</span>}\n </button>\n )\n })\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n }\n\n // Default: text input\n return (\n <input\n type=\"text\"\n value={localFilter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter value...\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n />\n )\n }\n\n return (\n <>\n {/* Modal overlay */}\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center p-4\"\n style={{ backgroundColor: 'var(--dc-overlay)' }}\n onClick={onClose}\n >\n <div\n ref={containerRef}\n className=\"bg-dc-surface rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-auto\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-4 border-b border-dc-border\">\n <h2 className=\"text-lg font-semibold text-dc-text\">Edit Filter</h2>\n <button\n onClick={onClose}\n className=\"p-1 text-dc-text-muted hover:text-dc-text transition-colors\"\n >\n <CloseIcon className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"p-4 space-y-4\">\n {/* Filter Label */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Filter Label\n </label>\n <input\n type=\"text\"\n value={localLabel}\n onChange={(e) => setLocalLabel(e.target.value)}\n placeholder=\"Enter filter label\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n\n {/* Info box for universal time filters */}\n {initialFilter.isUniversalTime && (\n <div className=\"p-3 rounded-md bg-dc-info-bg border border-dc-info-border\">\n <div className=\"text-sm font-medium text-dc-info mb-1\">\n Universal Time Filter\n </div>\n <div className=\"text-xs text-dc-text-secondary\">\n This filter applies to all time dimensions in mapped portlets.\n Users can select the date range when viewing the dashboard.\n </div>\n </div>\n )}\n\n {/* Field selection (not for universal time filters) */}\n {!initialFilter.isUniversalTime && (\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"block text-sm font-medium text-dc-text-secondary\">\n Field\n </label>\n <button\n onClick={() => setShowAllFields(!showAllFields)}\n className=\"flex items-center gap-1 text-xs px-2 py-1 rounded hover:bg-dc-surface-hover text-dc-text-muted\"\n title={showAllFields ? 'Show dashboard fields only' : 'Show all fields'}\n >\n {showAllFields ? (\n <>\n <EyeOffIcon className=\"w-3.5 h-3.5\" />\n <span>Dashboard</span>\n </>\n ) : (\n <>\n <EyeIcon className=\"w-3.5 h-3.5\" />\n <span>All</span>\n </>\n )}\n </button>\n </div>\n <button\n onClick={() => setShowFieldSearch(true)}\n className=\"w-full flex items-center gap-2 p-3 bg-dc-surface-secondary rounded hover:bg-dc-surface-tertiary transition-colors\"\n >\n {localFilter.member ? (\n <>\n <span className={`w-6 h-6 flex items-center justify-center rounded ${iconBgClass} ${iconTextClass}`}>\n {FieldIcon && <FieldIcon className=\"w-4 h-4\" />}\n </span>\n <span className=\"flex-1 text-sm font-medium text-dc-text text-left\">{fieldTitle}</span>\n </>\n ) : (\n <>\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-surface-tertiary text-dc-text-muted\">\n <DimensionIcon className=\"w-4 h-4\" />\n </span>\n <span className=\"flex-1 text-sm text-dc-text-muted text-left\">Click to select a field</span>\n </>\n )}\n <EditIcon className=\"w-4 h-4 text-dc-text-muted\" />\n </button>\n </div>\n )}\n\n {/* Operator selector (only if field is selected) */}\n {(localFilter.member || initialFilter.isUniversalTime) && !initialFilter.isUniversalTime && (\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Operator\n </label>\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsOperatorDropdownOpen(!isOperatorDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{operatorLabel}</span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isOperatorDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isOperatorDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-y-auto\">\n {availableOperators.map((op) => (\n <button\n key={op.operator}\n onClick={() => handleOperatorChange(op.operator as FilterOperator)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n op.operator === localFilter.operator ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {op.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Value input (only if field is selected, not for universal time filters) */}\n {localFilter.member && !initialFilter.isUniversalTime && (\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Default Value\n </label>\n {renderValueInput()}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-between p-4 border-t border-dc-border\">\n <button\n onClick={onDelete}\n className=\"px-4 py-2 text-sm font-medium text-dc-danger hover:bg-dc-danger-bg rounded transition-colors\"\n >\n Delete Filter\n </button>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={onClose}\n className=\"px-4 py-2 text-sm font-medium text-dc-text-secondary hover:text-dc-text transition-colors\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n className=\"px-4 py-2 text-sm font-medium text-dc-primary-content bg-dc-primary hover:bg-dc-primary-hover rounded transition-colors\"\n >\n Done\n </button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Field Search Modal */}\n {showFieldSearch && (\n <FieldSearchModal\n isOpen={showFieldSearch}\n onClose={() => setShowFieldSearch(false)}\n onSelect={handleFieldSelected}\n mode=\"filter\"\n schema={activeSchema}\n selectedFields={localFilter.member ? [localFilter.member] : []}\n />\n )}\n </>\n )\n}\n","/**\n * FilterEditModal Component\n *\n * Modal for editing dashboard filter details including label, field, operator, and values.\n * Now delegates to DashboardFilterConfigModal for the modern search-based UX.\n *\n * Pattern: Self-contained modal with local state (matches PortletEditModal pattern)\n * - All editing state is local to the modal\n * - Changes only propagate on \"Done\" button click via onSave callback\n * - Cancel/close resets local state without saving\n */\n\nimport React, { useMemo, useCallback } from 'react'\nimport { extractDashboardFields } from '../../utils/filterUtils'\nimport DashboardFilterConfigModal from './DashboardFilterConfigModal'\nimport type { DashboardFilter, CubeMeta, DashboardConfig } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\n\ninterface FilterEditModalProps {\n filter: DashboardFilter\n schema: CubeMeta | null\n dashboardConfig: DashboardConfig\n isOpen: boolean\n onSave: (filter: DashboardFilter) => void | Promise<void>\n onClose: () => void\n onDelete: () => void\n convertToMetaResponse: (cubeMeta: CubeMeta | null) => MetaResponse | null\n}\n\nconst FilterEditModal: React.FC<FilterEditModalProps> = ({\n filter,\n schema,\n dashboardConfig,\n isOpen,\n onSave,\n onClose,\n onDelete,\n convertToMetaResponse\n}) => {\n // Convert full schema to MetaResponse format\n const fullSchema = useMemo(() => {\n return convertToMetaResponse(schema)\n }, [schema, convertToMetaResponse])\n\n // Extract fields used in dashboard\n const dashboardFields = useMemo(() => {\n return extractDashboardFields(dashboardConfig)\n }, [dashboardConfig])\n\n // Create filtered schema showing only dashboard fields\n const filteredSchema = useMemo<MetaResponse | null>(() => {\n if (!schema) return null\n\n const filteredCubes = schema.cubes\n .map(cube => {\n const cubeName = cube.name\n\n const filteredMeasures = cube.measures.filter(measure => {\n const fullName = measure.name.includes('.')\n ? measure.name\n : `${cubeName}.${measure.name}`\n return dashboardFields.measures.has(fullName)\n })\n\n const filteredDimensions = cube.dimensions.filter(dimension => {\n const fullName = dimension.name.includes('.')\n ? dimension.name\n : `${cubeName}.${dimension.name}`\n return dashboardFields.dimensions.has(fullName) ||\n dashboardFields.timeDimensions.has(fullName)\n })\n\n if (filteredMeasures.length > 0 || filteredDimensions.length > 0) {\n return {\n ...cube,\n measures: filteredMeasures,\n dimensions: filteredDimensions\n }\n }\n\n return null\n })\n .filter((cube): cube is NonNullable<typeof cube> => cube !== null)\n\n const filteredCubeMeta: CubeMeta = {\n ...schema,\n cubes: filteredCubes\n }\n\n return convertToMetaResponse(filteredCubeMeta)\n }, [schema, dashboardFields, convertToMetaResponse])\n\n // Handle save with async support\n const handleSave = useCallback(async (updatedFilter: DashboardFilter) => {\n try {\n await onSave(updatedFilter)\n onClose()\n } catch (error) {\n console.error('Failed to save filter:', error)\n alert('Failed to save filter. Please try again.')\n }\n }, [onSave, onClose])\n\n if (!isOpen) return null\n\n return (\n <DashboardFilterConfigModal\n filter={filter}\n fullSchema={fullSchema}\n filteredSchema={filteredSchema}\n isOpen={isOpen}\n onSave={handleSave}\n onDelete={onDelete}\n onClose={onClose}\n />\n )\n}\n\nexport default FilterEditModal\n","/**\n * EditModeFilterList Component\n *\n * Displays filters in edit mode with chips showing filter labels and edit/delete actions\n */\n\nimport React from 'react'\nimport { getIcon } from '../../icons'\nimport type { DashboardFilter } from '../../types'\n\nconst FilterIcon = getIcon('filter')\nconst AddIcon = getIcon('add')\nconst CloseIcon = getIcon('close')\nconst EditIcon = getIcon('edit')\nconst ChevronDownIcon = getIcon('chevronDown')\nconst ClockIcon = getIcon('timeDimension')\n\ninterface EditModeFilterListProps {\n dashboardFilters: DashboardFilter[]\n onAddFilter: () => void\n onAddTimeFilter: () => void\n onEditFilter: (filterId: string) => void\n onRemoveFilter: (filterId: string) => void\n selectedFilterId?: string | null\n onFilterSelect?: (filterId: string) => void\n}\n\nconst EditModeFilterList: React.FC<EditModeFilterListProps> = ({\n dashboardFilters,\n onAddFilter,\n onAddTimeFilter,\n onEditFilter,\n onRemoveFilter,\n selectedFilterId,\n onFilterSelect\n}) => {\n const [isCollapsed, setIsCollapsed] = React.useState(false)\n\n // Render compact filter chip - just label + edit + delete\n const renderFilterChip = (dashboardFilter: DashboardFilter) => {\n const { id, label, isUniversalTime } = dashboardFilter\n const isSelected = selectedFilterId === id\n\n // Use calendar icon for universal time filters, funnel for regular filters\n const IconComponent = isUniversalTime ? ClockIcon : FilterIcon\n\n return (\n <div\n key={id}\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md border text-xs transition-all ${\n 'cursor-pointer hover:shadow-md'\n }`}\n style={{\n backgroundColor: isSelected ? 'var(--dc-primary)' : 'var(--dc-surface)',\n borderColor: isSelected ? 'var(--dc-primary)' : 'var(--dc-border)',\n borderWidth: isSelected ? '2px' : '1px',\n color: isSelected ? 'white' : 'var(--dc-text)',\n boxShadow: isSelected ? '0 0 0 3px rgba(var(--dc-primary-rgb), 0.1)' : 'none'\n }}\n onClick={() => {\n if (onFilterSelect) {\n onFilterSelect(id)\n }\n }}\n >\n <IconComponent\n className=\"w-3.5 h-3.5 shrink-0\"\n style={{ color: isSelected ? 'white' : 'var(--dc-primary)' }}\n />\n <span className=\"font-medium truncate\">{label}</span>\n\n {!isSelected && (\n <div className=\"flex items-center gap-0.5 ml-1\" onClick={(e) => e.stopPropagation()}>\n <button\n onClick={() => onEditFilter(id)}\n className=\"p-0.5 hover:bg-dc-hover rounded transition-colors\"\n title=\"Edit filter\"\n >\n <EditIcon className=\"w-3 h-3\" />\n </button>\n <button\n onClick={() => onRemoveFilter(id)}\n className=\"p-0.5 hover:bg-dc-danger-bg hover:text-dc-danger rounded transition-colors\"\n title=\"Remove filter\"\n >\n <CloseIcon className=\"w-3 h-3\" />\n </button>\n </div>\n )}\n </div>\n )\n }\n\n return (\n <>\n {/* Mobile: Header + collapsible content */}\n <div className=\"md:hidden\">\n {/* Header - clickable to toggle */}\n <div\n className=\"px-4 py-2 flex items-center justify-between cursor-pointer\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n >\n <div className=\"flex items-center gap-2\">\n <FilterIcon className=\"w-4 h-4 shrink-0\" style={{ color: 'var(--dc-primary)' }} />\n <h3 className=\"text-sm font-semibold\" style={{ color: 'var(--dc-text)' }}>\n Filters\n </h3>\n {dashboardFilters.length > 0 && (\n <span\n className=\"px-1.5 py-0.5 rounded-full text-xs font-medium\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n {dashboardFilters.length}\n </span>\n )}\n <ChevronDownIcon\n className={`w-4 h-4 transition-transform ${isCollapsed ? '' : 'rotate-180'}`}\n style={{ color: 'var(--dc-text-secondary)' }}\n />\n </div>\n\n <div className=\"flex items-center gap-1\">\n {/* Only show Date Range button if no universal time filter exists */}\n {!dashboardFilters.some(f => f.isUniversalTime) && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onAddTimeFilter()\n }}\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium transition-colors hover:opacity-80\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n color: 'var(--dc-primary)',\n border: '1px solid var(--dc-border)'\n }}\n title=\"Add date range filter (applies to all time dimensions)\"\n >\n <AddIcon className=\"w-3.5 h-3.5\" />\n <ClockIcon className=\"w-3.5 h-3.5\" />\n </button>\n )}\n <button\n onClick={(e) => {\n e.stopPropagation()\n onAddFilter()\n }}\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium transition-colors hover:opacity-80\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n <AddIcon className=\"w-3.5 h-3.5\" />\n </button>\n </div>\n </div>\n\n {/* Mobile Filter Chips - Collapsible */}\n {dashboardFilters.length > 0 && !isCollapsed && (\n <div className=\"px-4 pb-2 flex flex-col gap-2\">\n {dashboardFilters.map(renderFilterChip)}\n </div>\n )}\n\n {/* Mobile Empty State */}\n {dashboardFilters.length === 0 && !isCollapsed && (\n <div className=\"px-4 pb-2\">\n <div\n className=\"text-xs p-2 rounded-md text-center\"\n style={{\n backgroundColor: 'var(--dc-surface-secondary)',\n color: 'var(--dc-text-secondary)'\n }}\n >\n No filters configured. Click \"Add\" to create one.\n </div>\n </div>\n )}\n </div>\n\n {/* Desktop: Single row layout */}\n <div className=\"hidden md:flex md:items-center md:gap-3 px-4 py-2\">\n {/* Header Section */}\n <div className=\"flex items-center gap-2 shrink-0\">\n <FilterIcon className=\"w-4 h-4 shrink-0\" style={{ color: 'var(--dc-primary)' }} />\n <h3 className=\"text-sm font-semibold whitespace-nowrap\" style={{ color: 'var(--dc-text)' }}>\n Filters\n </h3>\n {dashboardFilters.length > 0 && (\n <span\n className=\"px-1.5 py-0.5 rounded-full text-xs font-medium\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n {dashboardFilters.length}\n </span>\n )}\n </div>\n\n {/* Filter Chips Section - grows to fill space */}\n {dashboardFilters.length > 0 ? (\n <div className=\"flex flex-wrap gap-2 flex-1 min-w-0\">\n {dashboardFilters.map(renderFilterChip)}\n </div>\n ) : (\n <div className=\"flex-1 min-w-0\">\n <div\n className=\"text-xs px-3 py-1 rounded-md inline-block\"\n style={{\n backgroundColor: 'var(--dc-surface-secondary)',\n color: 'var(--dc-text-secondary)'\n }}\n >\n No filters configured. Click \"Add\" to create one.\n </div>\n </div>\n )}\n\n {/* Add Button Section */}\n <div className=\"flex items-center gap-1 shrink-0\">\n {/* Only show Date Range button if no universal time filter exists */}\n {!dashboardFilters.some(f => f.isUniversalTime) && (\n <button\n onClick={onAddTimeFilter}\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium transition-colors hover:opacity-80\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n color: 'var(--dc-primary)',\n border: '1px solid var(--dc-border)'\n }}\n title=\"Add date range filter (applies to all time dimensions)\"\n >\n <AddIcon className=\"w-3.5 h-3.5\" />\n <span>Date Range</span>\n </button>\n )}\n <button\n onClick={onAddFilter}\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium transition-colors hover:opacity-80\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n <AddIcon className=\"w-3.5 h-3.5\" />\n <span>Filter</span>\n </button>\n </div>\n </div>\n </>\n )\n}\n\nexport default EditModeFilterList\n","/**\n * Utility functions for QueryBuilder components\n *\n * Common filter/query utilities are imported from the shared module\n * to avoid duplication. Only component-specific utilities are defined here.\n */\n\nimport type { CubeQuery, Filter, SimpleFilter } from '../../types'\nimport type { MetaField, MetaResponse } from '../QueryBuilder/types'\nimport { FILTER_OPERATORS } from '../QueryBuilder/types'\n\n// ============================================================================\n// Re-export common utilities from shared module (canonical source)\n// ============================================================================\nexport {\n // Filter type guards\n isSimpleFilter,\n isGroupFilter,\n isAndFilter,\n isOrFilter,\n // Filter manipulation\n flattenFilters,\n countFilters,\n createSimpleFilter,\n createAndFilter,\n createOrFilter,\n cleanupFilters,\n // Filter transformation\n transformFiltersForServer,\n transformFiltersFromServer,\n // Query utilities\n hasQueryContent,\n cleanQuery,\n cleanQueryForServer,\n transformQueryForUI,\n // Schema utilities\n getCubeNameFromField,\n getFieldType,\n getFieldTitle,\n getAvailableOperators,\n getAllFilterableFields,\n // Date utilities\n convertDateRangeTypeToValue,\n requiresNumberInput,\n formatDateForCube,\n} from '../../shared/utils'\n\n// Import for internal use\nimport {\n isSimpleFilter,\n isGroupFilter,\n getCubeNameFromField,\n getAllFilterableFields,\n getFieldType,\n} from '../../shared/utils'\n\n// ============================================================================\n// Component-specific utilities (unique to this module)\n// ============================================================================\n\n/**\n * Check if a field is selected in the current query\n */\nexport function isFieldSelected(\n fieldName: string,\n fieldType: 'measures' | 'dimensions' | 'timeDimensions',\n query: CubeQuery\n): boolean {\n switch (fieldType) {\n case 'measures':\n return query.measures?.includes(fieldName) || false\n case 'dimensions':\n return query.dimensions?.includes(fieldName) || false\n case 'timeDimensions':\n return query.timeDimensions?.some(td => td.dimension === fieldName) || false\n default:\n return false\n }\n}\n\n/**\n * Get all time dimension fields from schema\n */\nexport function getTimeDimensionFields(schema: MetaResponse): MetaField[] {\n const timeDimensions: MetaField[] = []\n\n schema.cubes.forEach(cube => {\n cube.dimensions.forEach(dimension => {\n if (dimension.type === 'time') {\n timeDimensions.push(dimension)\n }\n })\n })\n\n return timeDimensions\n}\n\n/**\n * Get all non-time dimension fields from schema\n */\nexport function getRegularDimensionFields(schema: MetaResponse): MetaField[] {\n const dimensions: MetaField[] = []\n\n schema.cubes.forEach(cube => {\n cube.dimensions.forEach(dimension => {\n if (dimension.type !== 'time') {\n dimensions.push(dimension)\n }\n })\n })\n\n return dimensions\n}\n\n/**\n * Get all measure fields from schema\n */\nexport function getMeasureFields(schema: MetaResponse): MetaField[] {\n const measures: MetaField[] = []\n\n schema.cubes.forEach(cube => {\n cube.measures.forEach(measure => {\n measures.push(measure)\n })\n })\n\n return measures\n}\n\n/**\n * Get count of selected fields across all types\n */\nexport function getSelectedFieldsCount(query: CubeQuery): number {\n let count = 0\n if (query.measures) count += query.measures.length\n if (query.dimensions) count += query.dimensions.length\n if (query.timeDimensions) count += query.timeDimensions.length\n return count\n}\n\n/**\n * Group fields by cube name\n */\nexport function groupFieldsByCube(fields: MetaField[]): Record<string, MetaField[]> {\n return fields.reduce((groups, field) => {\n const cubeName = getCubeNameFromField(field.name)\n if (!groups[cubeName]) {\n groups[cubeName] = []\n }\n groups[cubeName].push(field)\n return groups\n }, {} as Record<string, MetaField[]>)\n}\n\n/**\n * Create an empty query object\n */\nexport function createEmptyQuery(): CubeQuery {\n return {}\n}\n\n/**\n * Get all filterable fields from schema (measures, dimensions, and time dimensions)\n * Returns ALL fields if no query provided, or only query fields if query provided\n */\nexport function getFilterableFields(schema: MetaResponse, query?: CubeQuery): MetaField[] {\n const allFields: MetaField[] = []\n\n schema.cubes.forEach(cube => {\n allFields.push(...cube.measures)\n allFields.push(...cube.dimensions)\n })\n\n // If no query provided, return all fields\n if (!query) {\n return allFields.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n // Get currently selected fields from the query\n const selectedFields = new Set<string>()\n\n // Add measures\n if (query.measures) {\n query.measures.forEach(measure => selectedFields.add(measure))\n }\n\n // Add dimensions\n if (query.dimensions) {\n query.dimensions.forEach(dimension => selectedFields.add(dimension))\n }\n\n // Add time dimensions\n if (query.timeDimensions) {\n query.timeDimensions.forEach(td => selectedFields.add(td.dimension))\n }\n\n // Filter to only include selected fields\n const filterableFields = allFields.filter(field => selectedFields.has(field.name))\n\n return filterableFields.sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/**\n * Get organized filter field options with query fields prioritized at top\n */\nexport function getOrganizedFilterFields(schema: MetaResponse, query?: CubeQuery): {\n queryFields: MetaField[]\n allFields: MetaField[]\n} {\n const allFields = getAllFilterableFields(schema)\n\n if (!query) {\n return {\n queryFields: [],\n allFields\n }\n }\n\n // Get currently selected fields from the query\n const selectedFields = new Set<string>()\n\n // Add measures\n if (query.measures) {\n query.measures.forEach(measure => selectedFields.add(measure))\n }\n\n // Add dimensions\n if (query.dimensions) {\n query.dimensions.forEach(dimension => selectedFields.add(dimension))\n }\n\n // Add time dimensions\n if (query.timeDimensions) {\n query.timeDimensions.forEach(td => selectedFields.add(td.dimension))\n }\n\n // Split fields into query fields and other fields\n const queryFields = allFields.filter(field => selectedFields.has(field.name))\n\n return {\n queryFields,\n allFields\n }\n}\n\n/**\n * Validate a filter\n */\nexport function validateFilter(filter: SimpleFilter, schema: MetaResponse): {\n isValid: boolean\n errors: string[]\n} {\n const errors: string[] = []\n\n // Check if field exists\n const fields = getFilterableFields(schema)\n const fieldExists = fields.some(f => f.name === filter.member)\n\n if (!fieldExists) {\n errors.push(`Field \"${filter.member}\" does not exist`)\n }\n\n // Check if operator is valid for field type\n if (fieldExists) {\n const fieldType = getFieldType(filter.member, schema)\n const operatorMeta = FILTER_OPERATORS[filter.operator]\n\n if (!operatorMeta) {\n errors.push(`Invalid operator \"${filter.operator}\"`)\n } else if (!operatorMeta.fieldTypes.includes(fieldType)) {\n errors.push(`Operator \"${filter.operator}\" is not valid for field type \"${fieldType}\"`)\n } else {\n // Check values\n if (operatorMeta.requiresValues && (!filter.values || filter.values.length === 0)) {\n errors.push(`Operator \"${filter.operator}\" requires values`)\n }\n\n if (!operatorMeta.supportsMultipleValues && filter.values && filter.values.length > 1) {\n errors.push(`Operator \"${filter.operator}\" does not support multiple values`)\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors\n }\n}\n\n/**\n * Clean up filters by removing any that reference fields not in the current query (legacy)\n * Only used for backward compatibility - filters on non-query fields are now supported\n */\nexport function cleanupFiltersLegacy(filters: Filter[], query: CubeQuery): Filter[] {\n if (!filters || filters.length === 0) {\n return []\n }\n\n // Get currently selected fields from the query\n const selectedFields = new Set<string>()\n\n // Add measures\n if (query.measures) {\n query.measures.forEach(measure => selectedFields.add(measure))\n }\n\n // Add dimensions\n if (query.dimensions) {\n query.dimensions.forEach(dimension => selectedFields.add(dimension))\n }\n\n // Add time dimensions\n if (query.timeDimensions) {\n query.timeDimensions.forEach(td => selectedFields.add(td.dimension))\n }\n\n // Recursively clean filters\n const cleanFilter = (filter: Filter): Filter | null => {\n if (isSimpleFilter(filter)) {\n // Remove filter if its field is not selected\n return selectedFields.has(filter.member) ? filter : null\n } else if (isGroupFilter(filter)) {\n // Clean group recursively\n const cleanedFilters = filter.filters.map(cleanFilter).filter(f => f !== null) as Filter[]\n return cleanedFilters.length > 0 ? { type: filter.type, filters: cleanedFilters } : null\n }\n return null\n }\n\n // Clean all filters and remove nulls\n const cleanedFilters = filters.map(cleanFilter).filter(f => f !== null) as Filter[]\n\n return cleanedFilters\n}\n\n/**\n * Get the time dimensions that have date ranges applied\n */\nexport function getTimeDimensionsWithDateRanges(query: CubeQuery): Record<string, string | string[]> {\n const dateRanges: Record<string, string | string[]> = {}\n\n if (query.timeDimensions) {\n query.timeDimensions.forEach(td => {\n if (td.dateRange) {\n dateRanges[td.dimension] = td.dateRange\n }\n })\n }\n\n return dateRanges\n}\n\n/**\n * Check if a query has any time dimensions\n */\nexport function hasTimeDimensions(query: CubeQuery): boolean {\n return Boolean(query.timeDimensions && query.timeDimensions.length > 0)\n}\n\n// ============================================================================\n// Sorting utility functions\n// ============================================================================\n\n/**\n * Clean up order object by removing fields that are no longer in the query\n */\nexport function cleanupOrder(order: Record<string, 'asc' | 'desc'> | undefined, query: CubeQuery): Record<string, 'asc' | 'desc'> | undefined {\n if (!order) return undefined\n\n const allFields = [\n ...(query.measures || []),\n ...(query.dimensions || []),\n ...(query.timeDimensions || []).map(td => td.dimension)\n ]\n\n const cleanedOrder: Record<string, 'asc' | 'desc'> = {}\n for (const [field, direction] of Object.entries(order)) {\n if (allFields.includes(field)) {\n cleanedOrder[field] = direction\n }\n }\n\n return Object.keys(cleanedOrder).length > 0 ? cleanedOrder : undefined\n}\n\n/**\n * Get sort direction for a field from the order object\n */\nexport function getSortDirection(fieldName: string, order: Record<string, 'asc' | 'desc'> | undefined): 'asc' | 'desc' | null {\n return order?.[fieldName] || null\n}\n\n/**\n * Get tooltip text for sort button based on current direction\n */\nexport function getSortTooltip(direction: 'asc' | 'desc' | null): string {\n switch (direction) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n}\n\n/**\n * Get next sort direction in the cycle: null -> asc -> desc -> null\n */\nexport function getNextSortDirection(current: 'asc' | 'desc' | null): 'asc' | 'desc' | null {\n switch (current) {\n case null:\n return 'asc'\n case 'asc':\n return 'desc'\n case 'desc':\n return null\n default:\n return 'asc'\n }\n}\n\n// ============================================================================\n// Compact filter bar date utilities\n// ============================================================================\n\n/**\n * Date preset configuration for compact filter bar\n */\nexport interface DatePreset {\n id: string\n label: string\n value: string\n}\n\nexport const DATE_PRESETS: DatePreset[] = [\n { id: 'today', label: 'Today', value: 'today' },\n { id: 'yesterday', label: 'Yesterday', value: 'yesterday' },\n { id: '7d', label: '7D', value: 'last 7 days' },\n { id: '30d', label: '30D', value: 'last 30 days' },\n { id: '3m', label: '3M', value: 'last 3 months' },\n { id: '6m', label: '6M', value: 'last 6 months' },\n { id: '12m', label: '12M', value: 'last 12 months' }\n]\n\nexport const XTD_OPTIONS: DatePreset[] = [\n { id: 'wtd', label: 'Week to Date', value: 'this week' },\n { id: 'mtd', label: 'Month to Date', value: 'this month' },\n { id: 'qtd', label: 'Quarter to Date', value: 'this quarter' },\n { id: 'ytd', label: 'Year to Date', value: 'this year' }\n]\n\n/**\n * Calculate actual date range from a preset string\n * Returns start and end dates for display purposes\n */\nexport function calculateDateRange(preset: string): { start: Date, end: Date } | null {\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n\n const endOfToday = new Date(today)\n endOfToday.setHours(23, 59, 59, 999)\n\n switch (preset.toLowerCase()) {\n case 'today': {\n return { start: today, end: endOfToday }\n }\n case 'yesterday': {\n const yesterday = new Date(today)\n yesterday.setDate(yesterday.getDate() - 1)\n const endOfYesterday = new Date(yesterday)\n endOfYesterday.setHours(23, 59, 59, 999)\n return { start: yesterday, end: endOfYesterday }\n }\n case 'this week': {\n const startOfWeek = new Date(today)\n const dayOfWeek = startOfWeek.getDay()\n const diff = dayOfWeek === 0 ? 6 : dayOfWeek - 1 // Monday as first day\n startOfWeek.setDate(startOfWeek.getDate() - diff)\n return { start: startOfWeek, end: endOfToday }\n }\n case 'this month': {\n const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1)\n return { start: startOfMonth, end: endOfToday }\n }\n case 'this quarter': {\n const quarter = Math.floor(today.getMonth() / 3)\n const startOfQuarter = new Date(today.getFullYear(), quarter * 3, 1)\n return { start: startOfQuarter, end: endOfToday }\n }\n case 'this year': {\n const startOfYear = new Date(today.getFullYear(), 0, 1)\n return { start: startOfYear, end: endOfToday }\n }\n default: {\n // Handle \"last N units\" patterns\n const lastNMatch = preset.match(/^last\\s+(\\d+)\\s+(day|days|week|weeks|month|months|quarter|quarters|year|years)$/i)\n if (lastNMatch) {\n const num = parseInt(lastNMatch[1], 10)\n const unit = lastNMatch[2].toLowerCase()\n const startDate = new Date(today)\n\n if (unit === 'day' || unit === 'days') {\n startDate.setDate(startDate.getDate() - num + 1)\n } else if (unit === 'week' || unit === 'weeks') {\n startDate.setDate(startDate.getDate() - (num * 7) + 1)\n } else if (unit === 'month' || unit === 'months') {\n startDate.setMonth(startDate.getMonth() - num)\n startDate.setDate(startDate.getDate() + 1)\n } else if (unit === 'quarter' || unit === 'quarters') {\n startDate.setMonth(startDate.getMonth() - (num * 3))\n startDate.setDate(startDate.getDate() + 1)\n } else if (unit === 'year' || unit === 'years') {\n startDate.setFullYear(startDate.getFullYear() - num)\n startDate.setDate(startDate.getDate() + 1)\n }\n\n return { start: startDate, end: endOfToday }\n }\n\n // Handle \"last week\", \"last month\", etc. (without number)\n const lastUnitMatch = preset.match(/^last\\s+(week|month|quarter|year)$/i)\n if (lastUnitMatch) {\n const unit = lastUnitMatch[1].toLowerCase()\n\n if (unit === 'week') {\n const endOfLastWeek = new Date(today)\n const dayOfWeek = endOfLastWeek.getDay()\n const diff = dayOfWeek === 0 ? 6 : dayOfWeek - 1\n endOfLastWeek.setDate(endOfLastWeek.getDate() - diff - 1)\n endOfLastWeek.setHours(23, 59, 59, 999)\n\n const startOfLastWeek = new Date(endOfLastWeek)\n startOfLastWeek.setDate(startOfLastWeek.getDate() - 6)\n startOfLastWeek.setHours(0, 0, 0, 0)\n\n return { start: startOfLastWeek, end: endOfLastWeek }\n } else if (unit === 'month') {\n const startOfLastMonth = new Date(today.getFullYear(), today.getMonth() - 1, 1)\n const endOfLastMonth = new Date(today.getFullYear(), today.getMonth(), 0)\n endOfLastMonth.setHours(23, 59, 59, 999)\n return { start: startOfLastMonth, end: endOfLastMonth }\n } else if (unit === 'quarter') {\n const currentQuarter = Math.floor(today.getMonth() / 3)\n const lastQuarter = currentQuarter === 0 ? 3 : currentQuarter - 1\n const lastQuarterYear = currentQuarter === 0 ? today.getFullYear() - 1 : today.getFullYear()\n const startOfLastQuarter = new Date(lastQuarterYear, lastQuarter * 3, 1)\n const endOfLastQuarter = new Date(lastQuarterYear, lastQuarter * 3 + 3, 0)\n endOfLastQuarter.setHours(23, 59, 59, 999)\n return { start: startOfLastQuarter, end: endOfLastQuarter }\n } else if (unit === 'year') {\n const startOfLastYear = new Date(today.getFullYear() - 1, 0, 1)\n const endOfLastYear = new Date(today.getFullYear() - 1, 11, 31)\n endOfLastYear.setHours(23, 59, 59, 999)\n return { start: startOfLastYear, end: endOfLastYear }\n }\n }\n\n return null\n }\n }\n}\n\n/**\n * Format a date range for display (e.g., \"Jan 1, 2024 - Jan 31, 2024\")\n */\nexport function formatDateRangeDisplay(start: Date, end: Date): string {\n const options: Intl.DateTimeFormatOptions = {\n month: 'short',\n day: 'numeric',\n year: 'numeric'\n }\n\n const startStr = start.toLocaleDateString('en-US', options)\n const endStr = end.toLocaleDateString('en-US', options)\n\n // If same day, just show one date\n if (startStr === endStr) {\n return startStr\n }\n\n // If same year, omit year from start date\n if (start.getFullYear() === end.getFullYear()) {\n const startNoYear: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric' }\n return `${start.toLocaleDateString('en-US', startNoYear)} - ${endStr}`\n }\n\n return `${startStr} - ${endStr}`\n}\n\n/**\n * Detect preset ID from a date range value\n * Returns the preset ID (e.g., '7d', 'mtd') or 'custom' if not a preset\n */\nexport function detectPresetFromDateRange(dateRange: string | string[] | undefined): string | null {\n if (!dateRange) return null\n\n // Custom date range (array of dates)\n if (Array.isArray(dateRange)) {\n return 'custom'\n }\n\n const normalizedRange = dateRange.toLowerCase().trim()\n\n // Check regular presets\n for (const preset of DATE_PRESETS) {\n if (preset.value.toLowerCase() === normalizedRange) {\n return preset.id\n }\n }\n\n // Check XTD presets\n for (const preset of XTD_OPTIONS) {\n if (preset.value.toLowerCase() === normalizedRange) {\n return preset.id\n }\n }\n\n // Check for \"last N units\" patterns that don't match exact presets\n const lastNMatch = normalizedRange.match(/^last\\s+(\\d+)\\s+(day|days|week|weeks|month|months|quarter|quarters|year|years)$/i)\n if (lastNMatch) {\n return 'custom' // Dynamic last N is treated as custom\n }\n\n return 'custom'\n}\n\n/**\n * Format filter value for display in a compact chip\n */\nexport function formatFilterValueDisplay(values: any[], operator: string): string {\n if (!values || values.length === 0) {\n // Handle operators that don't need values\n if (operator === 'set') return 'is set'\n if (operator === 'notSet') return 'is not set'\n if (operator === 'isEmpty') return 'is empty'\n if (operator === 'isNotEmpty') return 'is not empty'\n return ''\n }\n\n const formattedValues = values.map(v => {\n if (v === true) return 'true'\n if (v === false) return 'false'\n if (v === null || v === undefined) return 'null'\n return String(v)\n })\n\n switch (operator) {\n case 'equals':\n return formattedValues.length === 1 ? `= ${formattedValues[0]}` : `in (${formattedValues.join(', ')})`\n case 'notEquals':\n return formattedValues.length === 1 ? `!= ${formattedValues[0]}` : `not in (${formattedValues.join(', ')})`\n case 'contains':\n return `contains \"${formattedValues[0]}\"`\n case 'notContains':\n return `!contains \"${formattedValues[0]}\"`\n case 'startsWith':\n return `starts with \"${formattedValues[0]}\"`\n case 'endsWith':\n return `ends with \"${formattedValues[0]}\"`\n case 'gt':\n return `> ${formattedValues[0]}`\n case 'gte':\n return `>= ${formattedValues[0]}`\n case 'lt':\n return `< ${formattedValues[0]}`\n case 'lte':\n return `<= ${formattedValues[0]}`\n case 'between':\n return `${formattedValues[0]} - ${formattedValues[1] || '?'}`\n case 'in':\n return `in (${formattedValues.join(', ')})`\n case 'notIn':\n return `not in (${formattedValues.join(', ')})`\n case 'set':\n return 'is set'\n case 'notSet':\n return 'is not set'\n default:\n return formattedValues.join(', ')\n }\n}\n","/**\n * DatePresetChips Component\n *\n * Quick-select date preset chips for the compact filter bar.\n * Displays common date ranges as clickable chips (Today, Yesterday, 7D, 30D, etc.)\n */\n\nimport React, { useMemo } from 'react'\nimport { DATE_PRESETS, calculateDateRange, formatDateRangeDisplay } from '../shared/utils'\n\ninterface DatePresetChipsProps {\n activePreset: string | null\n onPresetSelect: (presetValue: string) => void\n disabled?: boolean\n}\n\nconst DatePresetChips: React.FC<DatePresetChipsProps> = ({\n activePreset,\n onPresetSelect,\n disabled = false\n}) => {\n // Memoize tooltip content for each preset\n const presetTooltips = useMemo(() => {\n const tooltips: Record<string, string> = {}\n for (const preset of DATE_PRESETS) {\n const range = calculateDateRange(preset.value)\n if (range) {\n tooltips[preset.id] = formatDateRangeDisplay(range.start, range.end)\n }\n }\n return tooltips\n }, [])\n\n return (\n <div className=\"flex items-center gap-1\">\n {DATE_PRESETS.map(preset => {\n const isActive = activePreset === preset.id\n const tooltip = presetTooltips[preset.id]\n\n return (\n <button\n key={preset.id}\n type=\"button\"\n onClick={() => onPresetSelect(preset.value)}\n disabled={disabled}\n title={tooltip}\n className={`\n px-2.5 py-1 rounded text-xs font-medium transition-colors\n focus:outline-none focus:ring-2 focus:ring-offset-1\n disabled:opacity-50 disabled:cursor-not-allowed\n ${isActive ? 'shadow-sm' : 'border'}\n `}\n style={{\n backgroundColor: isActive ? 'var(--dc-primary)' : 'var(--dc-surface)',\n color: isActive ? 'white' : 'var(--dc-text)',\n borderColor: isActive ? 'transparent' : 'var(--dc-border)',\n ...(disabled ? {} : {\n cursor: 'pointer'\n })\n }}\n onMouseEnter={(e) => {\n if (!isActive && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--dc-surface-hover)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--dc-surface)'\n }\n }}\n >\n {preset.label}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport default DatePresetChips\n","/**\n * CustomDateDropdown Component\n *\n * Tabbed dropdown for custom date selection with Fixed, Since, and Last tabs.\n */\n\nimport React, { useState, useEffect, useRef, useCallback } from 'react'\nimport { formatDateForCube, convertDateRangeTypeToValue } from '../shared/utils'\n\ntype TabType = 'fixed' | 'since' | 'last'\ntype LastUnit = 'days' | 'weeks' | 'months' | 'quarters' | 'years'\n\ninterface CustomDateDropdownProps {\n isOpen: boolean\n onClose: () => void\n onDateRangeChange: (dateRange: string | string[]) => void\n currentDateRange?: string | string[]\n anchorRef: React.RefObject<HTMLElement>\n}\n\nconst LAST_UNITS: { value: LastUnit; label: string }[] = [\n { value: 'days', label: 'Days' },\n { value: 'weeks', label: 'Weeks' },\n { value: 'months', label: 'Months' },\n { value: 'quarters', label: 'Quarters' },\n { value: 'years', label: 'Years' }\n]\n\nconst CustomDateDropdown: React.FC<CustomDateDropdownProps> = ({\n isOpen,\n onClose,\n onDateRangeChange,\n currentDateRange\n}) => {\n const dropdownRef = useRef<HTMLDivElement>(null)\n\n // Tab state\n const [activeTab, setActiveTab] = useState<TabType>('fixed')\n\n // Fixed tab state\n const [fixedStartDate, setFixedStartDate] = useState('')\n const [fixedEndDate, setFixedEndDate] = useState('')\n\n // Since tab state\n const [sinceDate, setSinceDate] = useState('')\n\n // Last tab state\n const [lastNumber, setLastNumber] = useState(7)\n const [lastUnit, setLastUnit] = useState<LastUnit>('days')\n\n // Initialize state from current date range\n useEffect(() => {\n if (!currentDateRange) return\n\n if (Array.isArray(currentDateRange)) {\n // Custom date range - set fixed tab\n setActiveTab('fixed')\n setFixedStartDate(currentDateRange[0] || '')\n setFixedEndDate(currentDateRange[1] || currentDateRange[0] || '')\n } else {\n // Check for \"last N units\" pattern\n const lastNMatch = currentDateRange.match(/^last\\s+(\\d+)\\s+(day|days|week|weeks|month|months|quarter|quarters|year|years)$/i)\n if (lastNMatch) {\n setActiveTab('last')\n setLastNumber(parseInt(lastNMatch[1], 10))\n const unit = lastNMatch[2].toLowerCase()\n if (unit === 'day') setLastUnit('days')\n else if (unit === 'week') setLastUnit('weeks')\n else if (unit === 'month') setLastUnit('months')\n else if (unit === 'quarter') setLastUnit('quarters')\n else if (unit === 'year') setLastUnit('years')\n else setLastUnit(unit.endsWith('s') ? unit as LastUnit : `${unit}s` as LastUnit)\n }\n }\n }, [currentDateRange])\n\n // Handle click outside to close\n useEffect(() => {\n if (!isOpen) return\n\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n onClose()\n }\n }\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose()\n }\n }\n\n // Delay adding listener to prevent immediate close\n const timeoutId = setTimeout(() => {\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n }, 0)\n\n return () => {\n clearTimeout(timeoutId)\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n }\n }, [isOpen, onClose])\n\n // Handle apply for Fixed tab\n const handleApplyFixed = useCallback(() => {\n if (fixedStartDate && fixedEndDate) {\n onDateRangeChange([fixedStartDate, fixedEndDate])\n } else if (fixedStartDate) {\n onDateRangeChange([fixedStartDate, fixedStartDate])\n }\n }, [fixedStartDate, fixedEndDate, onDateRangeChange])\n\n // Handle apply for Since tab\n const handleApplySince = useCallback(() => {\n if (sinceDate) {\n const today = formatDateForCube(new Date())\n onDateRangeChange([sinceDate, today])\n }\n }, [sinceDate, onDateRangeChange])\n\n // Handle apply for Last tab\n const handleApplyLast = useCallback(() => {\n if (lastNumber > 0) {\n // Convert to the internal DateRangeType format then to value\n const rangeType = `last_n_${lastUnit}`\n const value = convertDateRangeTypeToValue(rangeType, lastNumber)\n onDateRangeChange(value)\n }\n }, [lastNumber, lastUnit, onDateRangeChange])\n\n if (!isOpen) return null\n\n const tabButtonStyle = (isActive: boolean) => ({\n backgroundColor: isActive ? 'var(--dc-primary)' : 'transparent',\n color: isActive ? 'white' : 'var(--dc-text)',\n borderBottom: isActive ? 'none' : `2px solid var(--dc-border)`\n })\n\n // Stop propagation to prevent parent handlers from interfering\n const handleDropdownClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n }\n\n return (\n <div\n ref={dropdownRef}\n className=\"absolute top-full left-0 mt-1 z-50 border rounded-lg shadow-lg min-w-[280px]\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n borderColor: 'var(--dc-border)',\n boxShadow: '0 10px 25px rgba(0, 0, 0, 0.15)'\n }}\n onClick={handleDropdownClick}\n onMouseDown={handleDropdownClick}\n >\n {/* Tab Headers */}\n <div\n className=\"flex border-b\"\n style={{ borderColor: 'var(--dc-border)' }}\n >\n {(['fixed', 'since', 'last'] as TabType[]).map(tab => (\n <button\n key={tab}\n type=\"button\"\n onClick={() => setActiveTab(tab)}\n className=\"flex-1 px-4 py-2 text-sm font-medium capitalize transition-colors\"\n style={tabButtonStyle(activeTab === tab)}\n >\n {tab}\n </button>\n ))}\n </div>\n\n {/* Tab Content */}\n <div className=\"p-4\">\n {/* Fixed Tab */}\n {activeTab === 'fixed' && (\n <div className=\"space-y-3\">\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n Start Date\n </label>\n <input\n type=\"date\"\n value={fixedStartDate}\n onChange={(e) => setFixedStartDate(e.target.value)}\n className=\"w-full px-3 py-2 text-sm border rounded focus:outline-none focus:ring-2\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-bg)',\n color: 'var(--dc-text)'\n }}\n />\n </div>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n End Date\n </label>\n <input\n type=\"date\"\n value={fixedEndDate}\n onChange={(e) => setFixedEndDate(e.target.value)}\n className=\"w-full px-3 py-2 text-sm border rounded focus:outline-none focus:ring-2\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-bg)',\n color: 'var(--dc-text)'\n }}\n />\n </div>\n <button\n type=\"button\"\n onClick={handleApplyFixed}\n disabled={!fixedStartDate}\n className=\"w-full py-2 text-sm font-medium rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n Apply\n </button>\n </div>\n )}\n\n {/* Since Tab */}\n {activeTab === 'since' && (\n <div className=\"space-y-3\">\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n Since Date\n </label>\n <input\n type=\"date\"\n value={sinceDate}\n onChange={(e) => setSinceDate(e.target.value)}\n className=\"w-full px-3 py-2 text-sm border rounded focus:outline-none focus:ring-2\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-bg)',\n color: 'var(--dc-text)'\n }}\n />\n </div>\n <p\n className=\"text-xs\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n From selected date to today\n </p>\n <button\n type=\"button\"\n onClick={handleApplySince}\n disabled={!sinceDate}\n className=\"w-full py-2 text-sm font-medium rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n Apply\n </button>\n </div>\n )}\n\n {/* Last Tab */}\n {activeTab === 'last' && (\n <div className=\"space-y-3\">\n <div className=\"flex gap-2\">\n <div className=\"flex-1\">\n <label\n className=\"block text-xs font-medium mb-1\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n Number\n </label>\n <input\n type=\"number\"\n min=\"1\"\n max=\"999\"\n value={lastNumber}\n onChange={(e) => setLastNumber(Math.max(1, parseInt(e.target.value, 10) || 1))}\n className=\"w-full px-3 py-2 text-sm border rounded focus:outline-none focus:ring-2\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-bg)',\n color: 'var(--dc-text)'\n }}\n />\n </div>\n <div className=\"flex-1\">\n <label\n className=\"block text-xs font-medium mb-1\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n Unit\n </label>\n <select\n value={lastUnit}\n onChange={(e) => setLastUnit(e.target.value as LastUnit)}\n className=\"w-full px-3 py-2 text-sm border rounded focus:outline-none focus:ring-2\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-bg)',\n color: 'var(--dc-text)'\n }}\n >\n {LAST_UNITS.map(unit => (\n <option key={unit.value} value={unit.value}>\n {unit.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n <p\n className=\"text-xs\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n Last {lastNumber} {lastNumber === 1 ? lastUnit.slice(0, -1) : lastUnit}\n </p>\n <button\n type=\"button\"\n onClick={handleApplyLast}\n disabled={lastNumber < 1}\n className=\"w-full py-2 text-sm font-medium rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n Apply\n </button>\n </div>\n )}\n </div>\n\n {/* Cancel Button */}\n <div\n className=\"px-4 pb-4\"\n >\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full py-2 text-sm font-medium rounded border transition-colors\"\n style={{\n borderColor: 'var(--dc-border)',\n color: 'var(--dc-text-secondary)',\n backgroundColor: 'transparent'\n }}\n >\n Cancel\n </button>\n </div>\n </div>\n )\n}\n\nexport default CustomDateDropdown\n","/**\n * XTDDropdown Component\n *\n * Dropdown for X-to-Date period selections (Week, Month, Quarter, Year to Date).\n */\n\nimport React, { useEffect, useRef } from 'react'\nimport { getIcon } from '../../icons'\nimport { XTD_OPTIONS, calculateDateRange, formatDateRangeDisplay } from '../shared/utils'\n\nconst CheckIcon = getIcon('check')\n\ninterface XTDDropdownProps {\n isOpen: boolean\n onClose: () => void\n onSelect: (xtdValue: string) => void\n currentXTD?: string | null\n anchorRef: React.RefObject<HTMLElement>\n}\n\nconst XTDDropdown: React.FC<XTDDropdownProps> = ({\n isOpen,\n onClose,\n onSelect,\n currentXTD\n}) => {\n const dropdownRef = useRef<HTMLDivElement>(null)\n\n // Handle click outside to close\n useEffect(() => {\n if (!isOpen) return\n\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n onClose()\n }\n }\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose()\n }\n }\n\n // Delay adding listener to prevent immediate close\n const timeoutId = setTimeout(() => {\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n }, 0)\n\n return () => {\n clearTimeout(timeoutId)\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n }\n }, [isOpen, onClose])\n\n if (!isOpen) return null\n\n // Stop propagation to prevent parent handlers from interfering\n const handleDropdownClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n }\n\n return (\n <div\n ref={dropdownRef}\n className=\"absolute top-full left-0 mt-1 z-50 border rounded-lg shadow-lg min-w-[180px] py-1\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n borderColor: 'var(--dc-border)',\n boxShadow: '0 10px 25px rgba(0, 0, 0, 0.15)'\n }}\n onClick={handleDropdownClick}\n onMouseDown={handleDropdownClick}\n >\n {XTD_OPTIONS.map(option => {\n const isActive = currentXTD === option.id\n const dateRange = calculateDateRange(option.value)\n const dateRangeText = dateRange\n ? formatDateRangeDisplay(dateRange.start, dateRange.end)\n : ''\n\n return (\n <button\n key={option.id}\n type=\"button\"\n onClick={() => onSelect(option.value)}\n className=\"w-full px-3 py-2 text-left text-sm transition-colors flex items-center justify-between gap-2\"\n style={{\n backgroundColor: isActive ? 'var(--dc-primary-bg)' : 'transparent',\n color: 'var(--dc-text)'\n }}\n onMouseEnter={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'var(--dc-surface-hover)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n >\n <div className=\"flex flex-col\">\n <span className=\"font-medium\">{option.label}</span>\n {dateRangeText && (\n <span\n className=\"text-xs mt-0.5\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n {dateRangeText}\n </span>\n )}\n </div>\n {isActive && (\n <CheckIcon\n className=\"w-4 h-4 shrink-0\"\n style={{ color: 'var(--dc-primary)' }}\n />\n )}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport default XTDDropdown\n","/**\n * FilterValueSelector Component\n * \n * Smart input component that adapts to operator type:\n * - Combo box for equals/notEquals with API-fetched values\n * - Number input for numeric operators\n * - Date picker for date operators\n * - No input for set/notSet operators\n */\n\nimport React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'\nimport { getIcon } from '../../icons'\nimport { useFilterValues } from '../../hooks/useFilterValues'\nimport { useDebounce } from '../../hooks/useDebounce'\nimport type { FilterValueSelectorProps } from '../QueryBuilder/types'\nimport { FILTER_OPERATORS } from '../QueryBuilder/types'\n\nconst ChevronDownIcon = getIcon('chevronDown')\nconst CloseIcon = getIcon('close')\n\nconst FilterValueSelector: React.FC<FilterValueSelectorProps> = ({\n fieldName,\n operator,\n values,\n onValuesChange,\n schema\n}) => {\n const operatorMeta = FILTER_OPERATORS[operator]\n const [isOpen, setIsOpen] = useState(false)\n const [searchText, setSearchText] = useState('')\n const [hasLoadedInitial, setHasLoadedInitial] = useState(false)\n const dropdownRef = useRef<HTMLDivElement>(null)\n const lastSearchedTerm = useRef<string>('')\n \n // Debounce the search text\n const debouncedSearchText = useDebounce(searchText, 300)\n \n // Check if the field is a dimension (not a measure)\n const isDimension = useMemo(() => schema ? schema.cubes.some(cube => \n cube.dimensions.some(dim => dim.name === fieldName)\n ) : false, [schema, fieldName])\n \n // Check if the field is a time dimension\n const isTimeDimension = useMemo(() => schema ? schema.cubes.some(cube => \n cube.dimensions.some(dim => dim.name === fieldName && dim.type === 'time')\n ) : false, [schema, fieldName])\n \n // Fetch distinct values for combo box (only for equals/notEquals/in/notIn on non-time dimensions)\n const shouldFetchValues = useMemo(() => \n (['equals', 'notEquals', 'in', 'notIn'].includes(operator)) && isDimension && !isTimeDimension,\n [operator, isDimension, isTimeDimension]\n )\n const shouldShowComboBox = shouldFetchValues\n \n const { \n values: distinctValues, \n loading: valuesLoading, \n error: valuesError,\n searchValues\n } = useFilterValues(fieldName, shouldFetchValues)\n \n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n }\n }\n \n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [])\n \n // Load initial values when dropdown opens\n useEffect(() => {\n if (isOpen && shouldFetchValues && searchValues) {\n searchValues('', true) // Force load with empty search\n setHasLoadedInitial(true)\n lastSearchedTerm.current = ''\n }\n }, [isOpen, shouldFetchValues, searchValues])\n \n // Trigger search when debounced search text changes\n useEffect(() => {\n if (hasLoadedInitial && shouldFetchValues && searchValues && debouncedSearchText !== lastSearchedTerm.current) {\n lastSearchedTerm.current = debouncedSearchText\n searchValues(debouncedSearchText)\n }\n }, [debouncedSearchText, hasLoadedInitial, shouldFetchValues, searchValues])\n \n // Handle dropdown toggle\n const handleDropdownToggle = useCallback(() => {\n const newIsOpen = !isOpen\n setIsOpen(newIsOpen)\n \n // Reset search when closing dropdown\n if (!newIsOpen) {\n setSearchText('')\n lastSearchedTerm.current = ''\n }\n }, [isOpen])\n \n // Handle search input change\n const handleSearchChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const newSearchText = e.target.value\n setSearchText(newSearchText)\n }, [])\n \n // Handle value selection for combo box\n const handleValueSelect = useCallback((value: any) => {\n if (operatorMeta.supportsMultipleValues) {\n // Add to selection if not already selected\n if (!values.includes(value)) {\n onValuesChange([...values, value])\n }\n } else {\n // Replace current value\n onValuesChange([value])\n setIsOpen(false)\n }\n // Clear search after selection\n setSearchText('')\n }, [operatorMeta.supportsMultipleValues, values, onValuesChange])\n \n // Handle value removal for multi-select\n const handleValueRemove = useCallback((valueToRemove: any) => {\n onValuesChange(values.filter(v => v !== valueToRemove))\n }, [values, onValuesChange])\n \n // Handle direct text input for non-combo operators\n const handleDirectInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n if (operatorMeta.valueType === 'number') {\n const numValue = parseFloat(value)\n // Accept valid numbers including zero\n if (!isNaN(numValue)) {\n onValuesChange([numValue])\n } else if (value === '' || value === '-') {\n // Allow empty string or just a minus sign for negative numbers being typed\n onValuesChange([])\n }\n } else {\n onValuesChange(value ? [value] : [])\n }\n }, [operatorMeta.valueType, onValuesChange])\n \n // Handle date input\n const handleDateInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n if (operator === 'inDateRange') {\n // For date range, we need two values\n const currentValues = values.length >= 2 ? values : ['', '']\n onValuesChange([value, currentValues[1]])\n } else {\n // Single date value\n onValuesChange(value ? [value] : [])\n }\n }, [operator, values, onValuesChange])\n \n const handleDateRangeEndInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n const currentValues = values.length >= 2 ? values : ['', '']\n onValuesChange([currentValues[0], value])\n }, [values, onValuesChange])\n\n // Handle between/notBetween range inputs (must be defined at top level, not inside conditionals)\n const handleBetweenStartInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = values.length >= 2 ? values : ['', '']\n const newValues = [!isNaN(value) ? value : e.target.value === '' ? '' : currentValues[0], currentValues[1]]\n onValuesChange(newValues.filter(v => v !== ''))\n }, [values, onValuesChange])\n\n const handleBetweenEndInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = values.length >= 2 ? values : ['', '']\n const newValues = [currentValues[0], !isNaN(value) ? value : e.target.value === '' ? '' : currentValues[1]]\n onValuesChange(newValues.filter(v => v !== ''))\n }, [values, onValuesChange])\n\n // Render based on operator type\n if (!operatorMeta.requiresValues) {\n // No input needed for set/notSet\n return (\n <div className=\"text-sm text-dc-text-muted italic\">\n No value required\n </div>\n )\n }\n \n if (operator === 'inDateRange') {\n // Date range picker\n return (\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"date\"\n value={values[0] || ''}\n onChange={handleDateInput}\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"date\"\n value={values[1] || ''}\n onChange={handleDateRangeEndInput}\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n </div>\n )\n }\n \n if (operator === 'between' || operator === 'notBetween') {\n // Between range picker (for numbers)\n return (\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"number\"\n value={values[0] !== undefined && values[0] !== null ? values[0] : ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"number\"\n value={values[1] !== undefined && values[1] !== null ? values[1] : ''}\n onChange={handleBetweenEndInput}\n placeholder=\"Max\"\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n </div>\n )\n }\n \n if (operatorMeta.valueType === 'date') {\n // Single date picker\n return (\n <input\n type=\"date\"\n value={values[0] || ''}\n onChange={handleDateInput}\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n )\n }\n \n if (operatorMeta.valueType === 'number') {\n // Number input\n return (\n <input\n type=\"number\"\n value={values[0] !== undefined && values[0] !== null ? values[0] : ''}\n onChange={handleDirectInput}\n placeholder=\"Enter number\"\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n )\n }\n \n // Time dimension with equals/notEquals/in/notIn - use date picker\n if (isTimeDimension && (['equals', 'notEquals', 'in', 'notIn'].includes(operator))) {\n if (operatorMeta.supportsMultipleValues) {\n // Multi-select date picker (for notEquals that supports multiple values)\n return (\n <div className=\"space-y-2 min-w-0 max-w-full\">\n {/* Selected dates display */}\n {values.length > 0 && (\n <div className=\"flex flex-wrap gap-1 max-w-full\">\n {values.map((value, index) => (\n <div\n key={index}\n className=\"inline-flex items-center bg-dc-time-dimension text-dc-time-dimension text-xs px-2 py-1 rounded-sm border border-dc-time-dimension\"\n >\n <span className=\"mr-1\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"text-dc-accent hover:text-dc-accent focus:outline-hidden\"\n >\n <CloseIcon className=\"w-3 h-3\" />\n </button>\n </div>\n ))}\n </div>\n )}\n \n {/* Add new date */}\n <input\n type=\"date\"\n onChange={(e) => {\n if (e.target.value && !values.includes(e.target.value)) {\n onValuesChange([...values, e.target.value])\n e.target.value = '' // Clear the input\n }\n }}\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n placeholder=\"Add date...\"\n />\n </div>\n )\n } else {\n // Single date picker\n return (\n <input\n type=\"date\"\n value={values[0] || ''}\n onChange={handleDateInput}\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n )\n }\n }\n \n if (shouldShowComboBox) {\n // Combo box with API-fetched values\n return (\n <div className=\"relative min-w-0 max-w-full\" ref={dropdownRef}>\n {/* Selected values display (for multi-select) */}\n {operatorMeta.supportsMultipleValues && values.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mb-2 max-w-full\">\n {values.map((value, index) => (\n <div\n key={index}\n className=\"inline-flex items-center bg-dc-time-dimension text-dc-time-dimension text-xs px-2 py-1 rounded-sm border border-dc-time-dimension\"\n >\n <span className=\"mr-1\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"text-dc-accent hover:text-dc-accent focus:outline-hidden\"\n >\n <CloseIcon className=\"w-3 h-3\" />\n </button>\n </div>\n ))}\n </div>\n )}\n \n {/* Single value display (for single-select) */}\n {!operatorMeta.supportsMultipleValues && values.length > 0 && (\n <div className=\"mb-2\">\n <div className=\"inline-flex items-center bg-dc-time-dimension text-dc-time-dimension text-xs px-2 py-1 rounded-sm border border-dc-time-dimension\">\n <span className=\"mr-1\">{String(values[0])}</span>\n <button\n onClick={() => onValuesChange([])}\n className=\"text-dc-accent hover:text-dc-accent focus:outline-hidden\"\n >\n <CloseIcon className=\"w-3 h-3\" />\n </button>\n </div>\n </div>\n )}\n \n {/* Dropdown trigger */}\n <button\n onClick={handleDropdownToggle}\n className=\"w-full text-left text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface hover:bg-dc-surface-hover focus:ring-2 focus:ring-dc-accent focus:border-dc-accent flex items-center justify-between min-w-0\"\n >\n <span className=\"text-dc-text-muted truncate\">\n {valuesLoading && !hasLoadedInitial ? 'Loading values...' : 'Select value...'}\n </span>\n <ChevronDownIcon className=\"w-4 h-4 text-dc-text-muted\" />\n </button>\n\n {/* Dropdown menu */}\n {isOpen && (\n <div className=\"absolute z-30 left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded-md shadow-lg max-h-60 overflow-y-auto\">\n {/* Search input */}\n <div className=\"p-2 border-b border-dc-border\">\n <input\n type=\"text\"\n value={searchText}\n onChange={handleSearchChange}\n placeholder=\"Search values...\"\n className=\"w-full text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div className=\"max-h-48 overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"p-2 text-sm text-dc-text-muted\">\n {searchText ? 'Searching...' : 'Loading values...'}\n </div>\n ) : valuesError ? (\n <div className=\"p-2 text-sm text-dc-error\">\n Error loading values: {valuesError}\n </div>\n ) : distinctValues.length === 0 ? (\n <div className=\"p-2 text-sm text-dc-text-muted\">\n {searchText ? 'No matching values' : 'No values available'}\n </div>\n ) : (\n distinctValues.map((value, index) => {\n const isSelected = values.includes(value)\n\n return (\n <button\n key={`${value}-${index}`}\n onClick={() => handleValueSelect(value)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover focus:outline-hidden focus:bg-dc-surface-hover ${\n isSelected ? 'bg-dc-accent-bg text-dc-accent' : 'text-dc-text-secondary'\n }`}\n >\n {String(value)}\n {isSelected && (\n <span className=\"float-right text-dc-accent\">✓</span>\n )}\n </button>\n )\n })\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n \n // Fallback to text input\n return (\n <input\n type=\"text\"\n value={values[0] !== undefined && values[0] !== null ? values[0] : ''}\n onChange={handleDirectInput}\n placeholder={`Enter ${operatorMeta.valueType} value`}\n className=\"text-sm border border-dc-border rounded-sm px-2 py-1 bg-dc-surface text-dc-text focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n />\n )\n}\n\nexport default FilterValueSelector","/**\n * FilterValuePopover Component\n *\n * Inline popover for editing filter values.\n * Uses FilterValueSelector for the actual value input.\n */\n\nimport React, { useEffect, useRef, useCallback } from 'react'\nimport FilterValueSelector from '../shared/FilterValueSelector'\nimport type { SimpleFilter, CubeMeta } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\n\ninterface FilterValuePopoverProps {\n filter: SimpleFilter\n schema: CubeMeta | null\n onValuesChange: (values: any[]) => void\n onClose: () => void\n anchorRef: React.RefObject<HTMLElement>\n}\n\n// Convert CubeMeta to MetaResponse format\nfunction convertToMetaResponse(cubeMeta: CubeMeta | null): MetaResponse | null {\n if (!cubeMeta) return null\n\n return {\n cubes: cubeMeta.cubes.map(cube => ({\n name: cube.name,\n title: cube.title || cube.name,\n description: cube.description || '',\n measures: cube.measures.map(m => ({\n name: m.name,\n title: m.title || m.name,\n type: m.type,\n description: '',\n shortTitle: m.shortTitle || m.title || m.name\n })),\n dimensions: cube.dimensions.map(d => ({\n name: d.name,\n title: d.title || d.name,\n type: d.type,\n description: '',\n shortTitle: d.shortTitle || d.title || d.name\n })),\n segments: cube.segments?.map(s => ({\n name: s.name,\n title: s.title || s.name,\n type: s.type,\n description: '',\n shortTitle: s.shortTitle || s.title || s.name\n })) || []\n }))\n }\n}\n\nconst FilterValuePopover: React.FC<FilterValuePopoverProps> = ({\n filter,\n schema,\n onValuesChange,\n onClose,\n anchorRef\n}) => {\n const popoverRef = useRef<HTMLDivElement>(null)\n\n // Handle click outside to close\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n popoverRef.current &&\n !popoverRef.current.contains(event.target as Node) &&\n anchorRef.current &&\n !anchorRef.current.contains(event.target as Node)\n ) {\n onClose()\n }\n }\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose()\n }\n }\n\n // Delay adding listener to prevent immediate close\n const timeoutId = setTimeout(() => {\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n }, 0)\n\n return () => {\n clearTimeout(timeoutId)\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n }\n }, [onClose, anchorRef])\n\n // Handle value change\n const handleValuesChange = useCallback((newValues: any[]) => {\n onValuesChange(newValues)\n }, [onValuesChange])\n\n // Convert schema to MetaResponse format\n const metaResponse = convertToMetaResponse(schema)\n\n return (\n <div\n ref={popoverRef}\n className=\"absolute top-full left-0 mt-1 z-50 border rounded-lg shadow-lg p-3 min-w-[220px]\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n borderColor: 'var(--dc-border)',\n boxShadow: 'var(--dc-shadow-lg)'\n }}\n >\n {/* Filter label */}\n <div\n className=\"text-xs font-medium mb-2\"\n style={{ color: 'var(--dc-text-secondary)' }}\n >\n Edit value\n </div>\n\n {/* Value selector */}\n <div className=\"min-w-[180px]\">\n <FilterValueSelector\n fieldName={filter.member}\n operator={filter.operator}\n values={filter.values || []}\n onValuesChange={handleValuesChange}\n schema={metaResponse}\n />\n </div>\n\n {/* Action buttons */}\n <div className=\"flex justify-end gap-2 mt-3 pt-2 border-t\" style={{ borderColor: 'var(--dc-border)' }}>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-3 py-1 text-xs font-medium rounded border transition-colors\"\n style={{\n borderColor: 'var(--dc-border)',\n color: 'var(--dc-text-secondary)',\n backgroundColor: 'transparent'\n }}\n >\n Close\n </button>\n </div>\n </div>\n )\n}\n\nexport default FilterValuePopover\n","/**\n * FilterChip Component\n *\n * Compact display of non-date filters as clickable chips.\n * Clicking opens a popover for inline value editing.\n */\n\nimport React, { useState, useRef, useCallback } from 'react'\nimport { getIcon } from '../../icons'\nimport FilterValuePopover from './FilterValuePopover'\nimport { formatFilterValueDisplay } from '../shared/utils'\nimport type { DashboardFilter, CubeMeta, SimpleFilter } from '../../types'\n\nconst CloseIcon = getIcon('close')\nconst EditIcon = getIcon('edit')\n\ninterface FilterChipProps {\n filter: DashboardFilter\n schema: CubeMeta | null\n isEditMode: boolean\n onChange: (updatedFilter: DashboardFilter) => void\n onEdit?: () => void\n onRemove?: () => void\n}\n\nconst FilterChip: React.FC<FilterChipProps> = ({\n filter,\n schema,\n isEditMode,\n onChange,\n onEdit,\n onRemove\n}) => {\n const [showPopover, setShowPopover] = useState(false)\n const chipRef = useRef<HTMLDivElement>(null)\n\n // Get filter details\n const simpleFilter = filter.filter as SimpleFilter\n const { label } = filter\n const { operator, values } = simpleFilter\n\n // Format value display\n const valueDisplay = formatFilterValueDisplay(values || [], operator)\n\n // Handle value change from popover\n const handleValueChange = useCallback((newValues: any[]) => {\n onChange({\n ...filter,\n filter: {\n ...simpleFilter,\n values: newValues\n }\n })\n }, [filter, simpleFilter, onChange])\n\n // Handle chip click - open popover in view mode, or edit in edit mode\n const handleChipClick = useCallback(() => {\n if (isEditMode) {\n // In edit mode, clicking opens the full modal\n onEdit?.()\n } else {\n // In view mode, show inline popover for value editing\n setShowPopover(true)\n }\n }, [isEditMode, onEdit])\n\n // Don't show chips for group filters\n if (!('member' in filter.filter)) {\n return null\n }\n\n return (\n <div ref={chipRef} className=\"relative inline-flex\">\n <div\n className={`\n inline-flex items-center gap-1 px-2 py-1 rounded text-xs\n border transition-colors cursor-pointer\n ${isEditMode ? 'pr-1' : ''}\n `}\n style={{\n backgroundColor: 'var(--dc-surface)',\n borderColor: 'var(--dc-border)',\n color: 'var(--dc-text)'\n }}\n onClick={handleChipClick}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--dc-surface-hover)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--dc-surface)'\n }}\n title={`${label} ${valueDisplay}`}\n >\n <span className=\"font-medium truncate max-w-[100px]\">{label}</span>\n {valueDisplay && (\n <>\n <span style={{ color: 'var(--dc-text-secondary)' }}>{valueDisplay}</span>\n </>\n )}\n\n {/* Edit mode: show edit and remove buttons */}\n {isEditMode && (\n <>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onEdit?.()\n }}\n className=\"p-0.5 rounded transition-colors\"\n style={{ color: 'var(--dc-text-secondary)' }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = 'var(--dc-text)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = 'var(--dc-text-secondary)'\n }}\n >\n <EditIcon className=\"w-3 h-3\" />\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onRemove?.()\n }}\n className=\"p-0.5 rounded transition-colors\"\n style={{ color: 'var(--dc-text-secondary)' }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = 'var(--dc-error)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = 'var(--dc-text-secondary)'\n }}\n >\n <CloseIcon className=\"w-3 h-3\" />\n </button>\n </>\n )}\n </div>\n\n {/* Value editing popover (view mode only) */}\n {showPopover && !isEditMode && (\n <FilterValuePopover\n filter={simpleFilter}\n schema={schema}\n onValuesChange={handleValueChange}\n onClose={() => setShowPopover(false)}\n anchorRef={chipRef}\n />\n )}\n </div>\n )\n}\n\nexport default FilterChip\n","/**\n * CompactFilterBar Component\n *\n * A Mixpanel-inspired compact horizontal filter bar for dashboards.\n * Provides quick preset date selection, custom date options, XTD options,\n * and compact non-date filter display.\n */\n\nimport React, { useState, useCallback, useMemo, useRef } from 'react'\nimport { getIcon } from '../../icons'\nimport DatePresetChips from './DatePresetChips'\nimport CustomDateDropdown from './CustomDateDropdown'\nimport XTDDropdown from './XTDDropdown'\nimport FilterChip from './FilterChip'\nimport type { DashboardFilter, CubeMeta, SimpleFilter } from '../../types'\nimport {\n detectPresetFromDateRange,\n calculateDateRange,\n formatDateRangeDisplay,\n XTD_OPTIONS\n} from '../shared/utils'\n\nconst AddIcon = getIcon('add')\nconst CalendarIcon = getIcon('timeDimension')\nconst ChevronDownIcon = getIcon('chevronDown')\nconst FilterIcon = getIcon('filter')\n\ninterface CompactFilterBarProps {\n dashboardFilters: DashboardFilter[]\n schema: CubeMeta | null\n isEditMode: boolean\n onDashboardFiltersChange: (filters: DashboardFilter[]) => void\n onAddFilter?: () => void\n onEditFilter?: (filterId: string) => void\n onRemoveFilter?: (filterId: string) => void\n}\n\nconst CompactFilterBar: React.FC<CompactFilterBarProps> = ({\n dashboardFilters,\n schema,\n isEditMode,\n onDashboardFiltersChange,\n onAddFilter,\n onEditFilter,\n onRemoveFilter\n}) => {\n // Dropdown state\n const [showCustomDropdown, setShowCustomDropdown] = useState(false)\n const [showXTDDropdown, setShowXTDDropdown] = useState(false)\n\n // Refs for dropdown positioning\n const customButtonRef = useRef<HTMLButtonElement>(null)\n const xtdButtonRef = useRef<HTMLButtonElement>(null)\n\n // Find universal time filter\n const universalTimeFilter = useMemo(() => {\n return dashboardFilters.find(df => df.isUniversalTime)\n }, [dashboardFilters])\n\n // Get current date range from universal time filter\n const currentDateRange = useMemo(() => {\n if (!universalTimeFilter) return null\n const filter = universalTimeFilter.filter as SimpleFilter\n // Handle both dateRange property and values array\n if (filter.dateRange) return filter.dateRange\n if (filter.values && filter.values.length > 0) {\n // Single string value (preset) - return as string\n if (filter.values.length === 1 && typeof filter.values[0] === 'string') {\n return filter.values[0]\n }\n // Array of dates for custom range\n return filter.values\n }\n return null\n }, [universalTimeFilter])\n\n // Detect active preset from current date range\n const activePresetId = useMemo(() => {\n return detectPresetFromDateRange(currentDateRange as string | string[] | undefined)\n }, [currentDateRange])\n\n // Check if XTD is active\n const activeXTDId = useMemo(() => {\n if (!currentDateRange || Array.isArray(currentDateRange)) return null\n const preset = detectPresetFromDateRange(currentDateRange)\n return XTD_OPTIONS.find(opt => opt.id === preset)?.id || null\n }, [currentDateRange])\n\n // Get non-date filters (exclude universal time filter)\n const nonDateFilters = useMemo(() => {\n return dashboardFilters.filter(df => !df.isUniversalTime)\n }, [dashboardFilters])\n\n // Generate unique ID for new filters\n const generateFilterId = useCallback(() => {\n return `df_${Date.now()}_${Math.random().toString(36).substring(7)}`\n }, [])\n\n // Handle date range change (preset, custom, or XTD)\n const handleDateRangeChange = useCallback((newDateRange: string | string[]) => {\n if (universalTimeFilter) {\n // Update existing filter\n const updatedFilters = dashboardFilters.map(df => {\n if (df.id === universalTimeFilter.id) {\n return {\n ...df,\n filter: {\n ...(df.filter as SimpleFilter),\n values: Array.isArray(newDateRange) ? newDateRange : [newDateRange],\n dateRange: newDateRange\n }\n }\n }\n return df\n })\n onDashboardFiltersChange(updatedFilters)\n } else {\n // Create new universal time filter\n const newFilter: DashboardFilter = {\n id: generateFilterId(),\n label: 'Date Range',\n isUniversalTime: true,\n filter: {\n member: '__universal_time__',\n operator: 'inDateRange',\n values: Array.isArray(newDateRange) ? newDateRange : [newDateRange],\n dateRange: newDateRange\n }\n }\n onDashboardFiltersChange([...dashboardFilters, newFilter])\n }\n }, [dashboardFilters, universalTimeFilter, onDashboardFiltersChange, generateFilterId])\n\n // Handle preset selection\n const handlePresetSelect = useCallback((presetValue: string) => {\n handleDateRangeChange(presetValue)\n }, [handleDateRangeChange])\n\n // Handle XTD selection\n const handleXTDSelect = useCallback((xtdValue: string) => {\n handleDateRangeChange(xtdValue)\n setShowXTDDropdown(false)\n }, [handleDateRangeChange])\n\n // Handle custom date selection\n const handleCustomDateSelect = useCallback((dateRange: string | string[]) => {\n handleDateRangeChange(dateRange)\n setShowCustomDropdown(false)\n }, [handleDateRangeChange])\n\n // Handle filter value change (for non-date filters)\n const handleFilterChange = useCallback((filterId: string, updatedFilter: DashboardFilter) => {\n const updatedFilters = dashboardFilters.map(df =>\n df.id === filterId ? updatedFilter : df\n )\n onDashboardFiltersChange(updatedFilters)\n }, [dashboardFilters, onDashboardFiltersChange])\n\n // Calculate tooltip for active date range\n const dateRangeTooltip = useMemo(() => {\n if (!currentDateRange) return null\n\n if (Array.isArray(currentDateRange)) {\n // Custom date range - format the dates\n const start = new Date(currentDateRange[0])\n const end = new Date(currentDateRange[1] || currentDateRange[0])\n return formatDateRangeDisplay(start, end)\n }\n\n // Preset - calculate the actual range\n const range = calculateDateRange(currentDateRange)\n if (range) {\n return formatDateRangeDisplay(range.start, range.end)\n }\n\n return currentDateRange\n }, [currentDateRange])\n\n // If no filters and not in edit mode, don't show anything\n if (!isEditMode && dashboardFilters.length === 0) {\n return null\n }\n\n return (\n <div\n className=\"border rounded-lg\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-surface)'\n }}\n >\n {/* Desktop Layout */}\n <div className=\"hidden md:flex items-center gap-2 px-3 py-2\">\n {/* Filter Icon */}\n <FilterIcon\n className=\"w-4 h-4 shrink-0\"\n style={{ color: 'var(--dc-text-secondary)' }}\n />\n\n {/* Date Preset Chips */}\n <DatePresetChips\n activePreset={activePresetId !== 'custom' && !activeXTDId ? activePresetId : null}\n onPresetSelect={handlePresetSelect}\n />\n\n {/* Custom Date Button */}\n <div className=\"relative\">\n <button\n ref={customButtonRef}\n type=\"button\"\n onClick={() => {\n setShowCustomDropdown(!showCustomDropdown)\n setShowXTDDropdown(false)\n }}\n title={activePresetId === 'custom' && dateRangeTooltip ? dateRangeTooltip : 'Custom date range'}\n className={`\n flex items-center gap-1 px-2.5 py-1 rounded text-xs font-medium border\n transition-colors focus:outline-none focus:ring-2 focus:ring-offset-1\n `}\n style={{\n backgroundColor: activePresetId === 'custom' ? 'var(--dc-primary)' : 'var(--dc-surface)',\n color: activePresetId === 'custom' ? 'white' : 'var(--dc-text)',\n borderColor: activePresetId === 'custom' ? 'transparent' : 'var(--dc-border)'\n }}\n >\n <CalendarIcon className=\"w-3 h-3\" />\n <span>Custom</span>\n <ChevronDownIcon className=\"w-3 h-3\" />\n </button>\n\n {showCustomDropdown && (\n <CustomDateDropdown\n isOpen={showCustomDropdown}\n onClose={() => setShowCustomDropdown(false)}\n onDateRangeChange={handleCustomDateSelect}\n currentDateRange={currentDateRange as string | string[] | undefined}\n anchorRef={customButtonRef}\n />\n )}\n </div>\n\n {/* XTD Button */}\n <div className=\"relative\">\n <button\n ref={xtdButtonRef}\n type=\"button\"\n onClick={() => {\n setShowXTDDropdown(!showXTDDropdown)\n setShowCustomDropdown(false)\n }}\n title={activeXTDId && dateRangeTooltip ? dateRangeTooltip : 'X to Date options'}\n className={`\n flex items-center gap-1 px-2.5 py-1 rounded text-xs font-medium border\n transition-colors focus:outline-none focus:ring-2 focus:ring-offset-1\n `}\n style={{\n backgroundColor: activeXTDId ? 'var(--dc-primary)' : 'var(--dc-surface)',\n color: activeXTDId ? 'white' : 'var(--dc-text)',\n borderColor: activeXTDId ? 'transparent' : 'var(--dc-border)'\n }}\n >\n <span>XTD</span>\n <ChevronDownIcon className=\"w-3 h-3\" />\n </button>\n\n {showXTDDropdown && (\n <XTDDropdown\n isOpen={showXTDDropdown}\n onClose={() => setShowXTDDropdown(false)}\n onSelect={handleXTDSelect}\n currentXTD={activeXTDId}\n anchorRef={xtdButtonRef}\n />\n )}\n </div>\n\n {/* Separator */}\n {nonDateFilters.length > 0 && (\n <div\n className=\"h-5 w-px mx-1\"\n style={{ backgroundColor: 'var(--dc-border)' }}\n />\n )}\n\n {/* Non-date Filter Chips */}\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {nonDateFilters.map(filter => (\n <FilterChip\n key={filter.id}\n filter={filter}\n schema={schema}\n isEditMode={isEditMode}\n onChange={(updatedFilter) => handleFilterChange(filter.id, updatedFilter)}\n onEdit={() => onEditFilter?.(filter.id)}\n onRemove={() => onRemoveFilter?.(filter.id)}\n />\n ))}\n </div>\n\n {/* Add Filter Button (Edit Mode) */}\n {isEditMode && onAddFilter && (\n <button\n type=\"button\"\n onClick={onAddFilter}\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs font-medium border transition-colors\"\n style={{\n borderColor: 'var(--dc-border)',\n color: 'var(--dc-text-secondary)',\n backgroundColor: 'transparent'\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--dc-surface-hover)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n >\n <AddIcon className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n\n {/* Mobile Layout */}\n <div className=\"md:hidden\">\n {/* Presets row with horizontal scroll */}\n <div className=\"flex items-center gap-2 overflow-x-auto px-3 py-2 scrollbar-thin\">\n {/* Filter Icon */}\n <FilterIcon\n className=\"w-4 h-4 shrink-0\"\n style={{ color: 'var(--dc-text-secondary)' }}\n />\n <DatePresetChips\n activePreset={activePresetId !== 'custom' && !activeXTDId ? activePresetId : null}\n onPresetSelect={handlePresetSelect}\n />\n </div>\n\n {/* Custom, XTD, and Add buttons */}\n <div\n className=\"flex items-center justify-between px-3 py-2 border-t\"\n style={{ borderColor: 'var(--dc-border)' }}\n >\n <div className=\"flex items-center gap-2\">\n {/* Custom Button */}\n <div className=\"relative\">\n <button\n ref={customButtonRef}\n type=\"button\"\n onClick={() => {\n setShowCustomDropdown(!showCustomDropdown)\n setShowXTDDropdown(false)\n }}\n className={`\n flex items-center gap-1 px-2.5 py-1 rounded text-xs font-medium border\n transition-colors\n `}\n style={{\n backgroundColor: activePresetId === 'custom' ? 'var(--dc-primary)' : 'var(--dc-surface)',\n color: activePresetId === 'custom' ? 'white' : 'var(--dc-text)',\n borderColor: activePresetId === 'custom' ? 'transparent' : 'var(--dc-border)'\n }}\n >\n <CalendarIcon className=\"w-3 h-3\" />\n <span>Custom</span>\n </button>\n\n {showCustomDropdown && (\n <CustomDateDropdown\n isOpen={showCustomDropdown}\n onClose={() => setShowCustomDropdown(false)}\n onDateRangeChange={handleCustomDateSelect}\n currentDateRange={currentDateRange as string | string[] | undefined}\n anchorRef={customButtonRef}\n />\n )}\n </div>\n\n {/* XTD Button */}\n <div className=\"relative\">\n <button\n ref={xtdButtonRef}\n type=\"button\"\n onClick={() => {\n setShowXTDDropdown(!showXTDDropdown)\n setShowCustomDropdown(false)\n }}\n className={`\n flex items-center gap-1 px-2.5 py-1 rounded text-xs font-medium border\n transition-colors\n `}\n style={{\n backgroundColor: activeXTDId ? 'var(--dc-primary)' : 'var(--dc-surface)',\n color: activeXTDId ? 'white' : 'var(--dc-text)',\n borderColor: activeXTDId ? 'transparent' : 'var(--dc-border)'\n }}\n >\n <span>XTD</span>\n <ChevronDownIcon className=\"w-3 h-3\" />\n </button>\n\n {showXTDDropdown && (\n <XTDDropdown\n isOpen={showXTDDropdown}\n onClose={() => setShowXTDDropdown(false)}\n onSelect={handleXTDSelect}\n currentXTD={activeXTDId}\n anchorRef={xtdButtonRef}\n />\n )}\n </div>\n </div>\n\n {/* Add Filter Button (Edit Mode) */}\n {isEditMode && onAddFilter && (\n <button\n type=\"button\"\n onClick={onAddFilter}\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs font-medium border transition-colors\"\n style={{\n borderColor: 'var(--dc-border)',\n color: 'var(--dc-text-secondary)',\n backgroundColor: 'transparent'\n }}\n >\n <AddIcon className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n\n {/* Non-date Filter Chips (Mobile) */}\n {nonDateFilters.length > 0 && (\n <div\n className=\"px-3 py-2 border-t\"\n style={{ borderColor: 'var(--dc-border)' }}\n >\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {nonDateFilters.map(filter => (\n <FilterChip\n key={filter.id}\n filter={filter}\n schema={schema}\n isEditMode={isEditMode}\n onChange={(updatedFilter) => handleFilterChange(filter.id, updatedFilter)}\n onEdit={() => onEditFilter?.(filter.id)}\n onRemove={() => onRemoveFilter?.(filter.id)}\n />\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default CompactFilterBar\n","/**\n * DashboardFilterPanel Component\n *\n * Orchestrates dashboard-level filtering UI\n * - Edit mode: Shows filter chips with edit/delete actions\n * - View mode: Shows interactive read-only filters\n *\n * Pattern: Simplified coordination layer (matches portlet editing pattern)\n * - No local editing state (modal owns all edit state)\n * - Just tracks which filter is being edited and modal visibility\n * - Delegates to FilterEditModal for all editing logic\n */\n\nimport React, { useState, useCallback } from 'react'\nimport FilterEditModal from './DashboardFilters/FilterEditModal'\nimport EditModeFilterList from './DashboardFilters/EditModeFilterList'\nimport CompactFilterBar from './DashboardFilters/CompactFilterBar'\nimport type { DashboardFilter, CubeMeta, DashboardConfig } from '../types'\nimport type { MetaResponse } from '../shared/types'\n\ninterface DashboardFilterPanelProps {\n dashboardFilters: DashboardFilter[]\n editable: boolean\n schema: CubeMeta | null\n dashboardConfig: DashboardConfig\n onDashboardFiltersChange: (filters: DashboardFilter[]) => void\n onSaveFilters?: (filters: DashboardFilter[]) => void | Promise<void>\n selectedFilterId?: string | null\n onFilterSelect?: (filterId: string) => void\n isEditMode?: boolean\n}\n\nconst DashboardFilterPanel: React.FC<DashboardFilterPanelProps> = ({\n dashboardFilters,\n editable,\n schema,\n dashboardConfig,\n onDashboardFiltersChange,\n onSaveFilters,\n selectedFilterId,\n onFilterSelect,\n isEditMode = false\n}) => {\n // Track which filter is being edited and modal visibility (no local editing state)\n const [editingFilter, setEditingFilter] = useState<DashboardFilter | null>(null)\n const [showFilterBuilder, setShowFilterBuilder] = useState(false)\n\n // Convert CubeMeta to MetaResponse (QueryBuilder type)\n const convertToMetaResponse = useCallback((cubeMeta: CubeMeta | null): MetaResponse | null => {\n if (!cubeMeta) return null\n\n return {\n cubes: cubeMeta.cubes.map(cube => ({\n name: cube.name,\n title: cube.title || cube.name,\n description: cube.description || '',\n measures: cube.measures.map(m => ({\n name: m.name,\n title: m.title,\n type: m.type,\n description: '',\n shortTitle: m.shortTitle\n })),\n dimensions: cube.dimensions.map(d => ({\n name: d.name,\n title: d.title,\n type: d.type,\n description: '',\n shortTitle: d.shortTitle\n })),\n segments: cube.segments?.map(s => ({\n name: s.name,\n title: s.title,\n type: s.type,\n description: '',\n shortTitle: s.shortTitle\n })) || []\n }))\n }\n }, [])\n\n // Generate unique ID for new filters\n const generateFilterId = useCallback(() => {\n return `df_${Date.now()}_${Math.random().toString(36).substring(7)}`\n }, [])\n\n // Handle adding a new filter - create temporary filter for modal\n const handleAddFilter = useCallback(() => {\n const newFilter: DashboardFilter = {\n id: generateFilterId(),\n label: `Filter ${dashboardFilters.length + 1}`,\n filter: {\n member: '',\n operator: 'equals',\n values: []\n }\n }\n setEditingFilter(newFilter)\n setShowFilterBuilder(true)\n }, [dashboardFilters.length, generateFilterId])\n\n // Handle adding a universal time filter - applies to all time dimensions\n // Creates filter directly without opening modal (fixed name, user just sets date range in view mode)\n const handleAddTimeFilter = useCallback(() => {\n const newFilter: DashboardFilter = {\n id: generateFilterId(),\n label: 'Date Range Filter',\n isUniversalTime: true,\n filter: {\n member: '__universal_time__', // Placeholder, not used in merge logic\n operator: 'inDateRange',\n values: ['last 30 days']\n }\n }\n // Add directly to filters without opening modal\n const updatedFilters = [...dashboardFilters, newFilter]\n onDashboardFiltersChange(updatedFilters)\n }, [generateFilterId, dashboardFilters, onDashboardFiltersChange])\n\n // Handle editing an existing filter - just open modal with filter\n const handleEditFilter = useCallback((filterId: string) => {\n const filterToEdit = dashboardFilters.find(df => df.id === filterId)\n if (filterToEdit) {\n setEditingFilter(filterToEdit)\n setShowFilterBuilder(true)\n }\n }, [dashboardFilters])\n\n // Handle removing a filter - simple filter list update\n const handleRemoveFilter = useCallback((filterId: string) => {\n const updatedFilters = dashboardFilters.filter(df => df.id !== filterId)\n onDashboardFiltersChange(updatedFilters)\n\n // Close modal if we're deleting the filter being edited\n if (editingFilter?.id === filterId) {\n setEditingFilter(null)\n setShowFilterBuilder(false)\n }\n }, [dashboardFilters, editingFilter, onDashboardFiltersChange])\n\n // Handle save from modal - update or add filter and save\n const handleSaveFilter = useCallback(async (filterData: DashboardFilter) => {\n // Check if this is a new filter (not in current list) or an update\n const existingFilterIndex = dashboardFilters.findIndex(f => f.id === filterData.id)\n\n let updatedFilters: DashboardFilter[]\n if (existingFilterIndex >= 0) {\n // Update existing filter\n updatedFilters = dashboardFilters.map(f =>\n f.id === filterData.id ? filterData : f\n )\n } else {\n // Add new filter\n updatedFilters = [...dashboardFilters, filterData]\n }\n\n // Update dashboard state\n onDashboardFiltersChange(updatedFilters)\n\n // Trigger save if callback provided\n if (onSaveFilters) {\n try {\n await onSaveFilters(updatedFilters)\n } catch (error) {\n console.error('Failed to save filters:', error)\n throw error // Re-throw so modal can handle it\n }\n }\n }, [dashboardFilters, onDashboardFiltersChange, onSaveFilters])\n\n // Handle modal close - just clean up state\n const handleCloseFilterBuilder = useCallback(() => {\n setEditingFilter(null)\n setShowFilterBuilder(false)\n }, [])\n\n // Hide filter panel completely when not editable (fully embedded mode without filter support)\n if (!editable) {\n return null\n }\n\n // Hide if no filters exist and not in edit mode (nothing to show)\n if (!isEditMode && dashboardFilters.length === 0) {\n return null\n }\n\n return (\n <div className=\"mb-4\">\n {/* Edit Mode - Full filter management with chips and actions */}\n {isEditMode ? (\n <div\n className=\"border rounded-lg\"\n style={{\n borderColor: 'var(--dc-border)',\n backgroundColor: 'var(--dc-surface)',\n boxShadow: 'var(--dc-shadow-sm)'\n }}\n >\n <EditModeFilterList\n dashboardFilters={dashboardFilters}\n onAddFilter={handleAddFilter}\n onAddTimeFilter={handleAddTimeFilter}\n onEditFilter={handleEditFilter}\n onRemoveFilter={handleRemoveFilter}\n selectedFilterId={selectedFilterId}\n onFilterSelect={onFilterSelect}\n />\n </div>\n ) : (\n /* View Mode - Compact Mixpanel-style filter bar */\n <CompactFilterBar\n dashboardFilters={dashboardFilters}\n schema={schema}\n isEditMode={false}\n onDashboardFiltersChange={onDashboardFiltersChange}\n onAddFilter={handleAddFilter}\n onEditFilter={handleEditFilter}\n onRemoveFilter={handleRemoveFilter}\n />\n )}\n\n {/* Filter Edit Modal */}\n {editable && showFilterBuilder && editingFilter && (\n <FilterEditModal\n filter={editingFilter}\n schema={schema}\n dashboardConfig={dashboardConfig}\n isOpen={showFilterBuilder}\n onSave={handleSaveFilter}\n onClose={handleCloseFilterBuilder}\n onDelete={() => handleRemoveFilter(editingFilter.id)}\n convertToMetaResponse={convertToMetaResponse}\n />\n )}\n </div>\n )\n}\n\nexport default DashboardFilterPanel\n","/**\n * ScaledGridWrapper component\n * Applies CSS transform scaling to the dashboard grid for intermediate screen sizes\n * Maintains the exact desktop layout appearance, just proportionally smaller\n */\n\nimport React, { useState, useEffect, useRef } from 'react'\n\ninterface ScaledGridWrapperProps {\n scaleFactor: number\n designWidth: number\n children: React.ReactNode\n}\n\n/**\n * Wrapper component that scales the grid using CSS transform\n * Handles height compensation to prevent overflow/whitespace issues\n */\nexport default function ScaledGridWrapper({\n scaleFactor,\n designWidth,\n children\n}: ScaledGridWrapperProps) {\n const [actualHeight, setActualHeight] = useState(0)\n const innerRef = useRef<HTMLDivElement>(null)\n\n // Measure actual grid height to calculate visible height\n useEffect(() => {\n if (!innerRef.current) return\n\n const observer = new ResizeObserver((entries) => {\n setActualHeight(entries[0]?.contentRect.height ?? 0)\n })\n\n observer.observe(innerRef.current)\n\n // Set initial height\n setActualHeight(innerRef.current.offsetHeight || 0)\n\n return () => observer.disconnect()\n }, [])\n\n // The scaled visual height\n const visualHeight = actualHeight * scaleFactor\n\n return (\n <div\n className=\"scaled-grid-container\"\n style={{\n height: visualHeight > 0 ? visualHeight : 'auto',\n overflow: 'hidden',\n width: '100%'\n }}\n >\n <div\n ref={innerRef}\n className=\"scaled-grid-inner\"\n style={{\n transform: `scale(${scaleFactor})`,\n transformOrigin: 'top left',\n width: designWidth\n }}\n >\n {children}\n </div>\n </div>\n )\n}\n","/**\n * MobileStackedLayout component\n * Simple vertical stack layout for mobile screens (<768px)\n * Read-only view with portlets sorted by grid position\n */\n\nimport { useMemo, useRef, useState, useCallback } from 'react'\nimport { getIcon } from '../icons'\nimport AnalyticsPortlet from './AnalyticsPortlet'\n\nconst RefreshIcon = getIcon('refresh')\nimport { ScrollContainerProvider } from '../providers/ScrollContainerContext'\nimport type { DashboardFilter, DashboardConfig } from '../types'\nimport type { ColorPalette } from '../utils/colorPalettes'\n\n/**\n * Finds the nearest scrollable ancestor of an element.\n */\nfunction findScrollableAncestor(element: HTMLElement | null): HTMLElement | null {\n if (!element) return null\n\n let current = element.parentElement\n\n while (current) {\n const style = window.getComputedStyle(current)\n const overflowY = style.overflowY\n const overflowX = style.overflowX\n\n const hasScrollableOverflow =\n overflowY === 'auto' || overflowY === 'scroll' ||\n overflowX === 'auto' || overflowX === 'scroll'\n\n const hasScrollContent =\n current.scrollHeight > current.clientHeight ||\n current.scrollWidth > current.clientWidth\n\n if (hasScrollableOverflow && hasScrollContent) {\n return current\n }\n\n if (current === document.body) break\n current = current.parentElement\n }\n\n return null\n}\n\ninterface MobileStackedLayoutProps {\n config: DashboardConfig\n colorPalette?: ColorPalette\n dashboardFilters?: DashboardFilter[]\n onPortletRefresh?: (portletId: string) => void\n}\n\n/**\n * Mobile-optimized stacked layout for dashboard portlets\n * Renders portlets in a single column, sorted by grid position\n */\nexport default function MobileStackedLayout({\n config,\n colorPalette,\n dashboardFilters,\n onPortletRefresh\n}: MobileStackedLayoutProps) {\n const portletComponentRefs = useRef<{ [key: string]: { refresh: () => void } | null }>({})\n\n // Scroll container detection for lazy loading\n const [scrollContainer, setScrollContainer] = useState<HTMLElement | null>(null)\n const containerRef = useRef<HTMLDivElement | null>(null)\n\n const setContainerRef = useCallback((node: HTMLDivElement | null) => {\n containerRef.current = node\n if (node) {\n setScrollContainer(findScrollableAncestor(node))\n }\n }, [])\n\n // Sort portlets by y position, then x position (top-to-bottom, left-to-right)\n const sortedPortlets = useMemo(() => {\n return [...config.portlets].sort((a, b) => {\n if (a.y !== b.y) return a.y - b.y\n return a.x - b.x\n })\n }, [config.portlets])\n\n const handlePortletRefresh = (portletId: string) => {\n // Refresh the specific portlet component\n portletComponentRefs.current[portletId]?.refresh()\n // Also call external handler if provided\n onPortletRefresh?.(portletId)\n }\n\n return (\n <ScrollContainerProvider value={scrollContainer}>\n <div ref={setContainerRef} className=\"mobile-stacked-layout space-y-4 px-2\">\n {sortedPortlets.map(portlet => {\n // Calculate height: use stored h * rowHeight (80px), with minimum\n const portletHeight = Math.max(300, portlet.h * 80)\n // Header is approximately 40px when shown\n const headerHeight = portlet.displayConfig?.hideHeader ? 0 : 40\n // Content height = total - header - padding (py-3 = 24px)\n const contentHeight = portletHeight - headerHeight - 24\n\n return (\n <div\n key={portlet.id}\n data-portlet-id={portlet.id}\n className=\"bg-dc-surface border border-dc-border rounded-lg flex flex-col\"\n style={{\n height: portletHeight,\n boxShadow: 'var(--dc-shadow-sm)'\n }}\n >\n {/* Portlet Header - Simplified for mobile (no edit controls) */}\n {!portlet.displayConfig?.hideHeader && (\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-dc-border shrink-0 bg-dc-surface-secondary rounded-t-lg\">\n <h3 className=\"font-semibold text-sm text-dc-text truncate flex-1\">\n {portlet.title}\n </h3>\n <div className=\"flex items-center gap-1 shrink-0 ml-2\">\n <button\n onClick={() => handlePortletRefresh(portlet.id)}\n className=\"p-1 bg-transparent border-none rounded-sm text-dc-text-secondary cursor-pointer hover:bg-dc-surface-hover transition-colors\"\n title=\"Refresh portlet data\"\n >\n <RefreshIcon style={{ width: '16px', height: '16px', color: 'currentColor' }} />\n </button>\n </div>\n </div>\n )}\n\n {/* Portlet Content - explicit height for charts to render */}\n <div\n className=\"px-2 py-3 overflow-visible flex flex-col\"\n style={{ height: contentHeight }}\n >\n <AnalyticsPortlet\n ref={el => { portletComponentRefs.current[portlet.id] = el }}\n query={portlet.query}\n chartType={portlet.chartType}\n chartConfig={portlet.chartConfig}\n displayConfig={portlet.displayConfig}\n dashboardFilters={dashboardFilters}\n dashboardFilterMapping={portlet.dashboardFilterMapping}\n eagerLoad={portlet.eagerLoad ?? config.eagerLoad ?? false}\n title={portlet.title}\n height={contentHeight}\n colorPalette={colorPalette}\n />\n </div>\n </div>\n )\n })}\n </div>\n </ScrollContainerProvider>\n )\n}\n","const isIterable = (obj) => Symbol.iterator in obj;\nconst hasIterableEntries = (value) => (\n // HACK: avoid checking entries type\n \"entries\" in value\n);\nconst compareEntries = (valueA, valueB) => {\n const mapA = valueA instanceof Map ? valueA : new Map(valueA.entries());\n const mapB = valueB instanceof Map ? valueB : new Map(valueB.entries());\n if (mapA.size !== mapB.size) {\n return false;\n }\n for (const [key, value] of mapA) {\n if (!mapB.has(key) || !Object.is(value, mapB.get(key))) {\n return false;\n }\n }\n return true;\n};\nconst compareIterables = (valueA, valueB) => {\n const iteratorA = valueA[Symbol.iterator]();\n const iteratorB = valueB[Symbol.iterator]();\n let nextA = iteratorA.next();\n let nextB = iteratorB.next();\n while (!nextA.done && !nextB.done) {\n if (!Object.is(nextA.value, nextB.value)) {\n return false;\n }\n nextA = iteratorA.next();\n nextB = iteratorB.next();\n }\n return !!nextA.done && !!nextB.done;\n};\nfunction shallow(valueA, valueB) {\n if (Object.is(valueA, valueB)) {\n return true;\n }\n if (typeof valueA !== \"object\" || valueA === null || typeof valueB !== \"object\" || valueB === null) {\n return false;\n }\n if (Object.getPrototypeOf(valueA) !== Object.getPrototypeOf(valueB)) {\n return false;\n }\n if (isIterable(valueA) && isIterable(valueB)) {\n if (hasIterableEntries(valueA) && hasIterableEntries(valueB)) {\n return compareEntries(valueA, valueB);\n }\n return compareIterables(valueA, valueB);\n }\n return compareEntries(\n { entries: () => Object.entries(valueA) },\n { entries: () => Object.entries(valueB) }\n );\n}\n\nexport { shallow };\n","import React from 'react';\nimport { shallow } from 'zustand/vanilla/shallow';\n\nfunction useShallow(selector) {\n const prev = React.useRef(void 0);\n return (state) => {\n const next = selector(state);\n return shallow(prev.current, next) ? prev.current : prev.current = next;\n };\n}\n\nexport { useShallow };\n","/**\n * useDashboard - Master Coordination Hook\n *\n * The single hook that provides everything DashboardGrid needs:\n * - Zustand store state and actions (from Context)\n * - Computed values (canEdit, resolvedRows, etc.)\n * - Config-modifying actions (that call onConfigChange/onSave)\n *\n * This hook replaces 14+ useState calls and 25+ useCallback handlers,\n * providing a clean interface for the DashboardGrid component.\n *\n * IMPORTANT: This hook must be used within DashboardStoreProvider\n *\n * Usage:\n * ```tsx\n * const dashboard = useDashboard({\n * config,\n * editable,\n * gridSettings,\n * onConfigChange,\n * onSave,\n * })\n *\n * // Access state\n * const { isEditMode, selectedFilterId } = dashboard\n *\n * // Access computed values\n * const { canEdit, resolvedRows } = dashboard\n *\n * // Access actions\n * dashboard.actions.openAddPortlet()\n * ```\n */\n\nimport React, { useMemo, useCallback, useRef } from 'react'\nimport { useShallow } from 'zustand/react/shallow'\nimport {\n useDashboardStore,\n type DashboardStore,\n type PortletDebugDataEntry,\n} from '../stores/dashboardStore'\nimport type { LayoutItem } from 'react-grid-layout'\nimport type {\n DashboardConfig,\n PortletConfig,\n RowLayout,\n RowLayoutColumn,\n DashboardFilter,\n DashboardGridSettings,\n DashboardLayoutMode,\n} from '../types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseDashboardOptions {\n /** Dashboard configuration */\n config: DashboardConfig\n /** Whether dashboard is editable */\n editable?: boolean\n /** Dashboard filters */\n dashboardFilters?: DashboardFilter[]\n /** Grid settings */\n gridSettings: DashboardGridSettings\n /** Allowed layout modes */\n allowedModes?: DashboardLayoutMode[]\n /** Whether responsive mode allows editing (desktop only) */\n isResponsiveEditable?: boolean\n /** Config change handler */\n onConfigChange?: (config: DashboardConfig) => void\n /** Save handler */\n onSave?: (config: DashboardConfig) => Promise<void> | void\n /** Grid width for row calculations */\n gridWidth?: number\n /** Portlet component refs for refresh functionality */\n portletComponentRefs?: React.MutableRefObject<Record<string, { refresh: () => void } | null>>\n /** Portlet refresh handler (external) */\n onPortletRefresh?: (portletId: string) => void\n}\n\nexport interface UseDashboardResult {\n // =========================================================================\n // Store State\n // =========================================================================\n /** Whether dashboard is in edit mode */\n isEditMode: boolean\n /** Selected filter ID for filter assignment mode */\n selectedFilterId: string | null\n /** Whether portlet modal is open */\n isPortletModalOpen: boolean\n /** Portlet being edited */\n editingPortlet: PortletConfig | null\n /** Whether filter config modal is open */\n isFilterConfigModalOpen: boolean\n /** Portlet for filter configuration */\n filterConfigPortlet: PortletConfig | null\n /** Portlet ID pending delete confirmation */\n deleteConfirmPortletId: string | null\n /** Draft rows during drag operations */\n draftRows: RowLayout[] | null\n /** Whether a portlet is being dragged */\n isDraggingPortlet: boolean\n /** Last known layout for change detection */\n lastKnownLayout: LayoutItem[]\n /** Whether component is initialized */\n isInitialized: boolean\n /** Debug data per portlet */\n debugData: Record<string, PortletDebugDataEntry>\n\n // =========================================================================\n // Computed Values\n // =========================================================================\n /** Whether editing is allowed (editable && isEditMode && desktop && !filterMode) */\n canEdit: boolean\n /** Whether layout mode can be changed */\n canChangeLayoutMode: boolean\n /** Currently selected filter object */\n selectedFilter: DashboardFilter | null\n /** Resolved rows for row-based layout */\n resolvedRows: RowLayout[]\n /** Current layout mode */\n layoutMode: DashboardLayoutMode\n /** Allowed layout modes */\n allowedModes: DashboardLayoutMode[]\n\n // =========================================================================\n // Actions\n // =========================================================================\n actions: UseDashboardActions\n}\n\nexport interface UseDashboardActions {\n // Edit Mode\n enterEditMode: () => void\n exitEditMode: () => void\n toggleEditMode: () => void\n selectFilter: (filterId: string | null) => void\n exitFilterSelectionMode: () => void\n\n // Modals\n openAddPortlet: () => void\n openEditPortlet: (portlet: PortletConfig) => void\n closePortletModal: () => void\n openFilterConfig: (portlet: PortletConfig) => void\n closeFilterConfig: () => void\n\n // Layout State (store-only)\n setDraftRows: (rows: RowLayout[] | null) => void\n setIsDraggingPortlet: (isDragging: boolean) => void\n setLastKnownLayout: (layout: LayoutItem[]) => void\n setIsInitialized: (initialized: boolean) => void\n setDragState: (state: { rowIndex: number; colIndex: number; portletId: string } | null) => void\n clearDragState: () => void\n\n // Layout Operations (config-modifying)\n hasLayoutActuallyChanged: (newLayout: LayoutItem[]) => boolean\n updateRowLayout: (rows: RowLayout[], save?: boolean, portletsOverride?: PortletConfig[]) => Promise<void>\n handleLayoutModeChange: (mode: DashboardLayoutMode) => Promise<void>\n\n // Portlet Operations\n savePortlet: (portletData: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'>) => Promise<string | null>\n deletePortlet: (portletId: string) => Promise<void>\n duplicatePortlet: (portletId: string) => Promise<string | undefined>\n refreshPortlet: (portletId: string) => void\n\n // Filter Operations\n toggleFilterForPortlet: (portletId: string, filterId: string) => Promise<void>\n selectAllForFilter: (filterId: string) => Promise<void>\n saveFilterConfig: (mapping: string[]) => Promise<void>\n\n // Config Operations\n handlePaletteChange: (paletteName: string) => Promise<void>\n\n // Delete Confirmation\n openDeleteConfirm: (portletId: string) => void\n closeDeleteConfirm: () => void\n confirmDelete: () => Promise<void>\n\n // Debug\n setDebugData: (portletId: string, data: PortletDebugDataEntry) => void\n clearDebugData: (portletId?: string) => void\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nconst createRowId = () => `row-${Date.now()}`\n\nconst equalizeRowColumns = (\n portletIds: string[],\n gridSettings: DashboardGridSettings\n): RowLayoutColumn[] => {\n const count = portletIds.length\n if (count === 0) return []\n\n const { cols, minW } = gridSettings\n const minTotal = minW * count\n\n if (minTotal > cols) {\n const base = Math.floor(cols / count)\n const remainder = cols % count\n return portletIds.map((id, index) => ({\n portletId: id,\n w: base + (index < remainder ? 1 : 0),\n }))\n }\n\n const remaining = cols - minTotal\n const extra = Math.floor(remaining / count)\n const remainder = remaining % count\n\n return portletIds.map((id, index) => ({\n portletId: id,\n w: minW + extra + (index < remainder ? 1 : 0),\n }))\n}\n\nconst adjustRowWidths = (\n columns: RowLayoutColumn[],\n gridSettings: DashboardGridSettings\n): RowLayoutColumn[] => {\n if (columns.length === 0) return []\n\n const { cols, minW } = gridSettings\n const adjusted = columns.map((column) => ({\n ...column,\n w: Math.max(minW, column.w),\n }))\n\n let total = adjusted.reduce((sum, column) => sum + column.w, 0)\n if (total === cols) return adjusted\n\n if (total < cols) {\n let remaining = cols - total\n let index = 0\n while (remaining > 0) {\n adjusted[index % adjusted.length].w += 1\n remaining -= 1\n index += 1\n }\n return adjusted\n }\n\n let overflow = total - cols\n for (let index = adjusted.length - 1; index >= 0 && overflow > 0; index -= 1) {\n const column = adjusted[index]\n const reducible = Math.max(0, column.w - minW)\n if (reducible === 0) continue\n const delta = Math.min(reducible, overflow)\n column.w -= delta\n overflow -= delta\n }\n\n return adjusted\n}\n\nconst convertPortletsToRows = (\n portlets: PortletConfig[],\n gridSettings: DashboardGridSettings\n): RowLayout[] => {\n if (portlets.length === 0) return []\n\n const sorted = [...portlets].sort((a, b) => {\n if (a.y !== b.y) return a.y - b.y\n return a.x - b.x\n })\n\n const rowsByY = new Map<number, PortletConfig[]>()\n sorted.forEach((portlet) => {\n const row = rowsByY.get(portlet.y) ?? []\n row.push(portlet)\n rowsByY.set(portlet.y, row)\n })\n\n return Array.from(rowsByY.entries())\n .sort(([a], [b]) => a - b)\n .map(([rowY, rowPortlets]) => {\n const rowHeight = Math.max(gridSettings.minH, ...rowPortlets.map((p) => p.h))\n const portletIds = rowPortlets.map((p) => p.id)\n return {\n id: `row-${rowY}`,\n h: rowHeight,\n columns: equalizeRowColumns(portletIds, gridSettings),\n }\n })\n}\n\nconst normalizeRows = (\n rows: RowLayout[],\n portlets: PortletConfig[],\n gridSettings: DashboardGridSettings\n): RowLayout[] => {\n const portletIds = new Set(portlets.map((p) => p.id))\n return rows\n .map((row) => ({\n ...row,\n h: Math.max(gridSettings.minH, row.h),\n columns: adjustRowWidths(\n row.columns.filter((col) => portletIds.has(col.portletId)),\n gridSettings\n ),\n }))\n .filter((row) => row.columns.length > 0)\n}\n\nconst convertRowsToPortlets = (\n rows: RowLayout[],\n portlets: PortletConfig[]\n): PortletConfig[] => {\n const portletMap = new Map(portlets.map((p) => [p.id, p]))\n let currentY = 0\n\n const updated: PortletConfig[] = []\n rows.forEach((row) => {\n let currentX = 0\n row.columns.forEach((column) => {\n const portlet = portletMap.get(column.portletId)\n if (!portlet) return\n updated.push({\n ...portlet,\n x: currentX,\n y: currentY,\n w: column.w,\n h: row.h,\n })\n currentX += column.w\n })\n currentY += row.h\n })\n\n const updatedIds = new Set(updated.map((p) => p.id))\n portlets.forEach((portlet) => {\n if (!updatedIds.has(portlet.id)) {\n updated.push(portlet)\n }\n })\n\n return updated\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\nconst selectStoreState = (state: DashboardStore) => ({\n isEditMode: state.isEditMode,\n selectedFilterId: state.selectedFilterId,\n isPortletModalOpen: state.isPortletModalOpen,\n editingPortlet: state.editingPortlet,\n isFilterConfigModalOpen: state.isFilterConfigModalOpen,\n filterConfigPortlet: state.filterConfigPortlet,\n deleteConfirmPortletId: state.deleteConfirmPortletId,\n draftRows: state.draftRows,\n isDraggingPortlet: state.isDraggingPortlet,\n lastKnownLayout: state.lastKnownLayout,\n isInitialized: state.isInitialized,\n debugData: state.debugData,\n})\n\nconst selectStoreActions = (state: DashboardStore) => ({\n setEditMode: state.setEditMode,\n toggleEditMode: state.toggleEditMode,\n setSelectedFilterId: state.setSelectedFilterId,\n exitFilterSelectionMode: state.exitFilterSelectionMode,\n openPortletModal: state.openPortletModal,\n closePortletModal: state.closePortletModal,\n openFilterConfigModal: state.openFilterConfigModal,\n closeFilterConfigModal: state.closeFilterConfigModal,\n openDeleteConfirm: state.openDeleteConfirm,\n closeDeleteConfirm: state.closeDeleteConfirm,\n setDraftRows: state.setDraftRows,\n setIsDraggingPortlet: state.setIsDraggingPortlet,\n setLastKnownLayout: state.setLastKnownLayout,\n setIsInitialized: state.setIsInitialized,\n setDragState: state.setDragState,\n clearDragState: state.clearDragState,\n setDebugData: state.setDebugData,\n clearDebugData: state.clearDebugData,\n})\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboard(options: UseDashboardOptions): UseDashboardResult {\n const {\n config,\n editable = false,\n dashboardFilters,\n gridSettings,\n allowedModes: propAllowedModes,\n isResponsiveEditable = true,\n onConfigChange,\n onSave,\n portletComponentRefs,\n onPortletRefresh,\n } = options\n\n // =========================================================================\n // Store Access\n // =========================================================================\n\n const storeState = useDashboardStore(useShallow(selectStoreState))\n const storeActions = useDashboardStore(useShallow(selectStoreActions))\n\n // Keep refs for draft rows (needed for mouse event handlers)\n const draftRowsRef = useRef<RowLayout[] | null>(null)\n draftRowsRef.current = storeState.draftRows\n\n // =========================================================================\n // Computed Values\n // =========================================================================\n\n const allowedModes: DashboardLayoutMode[] = useMemo(() => {\n return propAllowedModes && propAllowedModes.length > 0\n ? propAllowedModes\n : ['rows', 'grid']\n }, [propAllowedModes])\n\n const layoutMode: DashboardLayoutMode = useMemo(() => {\n const fallbackMode: DashboardLayoutMode = allowedModes.includes('rows')\n ? 'rows'\n : allowedModes[0] ?? 'grid'\n const configMode = config.layoutMode ?? 'grid'\n return allowedModes.includes(configMode) ? configMode : fallbackMode\n }, [config.layoutMode, allowedModes])\n\n const canEdit = useMemo(() => {\n return (\n editable &&\n storeState.isEditMode &&\n isResponsiveEditable &&\n !storeState.selectedFilterId\n )\n }, [editable, storeState.isEditMode, isResponsiveEditable, storeState.selectedFilterId])\n\n const canChangeLayoutMode = useMemo(() => {\n return (\n editable &&\n storeState.isEditMode &&\n isResponsiveEditable &&\n !storeState.selectedFilterId &&\n allowedModes.length > 1\n )\n }, [\n editable,\n storeState.isEditMode,\n isResponsiveEditable,\n storeState.selectedFilterId,\n allowedModes.length,\n ])\n\n const selectedFilter = useMemo(() => {\n if (!storeState.selectedFilterId || !dashboardFilters) return null\n return dashboardFilters.find((f) => f.id === storeState.selectedFilterId) ?? null\n }, [storeState.selectedFilterId, dashboardFilters])\n\n const resolvedRows = useMemo(() => {\n if (layoutMode !== 'rows') return []\n const baseRows =\n storeState.draftRows ??\n config.rows ??\n convertPortletsToRows(config.portlets, gridSettings)\n return normalizeRows(baseRows, config.portlets, gridSettings)\n }, [layoutMode, storeState.draftRows, config.rows, config.portlets, gridSettings])\n\n // =========================================================================\n // Actions\n // =========================================================================\n\n // Edit mode actions\n const enterEditMode = useCallback(() => {\n storeActions.setEditMode(true)\n }, [storeActions])\n\n const exitEditMode = useCallback(() => {\n storeActions.setEditMode(false)\n }, [storeActions])\n\n const toggleEditMode = useCallback(() => {\n if (isResponsiveEditable) {\n storeActions.toggleEditMode()\n }\n }, [isResponsiveEditable, storeActions])\n\n const selectFilter = useCallback(\n (filterId: string | null) => {\n // Toggle selection: if already selected, deselect\n storeActions.setSelectedFilterId(\n filterId === storeState.selectedFilterId ? null : filterId\n )\n },\n [storeActions, storeState.selectedFilterId]\n )\n\n // Modal actions\n const openAddPortlet = useCallback(() => {\n storeActions.openPortletModal(null)\n }, [storeActions])\n\n const openEditPortlet = useCallback(\n (portlet: PortletConfig) => {\n storeActions.openPortletModal(portlet)\n },\n [storeActions]\n )\n\n const openFilterConfig = useCallback(\n (portlet: PortletConfig) => {\n storeActions.openFilterConfigModal(portlet)\n },\n [storeActions]\n )\n\n // Layout change detection\n const hasLayoutActuallyChanged = useCallback(\n (newLayout: LayoutItem[]) => {\n if (!storeState.isInitialized || storeState.lastKnownLayout.length === 0) {\n return false\n }\n\n for (const newItem of newLayout) {\n const oldItem = storeState.lastKnownLayout.find((item) => item.i === newItem.i)\n if (!oldItem) continue\n\n if (\n oldItem.x !== newItem.x ||\n oldItem.y !== newItem.y ||\n oldItem.w !== newItem.w ||\n oldItem.h !== newItem.h\n ) {\n return true\n }\n }\n return false\n },\n [storeState.isInitialized, storeState.lastKnownLayout]\n )\n\n // Row layout update\n const updateRowLayout = useCallback(\n async (\n rows: RowLayout[],\n save = true,\n portletsOverride?: PortletConfig[]\n ) => {\n if (!onConfigChange) return\n\n const portlets = portletsOverride ?? config.portlets\n const normalizedRows = normalizeRows(rows, portlets, gridSettings)\n const updatedPortlets = convertRowsToPortlets(normalizedRows, portlets)\n const updatedConfig: DashboardConfig = {\n ...config,\n layoutMode: 'rows',\n rows: normalizedRows,\n portlets: updatedPortlets,\n }\n\n storeActions.setDraftRows(null)\n onConfigChange(updatedConfig)\n\n if (save && onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed after row layout change:', error)\n }\n }\n },\n [config, gridSettings, onConfigChange, onSave, storeActions]\n )\n\n // Layout mode change\n const handleLayoutModeChange = useCallback(\n async (mode: DashboardLayoutMode) => {\n if (\n !onConfigChange ||\n mode === layoutMode ||\n !canChangeLayoutMode ||\n !allowedModes.includes(mode)\n ) {\n return\n }\n\n const baseRows = normalizeRows(\n config.rows && config.rows.length > 0\n ? config.rows\n : convertPortletsToRows(config.portlets, gridSettings),\n config.portlets,\n gridSettings\n )\n\n const updatedPortlets = convertRowsToPortlets(baseRows, config.portlets)\n const updatedConfig: DashboardConfig = {\n ...config,\n layoutMode: mode,\n rows: baseRows,\n portlets: updatedPortlets,\n }\n\n storeActions.setDraftRows(null)\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed after layout mode switch:', error)\n }\n }\n },\n [\n allowedModes,\n canChangeLayoutMode,\n config,\n gridSettings,\n layoutMode,\n onConfigChange,\n onSave,\n storeActions,\n ]\n )\n\n // Portlet operations\n const savePortlet = useCallback(\n async (\n portletData: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'>\n ): Promise<string | null> => {\n if (!onConfigChange) return null\n\n let updatedPortlets = [...config.portlets]\n let isNewPortlet = false\n let newPortletId: string | null = null\n\n if (storeState.editingPortlet) {\n // Editing existing portlet\n const index = updatedPortlets.findIndex(\n (p) => p.id === storeState.editingPortlet!.id\n )\n if (index !== -1) {\n updatedPortlets[index] = portletData as PortletConfig\n }\n } else {\n // Adding new portlet\n isNewPortlet = true\n const newPortlet: PortletConfig = {\n ...portletData,\n id: `portlet-${Date.now()}`,\n x: 0,\n y: 0,\n } as PortletConfig\n\n newPortletId = newPortlet.id\n\n // Find best position for new portlet\n let maxY = 0\n config.portlets.forEach((p) => {\n if (p.y + p.h > maxY) {\n maxY = p.y + p.h\n }\n })\n newPortlet.y = maxY\n\n updatedPortlets.push(newPortlet)\n }\n\n if (layoutMode === 'rows') {\n const baseRows =\n resolvedRows.length > 0\n ? resolvedRows.map((row) => ({\n ...row,\n columns: row.columns.map((col) => ({ ...col })),\n }))\n : normalizeRows(\n config.rows ?? convertPortletsToRows(config.portlets, gridSettings),\n updatedPortlets,\n gridSettings\n )\n\n const nextRows =\n isNewPortlet && newPortletId\n ? [\n ...baseRows,\n {\n id: createRowId(),\n h: Math.max(gridSettings.minH, 5),\n columns: equalizeRowColumns([newPortletId], gridSettings),\n },\n ]\n : baseRows\n\n await updateRowLayout(nextRows, true, updatedPortlets)\n } else {\n const updatedConfig: DashboardConfig = {\n ...config,\n portlets: updatedPortlets,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n }\n\n storeActions.closePortletModal()\n return newPortletId\n },\n [\n config,\n gridSettings,\n layoutMode,\n onConfigChange,\n onSave,\n resolvedRows,\n storeActions,\n storeState.editingPortlet,\n updateRowLayout,\n ]\n )\n\n // Internal delete logic (called after confirmation)\n const executeDeletePortlet = useCallback(\n async (portletId: string) => {\n if (!onConfigChange) return\n\n const updatedPortlets = config.portlets.filter((p) => p.id !== portletId)\n\n if (layoutMode === 'rows') {\n const nextRows = resolvedRows\n .map((row) => ({\n ...row,\n columns: row.columns.filter((col) => col.portletId !== portletId),\n }))\n .filter((row) => row.columns.length > 0)\n .map((row) => ({\n ...row,\n columns: equalizeRowColumns(\n row.columns.map((col) => col.portletId),\n gridSettings\n ),\n }))\n\n await updateRowLayout(nextRows, true, updatedPortlets)\n } else {\n const updatedConfig: DashboardConfig = {\n ...config,\n portlets: updatedPortlets,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n }\n },\n [config, gridSettings, layoutMode, onConfigChange, onSave, resolvedRows, updateRowLayout]\n )\n\n // Public delete action - opens confirmation modal\n const deletePortlet = useCallback(\n async (portletId: string) => {\n storeActions.openDeleteConfirm(portletId)\n },\n [storeActions]\n )\n\n // Confirm delete action - called when user confirms in modal\n const confirmDelete = useCallback(async () => {\n const portletId = storeState.deleteConfirmPortletId\n if (!portletId) return\n\n await executeDeletePortlet(portletId)\n storeActions.closeDeleteConfirm()\n }, [executeDeletePortlet, storeState.deleteConfirmPortletId, storeActions])\n\n const duplicatePortlet = useCallback(\n async (portletId: string): Promise<string | undefined> => {\n if (!onConfigChange) return undefined\n\n const originalPortlet = config.portlets.find((p) => p.id === portletId)\n if (!originalPortlet) return undefined\n\n const duplicatedPortlet: PortletConfig = {\n ...originalPortlet,\n id: `portlet-${Date.now()}`,\n title: `${originalPortlet.title} Duplicated`,\n x: 0,\n y: 0,\n }\n\n let maxY = 0\n config.portlets.forEach((p) => {\n if (p.y + p.h > maxY) {\n maxY = p.y + p.h\n }\n })\n duplicatedPortlet.y = maxY\n\n const updatedPortlets = [...config.portlets, duplicatedPortlet]\n\n if (layoutMode === 'rows') {\n const baseRows = resolvedRows.map((row) => ({\n ...row,\n columns: row.columns.map((col) => ({ ...col })),\n }))\n const nextRows = [\n ...baseRows,\n {\n id: createRowId(),\n h: Math.max(gridSettings.minH, 5),\n columns: equalizeRowColumns([duplicatedPortlet.id], gridSettings),\n },\n ]\n await updateRowLayout(nextRows, true, updatedPortlets)\n } else {\n const updatedConfig: DashboardConfig = {\n ...config,\n portlets: updatedPortlets,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n }\n\n return duplicatedPortlet.id\n },\n [config, gridSettings, layoutMode, onConfigChange, onSave, resolvedRows, updateRowLayout]\n )\n\n const refreshPortlet = useCallback(\n (portletId: string) => {\n const portletComponent = portletComponentRefs?.current?.[portletId]\n if (portletComponent?.refresh) {\n portletComponent.refresh()\n }\n onPortletRefresh?.(portletId)\n },\n [portletComponentRefs, onPortletRefresh]\n )\n\n // Filter operations\n const toggleFilterForPortlet = useCallback(\n async (portletId: string, filterId: string) => {\n if (!onConfigChange) return\n\n const updatedPortlets = config.portlets.map((p) => {\n if (p.id === portletId) {\n const currentMapping = p.dashboardFilterMapping || []\n const hasFilter = currentMapping.includes(filterId)\n\n return {\n ...p,\n dashboardFilterMapping: hasFilter\n ? currentMapping.filter((id) => id !== filterId)\n : [...currentMapping, filterId],\n }\n }\n return p\n })\n\n const updatedConfig: DashboardConfig = {\n ...config,\n portlets: updatedPortlets,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n },\n [config, onConfigChange, onSave]\n )\n\n const selectAllForFilter = useCallback(\n async (filterId: string) => {\n if (!onConfigChange) return\n\n const updatedPortlets = config.portlets.map((p) => {\n const currentMapping = p.dashboardFilterMapping || []\n if (!currentMapping.includes(filterId)) {\n return {\n ...p,\n dashboardFilterMapping: [...currentMapping, filterId],\n }\n }\n return p\n })\n\n const updatedConfig: DashboardConfig = {\n ...config,\n portlets: updatedPortlets,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n },\n [config, onConfigChange, onSave]\n )\n\n const saveFilterConfig = useCallback(\n async (mapping: string[]) => {\n if (!onConfigChange || !storeState.filterConfigPortlet) return\n\n const updatedPortlets = config.portlets.map((p) => {\n if (p.id === storeState.filterConfigPortlet!.id) {\n return {\n ...p,\n dashboardFilterMapping: mapping,\n }\n }\n return p\n })\n\n const updatedConfig: DashboardConfig = {\n ...config,\n portlets: updatedPortlets,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n },\n [config, onConfigChange, onSave, storeState.filterConfigPortlet]\n )\n\n // Config operations\n const handlePaletteChange = useCallback(\n async (paletteName: string) => {\n if (!onConfigChange) return\n\n const updatedConfig: DashboardConfig = {\n ...config,\n colorPalette: paletteName,\n }\n\n onConfigChange(updatedConfig)\n\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed:', error)\n }\n }\n },\n [config, onConfigChange, onSave]\n )\n\n // =========================================================================\n // Assemble Result\n // =========================================================================\n\n const actions: UseDashboardActions = useMemo(\n () => ({\n // Edit mode\n enterEditMode,\n exitEditMode,\n toggleEditMode,\n selectFilter,\n exitFilterSelectionMode: storeActions.exitFilterSelectionMode,\n\n // Modals\n openAddPortlet,\n openEditPortlet,\n closePortletModal: storeActions.closePortletModal,\n openFilterConfig,\n closeFilterConfig: storeActions.closeFilterConfigModal,\n\n // Layout state\n setDraftRows: storeActions.setDraftRows,\n setIsDraggingPortlet: storeActions.setIsDraggingPortlet,\n setLastKnownLayout: storeActions.setLastKnownLayout,\n setIsInitialized: storeActions.setIsInitialized,\n setDragState: storeActions.setDragState,\n clearDragState: storeActions.clearDragState,\n\n // Layout operations\n hasLayoutActuallyChanged,\n updateRowLayout,\n handleLayoutModeChange,\n\n // Portlet operations\n savePortlet,\n deletePortlet,\n duplicatePortlet,\n refreshPortlet,\n\n // Filter operations\n toggleFilterForPortlet,\n selectAllForFilter,\n saveFilterConfig,\n\n // Config operations\n handlePaletteChange,\n\n // Delete confirmation\n openDeleteConfirm: storeActions.openDeleteConfirm,\n closeDeleteConfirm: storeActions.closeDeleteConfirm,\n confirmDelete,\n\n // Debug\n setDebugData: storeActions.setDebugData,\n clearDebugData: storeActions.clearDebugData,\n }),\n [\n enterEditMode,\n exitEditMode,\n toggleEditMode,\n selectFilter,\n storeActions,\n openAddPortlet,\n openEditPortlet,\n openFilterConfig,\n hasLayoutActuallyChanged,\n updateRowLayout,\n handleLayoutModeChange,\n savePortlet,\n deletePortlet,\n duplicatePortlet,\n refreshPortlet,\n toggleFilterForPortlet,\n selectAllForFilter,\n saveFilterConfig,\n handlePaletteChange,\n confirmDelete,\n ]\n )\n\n return {\n // Store state\n ...storeState,\n\n // Computed values\n canEdit,\n canChangeLayoutMode,\n selectedFilter,\n resolvedRows,\n layoutMode,\n allowedModes,\n\n // Actions\n actions,\n }\n}\n","/**\n * Dashboard Grid Component\n * Uses react-grid-layout for responsive grid layout\n * Simplified version without app-specific dependencies\n */\n\nimport {\n useCallback,\n useRef,\n useState,\n useEffect,\n useMemo,\n type ReactNode,\n type HTMLAttributes,\n type DragEvent,\n type MouseEvent,\n type Ref\n} from 'react'\nimport ReactGridLayout, { verticalCompactor, type LayoutItem, type Layout } from 'react-grid-layout'\nimport { getIcon } from '../icons'\nimport { useScrollDetection } from '../hooks/useScrollDetection'\nimport { useElementVisibility } from '../hooks/useElementVisibility'\nimport DashboardPortletCard from './DashboardPortletCard'\nimport RowManagedLayout from './RowManagedLayout'\nimport FloatingEditToolbar from './FloatingEditToolbar'\n\nconst ChartBarIcon = getIcon('measure')\nconst RefreshIcon = getIcon('refresh')\nconst EditIcon = getIcon('edit')\nconst CheckIcon = getIcon('check')\nconst DeleteIcon = getIcon('delete')\nconst AddIcon = getIcon('add')\nconst CopyIcon = getIcon('copy')\nconst FilterIcon = getIcon('filter')\nconst DesktopIcon = getIcon('desktop')\nconst GridIcon = getIcon('segment')\nconst RowsIcon = getIcon('table')\nimport PortletAnalysisModal from './PortletAnalysisModal'\nimport PortletFilterConfigModal from './PortletFilterConfigModal'\nimport ConfirmModal from './ConfirmModal'\nimport { useCubeFeatures } from '../providers/CubeProvider'\nimport ColorPaletteSelector from './ColorPaletteSelector'\nimport DashboardFilterPanel from './DashboardFilterPanel'\nimport ScaledGridWrapper from './ScaledGridWrapper'\nimport MobileStackedLayout from './MobileStackedLayout'\nimport { useResponsiveDashboard } from '../hooks/useResponsiveDashboard'\nimport { ScrollContainerProvider } from '../providers/ScrollContainerContext'\nimport { useDashboard } from '../hooks/useDashboardHook'\nimport type { ColorPalette } from '../utils/colorPalettes'\n\n/**\n * Finds the nearest scrollable ancestor of an element.\n * Used to detect scroll container for lazy loading IntersectionObserver.\n */\nfunction findScrollableAncestor(element: HTMLElement | null): HTMLElement | null {\n if (!element) return null\n\n let current = element.parentElement\n\n while (current) {\n const style = window.getComputedStyle(current)\n const overflowY = style.overflowY\n const overflowX = style.overflowX\n\n const hasScrollableOverflow =\n overflowY === 'auto' || overflowY === 'scroll' ||\n overflowX === 'auto' || overflowX === 'scroll'\n\n const hasScrollContent =\n current.scrollHeight > current.clientHeight ||\n current.scrollWidth > current.clientWidth\n\n if (hasScrollableOverflow && hasScrollContent) {\n return current\n }\n\n if (current === document.body) break\n current = current.parentElement\n }\n\n return null // Use viewport\n}\nimport type {\n DashboardConfig,\n PortletConfig,\n DashboardFilter,\n CubeMeta,\n DashboardLayoutMode,\n DashboardGridSettings,\n RowLayout,\n RowLayoutColumn\n} from '../types'\n\n// CSS for react-grid-layout should be imported by the consuming app\n// import 'react-grid-layout/css/styles.css'\n\ninterface DashboardGridProps {\n config: DashboardConfig\n editable?: boolean\n dashboardFilters?: DashboardFilter[] // Dashboard-level filters to apply to portlets\n loadingComponent?: ReactNode // Custom loading indicator for all portlets\n onConfigChange?: (config: DashboardConfig) => void\n onPortletRefresh?: (portletId: string) => void\n onSave?: (config: DashboardConfig) => Promise<void> | void\n colorPalette?: ColorPalette // Complete palette with both colors and gradient\n schema?: CubeMeta | null // Cube metadata for filter panel\n onDashboardFiltersChange?: (filters: DashboardFilter[]) => void // Handler for filter changes\n dashboardModes?: DashboardLayoutMode[]\n}\n\nconst DEFAULT_GRID_SETTINGS: DashboardGridSettings = {\n cols: 12,\n rowHeight: 80,\n minW: 2,\n minH: 2\n}\n\nconst createRowId = () => `row-${Date.now()}`\n\nconst getGridSettings = (config: DashboardConfig): DashboardGridSettings => ({\n cols: config.grid?.cols ?? DEFAULT_GRID_SETTINGS.cols,\n rowHeight: config.grid?.rowHeight ?? DEFAULT_GRID_SETTINGS.rowHeight,\n minW: config.grid?.minW ?? DEFAULT_GRID_SETTINGS.minW,\n minH: config.grid?.minH ?? DEFAULT_GRID_SETTINGS.minH\n})\n\nconst equalizeRowColumns = (\n portletIds: string[],\n gridSettings: DashboardGridSettings\n): RowLayoutColumn[] => {\n const count = portletIds.length\n if (count === 0) return []\n\n const { cols, minW } = gridSettings\n const minTotal = minW * count\n\n if (minTotal > cols) {\n const base = Math.floor(cols / count)\n const remainder = cols % count\n return portletIds.map((id, index) => ({\n portletId: id,\n w: base + (index < remainder ? 1 : 0)\n }))\n }\n\n const remaining = cols - minTotal\n const extra = Math.floor(remaining / count)\n const remainder = remaining % count\n\n return portletIds.map((id, index) => ({\n portletId: id,\n w: minW + extra + (index < remainder ? 1 : 0)\n }))\n}\n\nconst adjustRowWidths = (\n columns: RowLayoutColumn[],\n gridSettings: DashboardGridSettings\n): RowLayoutColumn[] => {\n if (columns.length === 0) return []\n\n const { cols, minW } = gridSettings\n const adjusted = columns.map(column => ({\n ...column,\n w: Math.max(minW, column.w)\n }))\n\n let total = adjusted.reduce((sum, column) => sum + column.w, 0)\n if (total === cols) return adjusted\n\n if (total < cols) {\n let remaining = cols - total\n let index = 0\n while (remaining > 0) {\n adjusted[index % adjusted.length].w += 1\n remaining -= 1\n index += 1\n }\n return adjusted\n }\n\n let overflow = total - cols\n for (let index = adjusted.length - 1; index >= 0 && overflow > 0; index -= 1) {\n const column = adjusted[index]\n const reducible = Math.max(0, column.w - minW)\n if (reducible === 0) continue\n const delta = Math.min(reducible, overflow)\n column.w -= delta\n overflow -= delta\n }\n\n return adjusted\n}\n\n// Helper functions moved to useDashboardHook.ts:\n// - convertPortletsToRows\n// - normalizeRows\n// - convertRowsToPortlets\n\nexport default function DashboardGrid({\n config,\n editable = false,\n dashboardFilters,\n loadingComponent,\n onConfigChange,\n onPortletRefresh,\n onSave,\n colorPalette,\n schema,\n onDashboardFiltersChange,\n dashboardModes\n}: DashboardGridProps) {\n // Get features from context for conditional modal rendering\n const { features } = useCubeFeatures()\n\n // Responsive dashboard hook for three-tier layout strategy\n const {\n containerRef,\n containerWidth,\n displayMode,\n scaleFactor,\n isEditable: isResponsiveEditable,\n designWidth\n } = useResponsiveDashboard()\n\n // allowedModes is passed to useDashboard hook which computes layoutMode\n const allowedModes: DashboardLayoutMode[] = dashboardModes && dashboardModes.length > 0\n ? dashboardModes\n : ['rows', 'grid']\n const gridSettings = useMemo(() => getGridSettings(config), [config])\n\n // Scroll container detection for lazy loading\n // Null = viewport, element = scrolling container\n // Detection happens once in the ref callback to avoid double state updates\n const [scrollContainer, setScrollContainer] = useState<HTMLElement | null>(null)\n const containerElementRef = useRef<HTMLDivElement | null>(null)\n const scrollContainerRef = useRef<HTMLElement | null>(null)\n const editBarRef = useRef<HTMLDivElement | null>(null)\n\n // Combined ref for container\n const combinedContainerRef = useCallback((node: HTMLDivElement | null) => {\n containerElementRef.current = node\n containerRef(node)\n if (node) {\n const foundScrollContainer = findScrollableAncestor(node)\n setScrollContainer(foundScrollContainer)\n scrollContainerRef.current = foundScrollContainer\n }\n }, [containerRef])\n\n // Calculate grid width based on display mode\n // Desktop: use actual container width (allows wider than 1200px)\n // Scaled: use design width (1200px) and apply CSS scaling\n const gridWidth = displayMode === 'desktop' ? containerWidth : designWidth\n\n // Refs to store portlet refs for refresh functionality (kept local - DOM-specific)\n const portletRefs = useRef<{ [key: string]: HTMLDivElement | null }>({})\n const portletComponentRefs = useRef<{ [key: string]: { refresh: () => void } | null }>({})\n const draftRowsRef = useRef<RowLayout[] | null>(null)\n const dragStateRef = useRef<{ rowIndex: number; colIndex: number; portletId: string } | null>(null)\n\n // =========================================================================\n // Dashboard State from Zustand Store via useDashboard hook\n // Replaces 11 useState calls and provides computed values + actions\n // =========================================================================\n const dashboard = useDashboard({\n config,\n editable,\n dashboardFilters,\n gridSettings,\n allowedModes,\n isResponsiveEditable,\n onConfigChange,\n onSave,\n gridWidth,\n portletComponentRefs,\n onPortletRefresh,\n })\n\n // Destructure for easier access (maintains existing variable names)\n // Note: lastKnownLayout is managed internally by the hook and accessed via actions\n const {\n isEditMode,\n selectedFilterId,\n isPortletModalOpen,\n editingPortlet,\n isFilterConfigModalOpen,\n filterConfigPortlet,\n deleteConfirmPortletId,\n draftRows,\n isDraggingPortlet,\n isInitialized,\n // debugData removed - now read from store directly in DashboardPortletCard\n canEdit,\n canChangeLayoutMode,\n selectedFilter,\n resolvedRows,\n layoutMode,\n actions,\n } = dashboard\n\n // Sync draftRowsRef with store state (for mouse event handlers)\n useEffect(() => {\n draftRowsRef.current = draftRows\n }, [draftRows])\n\n // Exit filter selection mode when leaving edit mode or when switching to non-desktop mode\n useEffect(() => {\n if ((!isEditMode || !isResponsiveEditable) && selectedFilterId) {\n actions.exitFilterSelectionMode()\n }\n }, [isEditMode, isResponsiveEditable, selectedFilterId, actions])\n\n // Exit edit mode when switching to non-desktop view\n useEffect(() => {\n if (!isResponsiveEditable && isEditMode) {\n actions.exitEditMode()\n }\n }, [isResponsiveEditable, isEditMode, actions])\n\n // Track scroll state for sticky header using debounced scroll detection\n // Uses the actual scroll container (found via findScrollableAncestor) instead of window\n const isScrolled = useScrollDetection(scrollContainerRef, {\n threshold: 20,\n debounceMs: 150,\n container: scrollContainer // State dependency to trigger re-init when container found\n })\n\n // Track edit bar visibility for floating toolbar\n // When edit bar scrolls out of view, show floating toolbar\n const isEditBarVisible = useElementVisibility(editBarRef, {\n threshold: 80,\n debounceMs: 100,\n containerRef: scrollContainerRef,\n container: scrollContainer // State dependency to trigger re-init when container found\n })\n\n // Set up initialization tracking\n useEffect(() => {\n // Mark as initialized after first render to prevent saves during load/resize\n const timer = setTimeout(() => {\n actions.setIsInitialized(true)\n // Store initial layout for comparison\n const initialLayout = config.portlets.map(portlet => ({\n i: portlet.id,\n x: portlet.x,\n y: portlet.y,\n w: portlet.w,\n h: portlet.h\n }))\n actions.setLastKnownLayout(initialLayout)\n }, 200) // Slightly longer delay to ensure responsive grid is fully settled\n\n return () => clearTimeout(timer)\n }, [config.portlets, actions])\n\n // Scroll detection now handled by useScrollDetection hook above (lines 373-378)\n // This eliminates the old window.addEventListener('scroll') listener that was\n // listening to the wrong element and causing performance issues\n\n // Set up ESC key listener for filter selection mode\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && selectedFilterId) {\n actions.exitFilterSelectionMode()\n }\n }\n\n window.addEventListener('keydown', handleKeyDown)\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown)\n }\n }, [selectedFilterId, actions])\n\n const handleLayoutChange = useCallback((_layout: Layout) => {\n // This function is called for ALL layout changes\n // We should NOT save here - only update internal state if needed\n // Actual saving only happens in handleDragStop and handleResizeStop for explicit user actions\n\n // Note: We don't call onConfigChange here to prevent saving intermediate layout changes\n // The layout changes are handled by react-grid-layout internally\n }, []) // No dependencies since we're not doing anything\n\n // Handle drag stop - save when user finishes dragging (only if layout actually changed)\n const handleDragStop = useCallback(async (layout: Layout, _oldItem: LayoutItem | null, _newItem: LayoutItem | null, _placeholder: LayoutItem | null, _e: Event, _element: HTMLElement | undefined) => {\n if (!editable || !isEditMode || !onSave || !isInitialized) return\n\n // Only save if the layout actually changed from user interaction\n // Convert readonly Layout to mutable array for comparison\n const mutableLayout = [...layout]\n if (!actions.hasLayoutActuallyChanged(mutableLayout)) {\n return // No actual change, don't save\n }\n\n // Get the current updated config (only called in desktop mode)\n const updatedPortlets = config.portlets.map(portlet => {\n const layoutItem = mutableLayout.find(item => item.i === portlet.id)\n if (layoutItem) {\n return {\n ...portlet,\n x: layoutItem.x,\n y: layoutItem.y,\n w: layoutItem.w,\n h: layoutItem.h\n }\n }\n return portlet\n })\n\n // Preserve existing responsive layouts, only update with new lg layout\n const updatedConfig = {\n ...config,\n portlets: updatedPortlets,\n layouts: {\n ...config.layouts,\n lg: mutableLayout // Only save the large layout, let RGL handle responsive adjustments\n }\n }\n\n // Update our tracking of the last known layout\n actions.setLastKnownLayout(mutableLayout)\n\n // Update config state first\n onConfigChange?.(updatedConfig)\n\n // Auto-save after drag operation\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed after drag:', error)\n }\n }, [config, editable, isEditMode, onConfigChange, onSave, isInitialized, actions])\n\n // Handle resize stop - update config and save (resize is user interaction)\n const handleResizeStop = useCallback(async (layout: Layout, _oldItem: LayoutItem | null, _newItem: LayoutItem | null, _placeholder: LayoutItem | null, _e: Event, _element: HTMLElement | undefined) => {\n if (!editable || !isEditMode || !onConfigChange || !isInitialized) return\n\n // Only proceed if the layout actually changed from user interaction\n // Convert readonly Layout to mutable array for comparison\n const mutableLayout = [...layout]\n if (!actions.hasLayoutActuallyChanged(mutableLayout)) {\n return // No actual change, don't save\n }\n\n // Get the current updated config (only called in desktop mode)\n const updatedPortlets = config.portlets.map(portlet => {\n const layoutItem = mutableLayout.find(item => item.i === portlet.id)\n if (layoutItem) {\n return {\n ...portlet,\n x: layoutItem.x,\n y: layoutItem.y,\n w: layoutItem.w,\n h: layoutItem.h\n }\n }\n return portlet\n })\n\n // Preserve existing responsive layouts, only update with new lg layout\n const updatedConfig = {\n ...config,\n portlets: updatedPortlets,\n layouts: {\n ...config.layouts,\n lg: mutableLayout // Only save the large layout, let RGL handle responsive adjustments\n }\n }\n\n // Update our tracking of the last known layout\n actions.setLastKnownLayout(mutableLayout)\n\n // Update config state\n onConfigChange(updatedConfig)\n\n // Auto-save after resize operation (user deliberately resized)\n if (onSave) {\n try {\n await onSave(updatedConfig)\n } catch (error) {\n console.error('Auto-save failed after resize:', error)\n }\n }\n }, [config, editable, isEditMode, onConfigChange, onSave, isInitialized, actions])\n\n // handleLayoutModeChange now uses actions.handleLayoutModeChange from hook\n\n const startRowResize = useCallback((rowIndex: number, event: MouseEvent<HTMLDivElement>) => {\n if (!canEdit) return\n event.preventDefault()\n\n const startY = event.clientY\n const startRows = resolvedRows.map(row => ({\n ...row,\n columns: row.columns.map(column => ({ ...column }))\n }))\n\n const handleMouseMove = (moveEvent: globalThis.MouseEvent) => {\n const delta = moveEvent.clientY - startY\n const deltaUnits = Math.round(delta / gridSettings.rowHeight)\n const nextRows = startRows.map((row, index) => {\n if (index !== rowIndex) return row\n return {\n ...row,\n h: Math.max(gridSettings.minH, row.h + deltaUnits)\n }\n })\n actions.setDraftRows(nextRows)\n }\n\n const handleMouseUp = () => {\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n const finalRows = draftRowsRef.current ?? startRows\n actions.updateRowLayout(finalRows)\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n }, [canEdit, gridSettings, resolvedRows, actions])\n\n const startColumnResize = useCallback((rowIndex: number, columnIndex: number, event: MouseEvent<HTMLDivElement>) => {\n if (!canEdit) return\n event.preventDefault()\n\n const startX = event.clientX\n const startRows = resolvedRows.map(row => ({\n ...row,\n columns: row.columns.map(column => ({ ...column }))\n }))\n\n const row = startRows[rowIndex]\n const leftColumn = row?.columns[columnIndex]\n const rightColumn = row?.columns[columnIndex + 1]\n if (!row || !leftColumn || !rightColumn) return\n\n const columnGap = 16\n const rowContentWidth = gridWidth - (row.columns.length - 1) * columnGap\n const unitWidth = rowContentWidth / gridSettings.cols\n\n const handleMouseMove = (moveEvent: globalThis.MouseEvent) => {\n const delta = moveEvent.clientX - startX\n const deltaUnits = Math.round(delta / unitWidth)\n if (deltaUnits === 0) {\n actions.setDraftRows(startRows)\n return\n }\n\n let nextLeft = leftColumn.w + deltaUnits\n let nextRight = rightColumn.w - deltaUnits\n\n if (nextLeft < gridSettings.minW) {\n const diff = gridSettings.minW - nextLeft\n nextLeft = gridSettings.minW\n nextRight -= diff\n }\n\n if (nextRight < gridSettings.minW) {\n const diff = gridSettings.minW - nextRight\n nextRight = gridSettings.minW\n nextLeft -= diff\n }\n\n if (nextLeft < gridSettings.minW || nextRight < gridSettings.minW) return\n\n const nextRows = startRows.map((rowItem, index) => {\n if (index !== rowIndex) return rowItem\n const nextColumns = rowItem.columns.map((column, colIndex) => {\n if (colIndex === columnIndex) {\n return { ...column, w: nextLeft }\n }\n if (colIndex === columnIndex + 1) {\n return { ...column, w: nextRight }\n }\n return column\n })\n return {\n ...rowItem,\n columns: adjustRowWidths(nextColumns, gridSettings)\n }\n })\n actions.setDraftRows(nextRows)\n }\n\n const handleMouseUp = () => {\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n const finalRows = draftRowsRef.current ?? startRows\n actions.updateRowLayout(finalRows)\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n }, [canEdit, gridSettings, gridWidth, resolvedRows, actions])\n\n const handlePortletDragStart = useCallback((rowIndex: number, colIndex: number, portletId: string, event: DragEvent<HTMLDivElement>) => {\n if (!canEdit) return\n dragStateRef.current = { rowIndex, colIndex, portletId }\n actions.setIsDraggingPortlet(true)\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', portletId)\n }, [canEdit, actions])\n\n const handlePortletDragEnd = useCallback(() => {\n dragStateRef.current = null\n actions.setIsDraggingPortlet(false)\n }, [actions])\n\n const handleRowDrop = useCallback((rowIndex: number, insertIndex: number | null) => {\n const dragState = dragStateRef.current\n if (!dragState) return\n\n const nextRows = resolvedRows.map(row => ({\n ...row,\n columns: row.columns.map(column => ({ ...column }))\n }))\n\n const sourceRowIndex = dragState.rowIndex\n const sourceRow = nextRows[sourceRowIndex]\n if (!sourceRow) return\n\n const [movedColumn] = sourceRow.columns.splice(dragState.colIndex, 1)\n let sourceRowRemoved = false\n if (sourceRow.columns.length === 0) {\n nextRows.splice(sourceRowIndex, 1)\n sourceRowRemoved = true\n }\n\n let targetRowIndex = rowIndex\n if (sourceRowRemoved && sourceRowIndex < rowIndex) {\n targetRowIndex -= 1\n }\n\n const targetRow = nextRows[targetRowIndex]\n if (!targetRow) return\n\n let targetIndex = insertIndex ?? targetRow.columns.length\n if (!sourceRowRemoved && sourceRowIndex === targetRowIndex && insertIndex !== null) {\n if (insertIndex > dragState.colIndex) {\n targetIndex -= 1\n }\n }\n targetRow.columns.splice(targetIndex, 0, movedColumn)\n\n const movedBetweenRows = sourceRowIndex !== targetRowIndex || sourceRowRemoved\n if (movedBetweenRows) {\n if (!sourceRowRemoved) {\n nextRows[sourceRowIndex] = {\n ...nextRows[sourceRowIndex],\n columns: equalizeRowColumns(\n nextRows[sourceRowIndex].columns.map(column => column.portletId),\n gridSettings\n )\n }\n }\n nextRows[targetRowIndex] = {\n ...nextRows[targetRowIndex],\n columns: equalizeRowColumns(\n nextRows[targetRowIndex].columns.map(column => column.portletId),\n gridSettings\n )\n }\n }\n\n actions.updateRowLayout(nextRows)\n }, [gridSettings, resolvedRows, actions])\n\n const handleNewRowDrop = useCallback((insertIndex: number) => {\n const dragState = dragStateRef.current\n if (!dragState) return\n\n const nextRows = resolvedRows.map(row => ({\n ...row,\n columns: row.columns.map(column => ({ ...column }))\n }))\n\n const sourceRow = nextRows[dragState.rowIndex]\n if (!sourceRow) return\n\n const [movedColumn] = sourceRow.columns.splice(dragState.colIndex, 1)\n if (sourceRow.columns.length === 0) {\n nextRows.splice(dragState.rowIndex, 1)\n } else {\n sourceRow.columns = equalizeRowColumns(\n sourceRow.columns.map(column => column.portletId),\n gridSettings\n )\n }\n\n const newRow: RowLayout = {\n id: createRowId(),\n h: Math.max(gridSettings.minH, 5),\n columns: equalizeRowColumns([movedColumn.portletId], gridSettings)\n }\n nextRows.splice(insertIndex, 0, newRow)\n\n actions.updateRowLayout(nextRows)\n }, [gridSettings, resolvedRows, actions])\n\n // Handle portlet refresh - use action from hook\n const handlePortletRefresh = useCallback((portletId: string) => {\n actions.refreshPortlet(portletId)\n }, [actions])\n\n // Portlet CRUD operations - now use actions from useDashboard hook\n // The hook handles all logic including row layout updates, saving, and modal state\n\n // Handle portlet save with scroll-to-new behavior\n const handlePortletSave = useCallback(async (portletData: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'>) => {\n const newPortletId = await actions.savePortlet(portletData)\n actions.closePortletModal()\n\n // Scroll to the new portlet after DOM update\n if (newPortletId) {\n setTimeout(() => {\n const scrollToPortlet = () => {\n let portletElement: HTMLElement | null = portletRefs.current[newPortletId]\n if (!portletElement) {\n portletElement = document.querySelector(`[data-portlet-id=\"${newPortletId}\"]`)\n }\n\n if (portletElement) {\n portletElement.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'nearest'\n })\n return true\n }\n return false\n }\n\n // Try multiple times with increasing delays\n if (!scrollToPortlet()) {\n setTimeout(() => {\n if (!scrollToPortlet()) {\n setTimeout(() => {\n scrollToPortlet()\n }, 300)\n }\n }, 200)\n }\n }, 200)\n }\n }, [actions])\n\n // Handle deleting portlet - delegate to hook action\n const handleDeletePortlet = useCallback(async (portletId: string) => {\n await actions.deletePortlet(portletId)\n }, [actions])\n\n // Handle duplicating portlet - delegate to hook action with scroll to new portlet\n const handleDuplicatePortlet = useCallback(async (portletId: string) => {\n const newPortletId = await actions.duplicatePortlet(portletId)\n\n // Scroll to the duplicated portlet after DOM update\n if (newPortletId) {\n setTimeout(() => {\n const scrollToPortlet = () => {\n let portletElement: HTMLElement | null = portletRefs.current[newPortletId]\n if (!portletElement) {\n portletElement = document.querySelector(`[data-portlet-id=\"${newPortletId}\"]`)\n }\n\n if (portletElement) {\n portletElement.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'nearest'\n })\n return true\n }\n return false\n }\n\n // Try multiple times with increasing delays\n if (!scrollToPortlet()) {\n setTimeout(() => {\n if (!scrollToPortlet()) {\n setTimeout(() => {\n scrollToPortlet()\n }, 300)\n }\n }, 200)\n }\n }, 200)\n }\n }, [actions])\n\n // Handle adding new portlet - delegate to hook action\n const handleAddPortlet = useCallback(() => {\n actions.openAddPortlet()\n }, [actions])\n\n // Handle editing existing portlet - delegate to hook action\n const handleEditPortlet = useCallback((portlet: PortletConfig) => {\n actions.openEditPortlet(portlet)\n }, [actions])\n\n // Handle palette change - delegate to hook action\n const handlePaletteChange = useCallback(async (paletteName: string) => {\n await actions.handlePaletteChange(paletteName)\n }, [actions])\n\n // Handle opening filter config modal - delegate to hook action\n const handleOpenFilterConfig = useCallback((portlet: PortletConfig) => {\n actions.openFilterConfig(portlet)\n }, [actions])\n\n // Handle saving filter configuration - delegate to hook action\n const handleSaveFilterConfig = useCallback(async (mapping: string[]) => {\n await actions.saveFilterConfig(mapping)\n }, [actions])\n\n // Memoized ref callbacks for DashboardPortletCard\n const handleSetPortletRef = useCallback((portletId: string, element: HTMLDivElement | null) => {\n portletRefs.current[portletId] = element\n }, [])\n\n const handleSetPortletComponentRef = useCallback((portletId: string, element: { refresh: () => void } | null) => {\n portletComponentRefs.current[portletId] = element\n }, [])\n\n // Memoized icons object to prevent re-renders\n const portletIcons = useMemo(() => ({\n RefreshIcon, EditIcon, DeleteIcon, CopyIcon, FilterIcon\n }), [])\n\n // Handle toggling filter for a portlet - delegate to hook action\n const handleToggleFilterForPortlet = useCallback(async (portletId: string, filterId: string) => {\n await actions.toggleFilterForPortlet(portletId, filterId)\n }, [actions])\n\n // Handle filter selection (click on filter chip) - delegate to hook action\n const handleFilterSelect = useCallback((filterId: string) => {\n actions.selectFilter(filterId)\n }, [actions])\n\n // Handle select all - delegate to hook action\n const handleSelectAllForFilter = useCallback(async (filterId: string) => {\n await actions.selectAllForFilter(filterId)\n }, [actions])\n\n // selectedFilter is now computed by the hook\n\n // Memoized callbacks object for DashboardPortletCard\n // This groups action callbacks into a stable object to reduce prop drilling\n const portletCallbacks = useMemo(() => ({\n onToggleFilter: handleToggleFilterForPortlet,\n onRefresh: handlePortletRefresh,\n onDuplicate: handleDuplicatePortlet,\n onEdit: handleEditPortlet,\n onDelete: handleDeletePortlet,\n onOpenFilterConfig: handleOpenFilterConfig,\n }), [\n handleToggleFilterForPortlet,\n handlePortletRefresh,\n handleDuplicatePortlet,\n handleEditPortlet,\n handleDeletePortlet,\n handleOpenFilterConfig,\n ])\n\n // Memoize renderPortletCard to prevent unnecessary re-renders of DashboardPortletCard\n // IMPORTANT: Must be defined before any early returns to follow Rules of Hooks\n // State props (isEditMode, selectedFilterId, debugData) now read from store in component\n const renderPortletCard = useCallback((\n portlet: PortletConfig,\n containerProps?: HTMLAttributes<HTMLDivElement>,\n headerProps?: HTMLAttributes<HTMLDivElement>\n ) => (\n <DashboardPortletCard\n portlet={portlet}\n editable={editable}\n dashboardFilters={dashboardFilters}\n configEagerLoad={config.eagerLoad}\n loadingComponent={loadingComponent}\n colorPalette={colorPalette}\n containerProps={containerProps}\n headerProps={headerProps}\n callbacks={portletCallbacks}\n setPortletRef={handleSetPortletRef}\n setPortletComponentRef={handleSetPortletComponentRef}\n icons={portletIcons}\n />\n ), [\n editable,\n dashboardFilters,\n config.eagerLoad,\n loadingComponent,\n colorPalette,\n portletCallbacks,\n handleSetPortletRef,\n handleSetPortletComponentRef,\n portletIcons\n ])\n\n if (!config.portlets || config.portlets.length === 0) {\n return (\n <>\n <div className=\"flex justify-center items-center min-h-[50vh]\">\n <div className=\"text-center\">\n <ChartBarIcon style={{ width: '64px', height: '64px', color: 'var(--dc-text-muted)', margin: '0 auto 16px auto' }} />\n <h3 className=\"text-lg font-semibold mb-2 text-dc-text\">No Portlets</h3>\n <p className=\"text-sm text-dc-text-secondary mb-4\">Add your first portlet to start visualizing your data</p>\n {editable && (\n <button\n onClick={handleAddPortlet}\n className=\"inline-flex items-center px-4 py-2 border border-dc-border bg-dc-surface rounded-md focus:outline-hidden focus:ring-2\"\n style={{\n color: 'var(--dc-primary)',\n borderColor: 'var(--dc-primary)'\n }}\n onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'var(--dc-surface-hover)'}\n onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'var(--dc-surface)'}\n >\n <AddIcon className=\"w-5 h-5 mr-2\" />\n Add Portlet\n </button>\n )}\n </div>\n </div>\n \n {/* Portlet Modal */}\n <PortletAnalysisModal\n isOpen={isPortletModalOpen}\n onClose={actions.closePortletModal}\n onSave={handlePortletSave}\n portlet={editingPortlet}\n title={editingPortlet ? 'Edit Portlet' : 'Add New Portlet'}\n submitText={editingPortlet ? 'Update Portlet' : 'Add Portlet'}\n colorPalette={colorPalette}\n dashboardFilters={dashboardFilters}\n />\n </>\n )\n }\n\n // Generate grid layout from portlets - only use for lg (desktop) breakpoint\n // Let react-grid-layout handle responsive adjustments automatically\n const baseLayout: LayoutItem[] = config.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: gridSettings.minW,\n minH: gridSettings.minH, // 2 rows at 80px = 160px minimum\n // Only enable drag/resize in edit mode\n isDraggable: canEdit,\n isResizable: canEdit,\n ...(canEdit ? { resizeHandles: ['s', 'w', 'e', 'n', 'se', 'sw', 'ne', 'nw'] as const } : {})\n }))\n\n // Render the portlet grid content (shared between desktop and scaled modes)\n const renderGridContent = () => (\n <ReactGridLayout\n className=\"layout\"\n layout={baseLayout}\n onLayoutChange={handleLayoutChange}\n onDragStop={handleDragStop}\n onResizeStop={handleResizeStop}\n width={gridWidth}\n gridConfig={{\n cols: gridSettings.cols,\n rowHeight: gridSettings.rowHeight,\n margin: [16, 16],\n containerPadding: [0, 0]\n }}\n dragConfig={{\n enabled: canEdit,\n handle: '.portlet-drag-handle'\n }}\n resizeConfig={{\n enabled: canEdit,\n handles: ['s', 'w', 'e', 'n', 'se', 'sw', 'ne', 'nw'],\n // Invisible but functional resize handles\n handleComponent: (axis, ref) => (\n <div\n ref={ref as Ref<HTMLDivElement>}\n className={`react-resizable-handle react-resizable-handle-${axis}`}\n style={{ opacity: 0 }}\n />\n )\n }}\n compactor={verticalCompactor}\n >\n {config.portlets\n .filter(portlet => portlet && portlet.id) // Guard against malformed portlets\n .map(portlet => (\n <div key={portlet.id}>\n {renderPortletCard(portlet)}\n </div>\n ))}\n </ReactGridLayout>\n )\n\n const renderRowContent = () => (\n <RowManagedLayout\n rows={resolvedRows}\n portlets={config.portlets}\n gridSettings={gridSettings}\n gridWidth={gridWidth}\n canEdit={canEdit}\n isDragging={isDraggingPortlet}\n onRowResize={startRowResize}\n onColumnResize={startColumnResize}\n onPortletDragStart={handlePortletDragStart}\n onPortletDragEnd={handlePortletDragEnd}\n onRowDrop={handleRowDrop}\n onNewRowDrop={handleNewRowDrop}\n renderPortlet={renderPortletCard}\n />\n )\n\n const renderActiveLayout = layoutMode === 'rows' ? renderRowContent() : renderGridContent()\n const editModeHint = 'Drag • Resize • Auto-save'\n\n return (\n <ScrollContainerProvider value={scrollContainer}>\n <div ref={combinedContainerRef} className=\"dashboard-grid-container w-full\" style={{ maxWidth: '100%', overflow: 'hidden' }}>\n {editable && features.editToolbar !== 'floating' && (\n <div\n ref={editBarRef}\n className={`mb-4 flex justify-between items-center sticky top-0 z-10 px-4 py-4 bg-dc-surface-tertiary border border-dc-border rounded-lg transition-all duration-200 ${\n isScrolled ? 'border-b' : ''\n }`}\n style={{\n boxShadow: isScrolled ? 'var(--dc-shadow-md)' : 'var(--dc-shadow-sm)'\n }}\n >\n <div className=\"flex items-center gap-4\">\n <button\n onClick={() => isResponsiveEditable && actions.toggleEditMode()}\n disabled={!isResponsiveEditable}\n className={`inline-flex items-center px-4 py-2 text-sm font-medium rounded-md transition-colors focus:outline-hidden focus:ring-2 focus:ring-offset-2 ${\n !isResponsiveEditable\n ? 'opacity-50 cursor-not-allowed bg-dc-surface-secondary border border-dc-border'\n : isEditMode\n ? 'bg-dc-surface-secondary border border-dc-border hover:bg-dc-surface-hover'\n : 'bg-dc-surface border border-dc-border hover:bg-dc-surface-hover'\n }`}\n style={{\n color: !isResponsiveEditable ? 'var(--dc-text-muted)' : 'var(--dc-primary)',\n borderColor: !isResponsiveEditable ? 'var(--dc-border)' : isEditMode ? 'var(--dc-border)' : 'var(--dc-primary)'\n }}\n >\n {isEditMode ? <CheckIcon className=\"w-4 h-4 mr-1.5\" /> : <EditIcon className=\"w-4 h-4 mr-1.5\" />}\n {isEditMode ? 'Finish Editing' : 'Edit'}\n </button>\n {isEditMode && allowedModes.length > 1 && (\n <div className=\"inline-flex rounded-md border border-dc-border overflow-hidden whitespace-nowrap\">\n <button\n onClick={() => actions.handleLayoutModeChange('grid')}\n disabled={!canChangeLayoutMode}\n className={`inline-flex items-center gap-2 whitespace-nowrap px-3 py-1.5 text-sm font-medium transition-colors ${\n layoutMode === 'grid'\n ? 'bg-dc-surface-secondary text-dc-text shadow-inner'\n : 'bg-dc-surface text-dc-text-secondary hover:bg-dc-surface-hover'\n } ${!canChangeLayoutMode ? 'cursor-not-allowed opacity-50' : ''}`}\n >\n <GridIcon className=\"w-4 h-4 shrink-0\" />\n Grid\n </button>\n <button\n onClick={() => actions.handleLayoutModeChange('rows')}\n disabled={!canChangeLayoutMode}\n className={`inline-flex items-center gap-2 whitespace-nowrap px-3 py-1.5 text-sm font-medium transition-colors ${\n layoutMode === 'rows'\n ? 'bg-dc-surface-secondary text-dc-text shadow-inner'\n : 'bg-dc-surface text-dc-text-secondary hover:bg-dc-surface-hover'\n } ${!canChangeLayoutMode ? 'cursor-not-allowed opacity-50' : ''}`}\n >\n <RowsIcon className=\"w-4 h-4 shrink-0\" />\n Rows\n </button>\n </div>\n )}\n {!isResponsiveEditable && (\n <div className=\"flex items-center gap-2 text-sm text-dc-text-secondary\">\n <DesktopIcon className=\"w-4 h-4\" />\n <span>Desktop view required for editing</span>\n </div>\n )}\n {isEditMode && isResponsiveEditable && (\n <p className=\"hidden md:block text-sm text-dc-text-secondary\">\n {editModeHint}\n </p>\n )}\n </div>\n\n {/* Color Palette Selector and Add Portlet - Only show in edit mode */}\n {isEditMode && (\n <div className=\"flex items-center gap-3\">\n <ColorPaletteSelector\n currentPalette={config.colorPalette}\n onPaletteChange={handlePaletteChange}\n className=\"shrink-0\"\n />\n\n <button\n onClick={handleAddPortlet}\n className=\"inline-flex items-center px-4 py-2 text-sm font-medium border rounded-md focus:outline-hidden focus:ring-2 focus:ring-offset-2 border-dc-border bg-dc-surface hover:bg-dc-surface-hover\"\n style={{\n color: 'var(--dc-primary)',\n borderColor: 'var(--dc-primary)'\n }}\n >\n <AddIcon className=\"w-5 h-5 mr-2\" />\n Add Portlet\n </button>\n </div>\n )}\n </div>\n )}\n\n {/* Floating Edit Toolbar - appears when top edit bar scrolls out of view (or always if editToolbar='floating') */}\n {editable && features.editToolbar !== 'top' && displayMode === 'desktop' && (\n <FloatingEditToolbar\n isEditBarVisible={features.editToolbar === 'floating' ? false : isEditBarVisible}\n position={features.floatingToolbarPosition || 'right'}\n isEditMode={isEditMode}\n onEditModeToggle={() => isResponsiveEditable && actions.toggleEditMode()}\n layoutMode={layoutMode}\n onLayoutModeChange={actions.handleLayoutModeChange}\n allowedModes={allowedModes}\n canChangeLayoutMode={canChangeLayoutMode}\n currentPalette={config.colorPalette || 'default'}\n onPaletteChange={actions.handlePaletteChange}\n onAddPortlet={actions.openAddPortlet}\n />\n )}\n\n {/* Dashboard Filter Panel - Always visible below toolbar */}\n <DashboardFilterPanel\n dashboardFilters={dashboardFilters || []}\n editable={editable}\n schema={schema || null}\n dashboardConfig={config}\n onDashboardFiltersChange={onDashboardFiltersChange || (() => {})}\n onSaveFilters={onSave ? async (filters: DashboardFilter[]) => {\n const updatedConfig = {\n ...config,\n filters\n }\n await onSave(updatedConfig)\n } : undefined}\n selectedFilterId={selectedFilterId}\n onFilterSelect={handleFilterSelect}\n isEditMode={isEditMode}\n />\n\n {/* Filter Selection Mode Banner */}\n {selectedFilterId && selectedFilter && (\n <div\n className=\"mb-4 px-4 py-3 rounded-md border-2 transition-all\"\n style={{\n backgroundColor: 'var(--dc-primary)',\n borderColor: 'var(--dc-primary)',\n color: 'white'\n }}\n >\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <FilterIcon className=\"w-5 h-5 shrink-0\" />\n <span className=\"font-medium\">\n Filter Selection Mode - Click portlets to toggle '{selectedFilter.label}'\n </span>\n <span className=\"text-sm opacity-90 hidden sm:inline\">• Press ESC to exit</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => handleSelectAllForFilter(selectedFilterId)}\n className=\"px-3 py-1 rounded-md transition-colors text-sm font-medium\"\n style={{\n backgroundColor: 'rgba(255, 255, 255, 0.2)',\n color: 'white'\n }}\n onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.3)'}\n onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.2)'}\n >\n Select All\n </button>\n <button\n onClick={() => actions.exitFilterSelectionMode()}\n className=\"px-3 py-1 rounded-md transition-colors text-sm font-medium\"\n style={{\n backgroundColor: 'rgba(255, 255, 255, 0.2)',\n color: 'white'\n }}\n onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.3)'}\n onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.2)'}\n >\n Exit\n </button>\n </div>\n </div>\n </div>\n )}\n \n {/* Render layout based on display mode */}\n {displayMode === 'mobile' ? (\n <MobileStackedLayout\n config={config}\n colorPalette={colorPalette}\n dashboardFilters={dashboardFilters}\n onPortletRefresh={handlePortletRefresh}\n />\n ) : displayMode === 'scaled' ? (\n <ScaledGridWrapper scaleFactor={scaleFactor} designWidth={designWidth}>\n {renderActiveLayout}\n </ScaledGridWrapper>\n ) : (\n renderActiveLayout\n )}\n \n {/* Portlet Modal */}\n <PortletAnalysisModal\n isOpen={isPortletModalOpen}\n onClose={actions.closePortletModal}\n onSave={handlePortletSave}\n portlet={editingPortlet}\n title={editingPortlet ? 'Edit Portlet' : 'Add New Portlet'}\n submitText={editingPortlet ? 'Update Portlet' : 'Add Portlet'}\n colorPalette={colorPalette}\n dashboardFilters={dashboardFilters}\n />\n\n {/* Filter Configuration Modal */}\n <PortletFilterConfigModal\n isOpen={isFilterConfigModalOpen}\n onClose={actions.closeFilterConfig}\n dashboardFilters={dashboardFilters || []}\n currentMapping={filterConfigPortlet?.dashboardFilterMapping || []}\n onSave={handleSaveFilterConfig}\n portletTitle={filterConfigPortlet?.title || ''}\n />\n\n {/* Delete Confirmation Modal */}\n <ConfirmModal\n isOpen={!!deleteConfirmPortletId}\n onClose={actions.closeDeleteConfirm}\n onConfirm={actions.confirmDelete}\n title=\"Delete Portlet\"\n message={\n <>\n Are you sure you want to delete{' '}\n <strong>\n {config.portlets.find(p => p.id === deleteConfirmPortletId)?.title || 'this portlet'}\n </strong>\n ? This action cannot be undone.\n </>\n }\n confirmText=\"Delete\"\n confirmVariant=\"danger\"\n />\n </div>\n </ScrollContainerProvider>\n )\n}\n","/**\n * Analytics Dashboard Component\n * Main dashboard container that uses CubeProvider context\n * Minimal dependencies, designed to be embedded in existing apps\n */\n\nimport { useCallback, useMemo } from 'react'\nimport DashboardGrid from './DashboardGrid'\nimport { useCubeFeatures, useCubeMeta } from '../providers/CubeProvider'\nimport { DashboardStoreProvider } from '../stores/dashboardStore'\nimport { getColorPalette } from '../utils/colorPalettes'\nimport { useDirtyStateTracking } from '../hooks/useDirtyStateTracking'\nimport type { AnalyticsDashboardProps, DashboardConfig, DashboardFilter } from '../types'\n\nexport default function AnalyticsDashboard({\n config,\n editable = false,\n dashboardFilters: propDashboardFilters,\n loadingComponent,\n onConfigChange,\n onSave,\n onDirtyStateChange\n}: AnalyticsDashboardProps) {\n // Get cube metadata for filter building\n const { meta } = useCubeMeta()\n const { dashboardModes } = useCubeFeatures()\n\n // Track dirty state and wrap save/change handlers\n const {\n handleConfigChange: handleConfigChangeWithDirtyTracking,\n handleSave: handleSaveWithDirtyTracking,\n } = useDirtyStateTracking<DashboardConfig>({\n initialConfig: config,\n onConfigChange,\n onSave,\n onDirtyStateChange,\n })\n\n // Merge programmatic filters (props) with config filters by ID\n // Config provides structure/metadata, props provide value overrides\n const mergedDashboardFilters = useMemo<DashboardFilter[]>(() => {\n const configFilters = config.filters || []\n const propFilters = propDashboardFilters || []\n\n // If no prop filters, use config filters as-is\n if (propFilters.length === 0) {\n return configFilters\n }\n\n // If no config filters, use prop filters as-is\n if (configFilters.length === 0) {\n return propFilters\n }\n\n // Merge by ID: config filters provide structure, prop filters provide values\n const mergedFilters: DashboardFilter[] = configFilters.map(configFilter => {\n // Find matching prop filter by ID\n const propFilter = propFilters.find(pf => pf.id === configFilter.id)\n\n if (propFilter) {\n // Merge: preserve config metadata, use prop filter values\n return {\n ...configFilter, // Preserve id, label, isUniversalTime from config\n filter: propFilter.filter // Use filter values from prop override\n }\n }\n\n // No override for this filter, use config as-is\n return configFilter\n })\n\n // Add any prop filters that don't exist in config (new filters)\n const configIds = new Set(configFilters.map(cf => cf.id))\n const newFilters = propFilters.filter(pf => !configIds.has(pf.id))\n\n return [...mergedFilters, ...newFilters]\n }, [config.filters, propDashboardFilters])\n\n // Handle dashboard filter changes\n const handleDashboardFiltersChange = useCallback((filters: DashboardFilter[]) => {\n // Only update config if we're not using programmatic filters\n if (!propDashboardFilters || propDashboardFilters.length === 0) {\n const updatedConfig = {\n ...config,\n filters\n }\n handleConfigChangeWithDirtyTracking(updatedConfig)\n } else {\n console.warn('Dashboard filters are controlled via props - config changes ignored')\n }\n }, [config, propDashboardFilters, handleConfigChangeWithDirtyTracking])\n\n // Resolve complete palette object based on config\n const colorPalette = useMemo(() => {\n const paletteName = config.colorPalette\n return getColorPalette(paletteName)\n }, [config.colorPalette])\n\n return (\n <DashboardStoreProvider>\n <div className=\"w-full\">\n {/* Dashboard Grid (now includes filter panel) */}\n <DashboardGrid\n config={config}\n editable={editable}\n dashboardFilters={mergedDashboardFilters}\n loadingComponent={loadingComponent}\n onConfigChange={handleConfigChangeWithDirtyTracking}\n onSave={handleSaveWithDirtyTracking}\n colorPalette={colorPalette}\n schema={meta}\n dashboardModes={dashboardModes}\n onDashboardFiltersChange={handleDashboardFiltersChange}\n />\n </div>\n </DashboardStoreProvider>\n )\n}\n","/**\n * Portlet Container Component\n * Simple wrapper for individual portlets\n */\n\nimport { useState, useCallback } from 'react'\nimport AnalyticsPortlet from './AnalyticsPortlet'\nimport DebugModal from './DebugModal'\nimport type { PortletConfig } from '../types'\n\ninterface PortletContainerProps {\n portlet: PortletConfig\n editable?: boolean\n onEdit?: (portlet: PortletConfig) => void\n onDelete?: (portletId: string) => void\n onRefresh?: (portletId: string) => void\n}\n\nexport default function PortletContainer({ \n portlet, \n editable = false,\n onEdit,\n onDelete,\n onRefresh\n}: PortletContainerProps) {\n const [debugData, setDebugData] = useState<{\n chartConfig: any\n displayConfig: any\n queryObject: any\n data: any[]\n chartType: string\n cacheInfo?: { hit: true; cachedAt: string; ttlMs: number; ttlRemainingMs: number }\n } | null>(null)\n\n // Memoize debug data callback to prevent AnalyticsPortlet re-renders\n const handleDebugDataReady = useCallback((data: {\n chartConfig: any\n displayConfig: any\n queryObject: any\n data: any[]\n chartType: string\n cacheInfo?: { hit: true; cachedAt: string; ttlMs: number; ttlRemainingMs: number }\n }) => {\n setDebugData(data)\n }, [])\n\n return (\n <div className=\"bg-dc-surface border border-dc-border rounded-lg flex flex-col h-full\" style={{ boxShadow: 'var(--dc-shadow-sm)' }}>\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-dc-border shrink-0 bg-dc-surface-secondary rounded-t-lg px-3 py-2 md:px-6 md:py-3\">\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n <h3 className=\"font-semibold text-sm truncate text-dc-text\">{portlet.title}</h3>\n {/* Debug button - right next to title */}\n {debugData && (\n <DebugModal\n chartConfig={debugData.chartConfig}\n displayConfig={debugData.displayConfig}\n queryObject={debugData.queryObject}\n data={debugData.data}\n chartType={debugData.chartType}\n cacheInfo={debugData.cacheInfo}\n />\n )}\n </div>\n\n <div className=\"flex items-center gap-2 ml-4\">\n\n {editable && (\n <>\n <button\n onClick={() => onRefresh?.(portlet.id)}\n className=\"p-1.5 hover:bg-dc-surface-hover rounded-sm text-dc-text-secondary\"\n title=\"Refresh\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n </button>\n <button\n onClick={() => onEdit?.(portlet)}\n className=\"p-1.5 hover:bg-dc-surface-hover rounded-sm text-dc-text-secondary\"\n title=\"Edit\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\" />\n </svg>\n </button>\n <button\n onClick={() => onDelete?.(portlet.id)}\n className=\"p-1.5 rounded-sm text-dc-danger\"\n style={{ backgroundColor: 'transparent' }}\n onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'var(--dc-danger-bg)'}\n onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}\n title=\"Delete\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" />\n </svg>\n </button>\n </>\n )}\n </div>\n </div>\n\n {/* Content */}\n <div className=\"px-2 py-3 md:px-4 md:pt-6 md:pb-4 flex-1 min-h-0\">\n <AnalyticsPortlet\n query={portlet.query}\n chartType={portlet.chartType}\n chartConfig={portlet.chartConfig}\n displayConfig={portlet.displayConfig}\n title={portlet.title}\n height=\"100%\"\n onDebugDataReady={handleDebugDataReady}\n />\n </div>\n </div>\n )\n}","import React, { useState, useEffect } from 'react'\nimport Modal from './Modal'\n\ninterface DashboardEditModalProps {\n isOpen: boolean\n onClose: () => void\n onSave: (data: { name: string; description?: string }) => Promise<void> | void\n title: string\n submitText: string\n initialName?: string\n initialDescription?: string\n}\n\nexport default function DashboardEditModal({\n isOpen,\n onClose,\n onSave,\n title,\n submitText,\n initialName = '',\n initialDescription = ''\n}: DashboardEditModalProps) {\n const [name, setName] = useState('')\n const [description, setDescription] = useState('')\n const [isSaving, setIsSaving] = useState(false)\n\n // Initialize form values when modal opens\n useEffect(() => {\n if (isOpen) {\n setName(initialName)\n setDescription(initialDescription)\n }\n }, [isOpen, initialName, initialDescription])\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n \n if (!name.trim()) {\n return\n }\n\n setIsSaving(true)\n \n try {\n await onSave({\n name: name.trim(),\n description: description.trim() || undefined\n })\n handleClose()\n } catch {\n // Failed to save dashboard\n // Don't close modal on error so user can retry\n } finally {\n setIsSaving(false)\n }\n }\n\n const handleClose = () => {\n setName('')\n setDescription('')\n setIsSaving(false)\n onClose()\n }\n\n const footer = (\n <>\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={isSaving}\n className=\"px-4 py-2 text-sm font-medium text-dc-text-secondary bg-dc-surface border border-dc-border rounded-md hover:bg-dc-surface-hover disabled:opacity-50\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n form=\"dashboard-form\"\n disabled={isSaving || !name.trim()}\n className=\"px-4 py-2 text-sm font-medium text-white bg-dc-primary border border-transparent rounded-md hover:bg-dc-primary-hover disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSaving ? 'Saving...' : submitText}\n </button>\n </>\n )\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={handleClose}\n title={title}\n size=\"fullscreen-mobile\"\n footer={footer}\n >\n <form id=\"dashboard-form\" onSubmit={handleSubmit} className=\"space-y-4 w-full\">\n <div>\n <label htmlFor=\"dashboard-name\" className=\"block text-sm font-medium text-dc-text-secondary mb-1\">\n Dashboard Name\n </label>\n <input\n type=\"text\"\n id=\"dashboard-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-dc-border rounded-md bg-dc-surface text-dc-text focus:outline-none focus:ring-2 focus:ring-dc-primary focus:border-dc-primary\"\n placeholder=\"Enter dashboard name...\"\n required\n autoFocus\n />\n </div>\n\n <div>\n <label htmlFor=\"dashboard-description\" className=\"block text-sm font-medium text-dc-text-secondary mb-1\">\n Description (optional)\n </label>\n <textarea\n id=\"dashboard-description\"\n rows={3}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n className=\"w-full px-3 py-2 border border-dc-border rounded-md bg-dc-surface text-dc-text focus:outline-none focus:ring-2 focus:ring-dc-primary focus:border-dc-primary\"\n placeholder=\"Enter description...\"\n />\n </div>\n </form>\n </Modal>\n )\n}","/**\n * QueryBuilder Shim\n *\n * Backward compatibility wrapper that provides the QueryBuilder interface\n * while using AnalysisBuilder internally.\n *\n * This allows existing code importing QueryBuilder to seamlessly use the new\n * AnalysisBuilder component without any code changes.\n */\nimport { forwardRef, useImperativeHandle, useRef } from 'react'\nimport AnalysisBuilder from './AnalysisBuilder'\nimport type { AnalysisBuilderRef } from './AnalysisBuilder/types'\nimport type { QueryBuilderProps, QueryBuilderRef } from './QueryBuilder/types'\n\nconst QueryBuilderShim = forwardRef<QueryBuilderRef, QueryBuilderProps>(\n (props, ref) => {\n const analysisBuilderRef = useRef<AnalysisBuilderRef>(null)\n\n // Map QueryBuilder ref interface to AnalysisBuilder ref\n useImperativeHandle(ref, () => ({\n getCurrentQuery: () => {\n const config = analysisBuilderRef.current?.getQueryConfig()\n if (!config) {\n return { measures: [], dimensions: [] }\n }\n // If multi-query, return first query for backward compatibility\n if ('queries' in config) {\n return config.queries[0] || { measures: [], dimensions: [] }\n }\n return config\n },\n\n getValidationState: () => {\n // AnalysisBuilder doesn't expose validation state\n // Return a basic \"valid\" state since AnalysisBuilder auto-validates\n return {\n status: 'valid' as const\n }\n },\n\n getValidationResult: () => {\n // AnalysisBuilder doesn't expose validation results\n // Return null as it's an optional field\n return null\n }\n }), [])\n\n // Map QueryBuilder props to AnalysisBuilder props\n return (\n <AnalysisBuilder\n ref={analysisBuilderRef}\n className={props.className}\n initialQuery={props.initialQuery}\n disableLocalStorage={props.disableLocalStorage}\n hideSettings={props.hideSettings}\n // Note: enableSharing and onShare props are not supported by AnalysisBuilder\n // The AnalysisBuilder has its own sharing mechanism\n />\n )\n }\n)\n\nQueryBuilderShim.displayName = 'QueryBuilder'\n\nexport default QueryBuilderShim\n"],"names":["observerMap","RootIds","rootId","unsupportedValue","getRootId","root","optionsToId","options","key","createObserver","id","instance","elements","thresholds","observer","entries","entry","_a2","inView","threshold","callback","observe","element","fallbackInView","bounds","callbacks","useInView","delay","trackVisibility","rootMargin","triggerOnce","skip","initialInView","onChange","ref","setRef","React2","lastInViewRef","state","setState","unobserve","previousInView","entryTarget","previousEntryTarget","result","DEFAULT_BINDING_KEY_LIMIT","getBindingKeyField","bindingKey","query","mappings","cubeName","getCubeNameFromQuery","mapping","m","parts","extractBindingKeyValues","data","bindingKeyField","limit","values","row","value","allValues","totalCount","a","b","limitedValues","buildStepQuery","step","previousBindingKeyValues","inFilter","calculateStepMetrics","currentCount","previousCount","firstStepCount","conversionRate","cumulativeConversionRate","buildStepResult","stepIndex","countUnique","executionTime","error","bindingKeyLimit","extracted","count","buildFunnelChartData","stepResults","index","buildFunnelResult","config","status","currentStepIndex","lastStepCount","totalExecutionTime","sum","r","buildFunnelConfigFromQueries","queries","stepLabels","stepTimeToConvert","steps","shouldStopFunnelExecution","stepResult","isFunnelData","DEFAULT_DEBOUNCE_MS","isValidFunnelConfig","useFunnelQuery","debounceMs","onStepComplete","onComplete","onError","cubeApi","useCubeApi","isValidConfig","debouncedConfig","isDebouncing","useDebounceQuery","setResult","useState","setStepResults","setStatus","setCurrentStepIndex","setError","executedQueries","setExecutedQueries","executionIdRef","useRef","abortControllerRef","useEffect","execute","useCallback","executionId","accumulatedResults","accumulatedQueries","currentBindingKeyValues","executionError","i","stepQuery","serverQuery","cleanQueryForServer","startTime","resultSet","stepError","err","finalStatus","finalResult","cancel","reset","stepLoadingStates","useMemo","_","chartData","createFunnelQueryKey","RefreshIcon","getIcon","ChartErrorBoundary","Component","props","errorInfo","jsxs","jsx","isMultiQueryConfig","obj","shouldIncludeFilter","filter","simpleFilter","f","getApplicableDashboardFilters","dashboardFilters","filterMapping","df","convertToServerFormat","groupFilter","convertedFilters","mergeDashboardAndPortletFilters","portletFilters","format","extractDashboardFields","dashboardConfig","measures","dimensions","timeDimensions","portlet","measure","dimension","td","extractFieldsFromFilters","field","e","filters","fields","getDateRangeFromFilter","applyUniversalTimeFilters","portletTimeDimensions","universalTimeFilters","dateRange","AnalyticsPortlet","React","forwardRef","chartType","chartConfig","displayConfig","dashboardFilterMapping","eagerLoad","_isVisible","height","_title","colorPalette","loadingComponent","onDebugDataReady","onDebugDataReadyRef","scrollContainer","useScrollContainer","inViewRef","isVisible","chartTypeConfig","useChartConfig","shouldSkipQuery","regularFilters","queryObject","multiQueryConfig","parsed","applicableFilters","q","mergedFilters","mergedTimeDimensions","isMultiQuery","shouldSkipSingle","shouldSkipMulti","queryClient","useQueryClient","singleQueryResult","useCubeLoadQuery","multiQueryResult","useMultiCubeLoadQuery","isLoading","isFetching","multiQueryData","useImperativeHandle","cleanedConfig","createMultiQueryKey","cleanedQuery","createQueryKey","handleRetry","getData","hasMandatoryFields","zone","LoadingIndicator","chartHeight","isValidChartType","LazyChart","useScrollDetection","containerRef","container","isScrolled","setIsScrolled","timeoutRef","handleScroll","shouldBeScrolled","prev","useElementVisibility","elementRef","setIsVisible","hasBeenVisibleRef","checkVisibility","elementRect","containerRect","visible","scrollTarget","rafId","highlightJs","loadingPromise","loadSyntaxHighlighter","hljs","javascript","sql","sql$1","json","json$1","highlightCodeBlocks","block","DebugModal","cacheInfo","isOpen","setIsOpen","handleKeyDown","event","timer","createStoreImpl","createState","listeners","partial","replace","nextState","previousState","listener","getState","api","initialState","createStore","identity","arg","useStore","selector","slice","trackedConnections","getTrackedConnectionState","name","api2","extractConnectionInformation","store","extensionConnector","existingConnection","newConnection","removeStoreFromTrackedConnections","connectionInfo","findCallerName","stack","_a","_b","traceLines","apiSetStateLineIndex","traceLine","callerLine","devtoolsImpl","fn","devtoolsOptions","set","get","enabled","anonymousActionType","__vite_import_meta_env__","connection","connectionInformation","isRecording","nameOrAction","action","setStateFromDevtools","originalIsRecording","store2","didWarnAboutReservedActionType","originalDispatch","args","message","parseJsonThen","stateFromDevtools","nextLiftedState","lastComputedState","devtools","stringified","subscribeWithSelectorImpl","origSubscribe","optListener","equalityFn","currentSlice","nextSlice","previousSlice","subscribeWithSelector","createJSONStorage","getStorage","storage","parse","str2","str","newValue","toThenable","input","onFulfilled","_onRejected","_onFulfilled","onRejected","persistImpl","baseOptions","persistedState","currentState","hasHydrated","hydrationListeners","finishHydrationListeners","setItem","savedSetState","configResult","stateFromStorage","hydrate","cb","postRehydrationCallback","deserializedStorageValue","migration","migrationResult","migrated","migratedState","newOptions","persist","createDefaultState","buildInitialState","createStoreActions","_get","isEdit","filterId","portletId","rows","isDragging","layout","initialized","rest","createDashboardStore","fallbackStore","getFallbackStore","DashboardStoreContext","createContext","DashboardStoreProvider","children","initialEditMode","storeRef","useDashboardStore","useContext","useDashboardStoreApi","useDashboardStoreOptional","contextStore","selectEditModeState","selectModalState","selectLayoutState","selectDebugData","selectPortletDebugData","selectEditModeActions","selectModalActions","selectLayoutActions","selectDebugDataActions","selectAllActions","ICON_STYLE","arePropsEqual","prevProps","nextProps","containerPropsEqual","shallowEqualObjects","headerPropsEqual","keysA","keysB","DashboardPortletCard","editable","configEagerLoad","containerProps","headerProps","setPortletRef","setPortletComponentRef","icons","isEditMode","selectedFilterId","debugData","setDebugData","hasSelectedFilter","isInSelectionMode","mergedContainerClassName","mergedHeaderClassName","containerOnClick","_containerClassName","containerStyle","restContainerProps","headerOnClick","_headerClassName","headerStyle","restHeaderProps","handleDebugDataReady","el","Fragment","COLUMN_GAP","RowManagedLayout","portlets","gridSettings","gridWidth","canEdit","onRowResize","onColumnResize","onPortletDragStart","onPortletDragEnd","onRowDrop","onNewRowDrop","renderPortlet","portletMap","activeDropKey","setActiveDropKey","setDropActive","isDragActive","handlePortletDragStart","rowIndex","columnIndex","handlePortletDragEnd","topDropActive","bottomDropActive","rowHeight","safeGridWidth","paddingLeft","paddingRight","unitWidth","column","width","COLOR_PALETTES","getColorPalette","paletteName","p","EditIcon","CheckIcon","GridIcon","RowsIcon","AddIcon","SwatchIcon","FloatingEditToolbar","isEditBarVisible","position","onEditModeToggle","layoutMode","onLayoutModeChange","allowedModes","canChangeLayoutMode","currentPalette","onPaletteChange","onAddPortlet","isPaletteOpen","setIsPaletteOpen","paletteRef","handleClickOutside","positionClasses","isHidden","toolbarContent","ToolbarButton","CompactPaletteDropdown","palette","createPortal","Icon","tooltip","isActive","disabled","onClick","color","Modal","onClose","title","size","closeOnBackdropClick","closeOnEscape","showCloseButton","footer","noPadding","handleEscapeKey","generateId","generateMetricLabel","label","n","parseRelativeDateRange","now","lowerRange","utcYear","utcMonth","utcDate","utcDay","start","end","mondayOffset","quarter","lastDaysMatch","days","lastWeeksMatch","lastMondayOffset","currentQuarter","lastQuarter","year","lastMonthsMatch","months","lastYearsMatch","years","parseDateRange","formatDateForCube","date","calculatePriorPeriod","currentStart","currentEnd","periodLengthMs","periodLengthDays","priorEnd","priorStart","findDateFilterForField","nested","simple","buildCompareDateRangeFromFilter","timeDimensionField","dateFilter","currentPeriod","priorPeriod","removeComparisonDateFilter","acc","cleanedSubFilters","buildCubeQuery","metrics","breakdowns","order","preserveComparisonFilters","comparisonFields","filteredFilters","compareDateRange","STORAGE_KEY","createInitialState","findFieldInSchema","fieldName","schema","cube","d","getFieldTitle","found","schemaToFieldOptions","mode","isTime","filterFieldOptions","searchTerm","selectedCube","filtered","opt","term","groupFieldsByCube","grouped","option","existing","getCubeNames","getCubeTitle","c","RECENT_FIELDS_KEY","MAX_RECENT_FIELDS","getRecentFields","stored","addRecentField","recent","getRecentFieldOptions","recentFieldNames","allOptions","recentOptions","isTimeDimension","breakdown","getFirstTimeDimension","getFirstDimension","getDimensions","getTimeDimensions","getChartAvailability","measureCount","dimensionCount","timeDimensionCount","totalBreakdowns","getAllChartAvailability","chartTypes","availability","selectBestChartType","currentChartType","hasTimeDimension","hasDimension","hasMeasure","getSmartChartDefaults","buildChartConfig","timeDimension","allBreakdowns","shouldAutoSwitchChartType","userManuallySelected","recommendedType","initialQueryState","initialAIState","queryToState","baseFilters","hasDateFilter","firstRange","defaultState","newQueryStates","newMergeStrategy","states","updater","newStates","strategy","newMetric","fieldToRemove","newMetrics","newOrder","existingIndex","fromIndex","toIndex","movedItem","granularity","newBreakdown","newBreakdowns","mergeStrategy","activeQueryIndex","queryStates","sourceIndex","sourceState","targetBreakdown","isEnabling","newChartType","newChartConfig","newFilter","convertDateRangeTypeToValue","smartConfig","updatedBreakdowns","existingFilters","updatedFilters","group","direction","newState","newActiveIndex","type","tab","view","prompt","generating","hasQuery","duration","newTimeToConvert","qs","sharedState","q1Breakdowns","current","validQueries","createAnalysisBuilderStore","AnalysisBuilderStoreContext","AnalysisBuilderStoreProvider","initialQuery","initialChartConfig","disableLocalStorage","useAnalysisBuilderStore","useAnalysisBuilderStoreApi","selectCurrentState","selectMetrics","selectBreakdowns","selectFilters","selectChartConfig","selectUIState","selectMultiQueryState","selectFunnelState","extractTimeDimensions","validateTimeDimensionAlignment","errors","q1TimeDims","qTimeDims","refTimeDim","matchingDim","validateMergeKeys","mergeKeys","allFields","detectMeasureCollisions","warnings","measureCounts","collisions","collisionIndices","indices","detectAsymmetricDateRanges","dateRanges","validateMultiQueryConfig","isMultiQueryValid","getValidationSummary","useAnalysisQueryBuilder","setActiveQueryIndex","setMergeStrategy","addQuery","removeQuery","getCurrentState","getMergeKeys","isMultiQueryModeGetter","queryState","isMultiQueryMode","currentQuery","allQueries","multiQueryValidation","isValidQuery","useAnalysisCombinedFields","combinedMetrics","seen","combined","qIndex","metric","combinedBreakdowns","effectiveBreakdowns","useAnalysisQueryExecution","initialData","funnelBindingKey","isFunnelMode","funnelConfig","funnelQueryResult","dryRunResult","useDryRunQueries","hasDebounced","refetch","executionStatus","hasResults","executionResults","perQueryResults","funnelExecutedQueries","useAnalysisChartDefaults","externalColorPalette","userManuallySelectedChart","localPaletteName","setChartType","setChartTypeManual","setChartConfig","setDisplayConfig","setLocalPaletteName","setUserManuallySelectedChart","chartAvailability","prevMetricsBreakdownsRef","currentKey","newConfig","smartDefaults","useAnalysisUIState","activeTab","activeView","displayLimit","showFieldModal","fieldModalMode","setActiveTab","setActiveView","setDisplayLimit","closeFieldModal","activeTableIndex","setActiveTableIndex","LZString","keyStrBase64","keyStrUriSafe","baseReverseDic","getBaseValue","alphabet","character","res","compressed","uncompressed","buf","TotalLen","current_value","bitsPerChar","getCharFromInt","context_dictionary","context_dictionaryToCreate","context_c","context_wc","context_w","context_enlargeIn","context_dictSize","context_numBits","context_data","context_data_val","context_data_position","ii","length","resetValue","getNextValue","dictionary","enlargeIn","dictSize","numBits","w","bits","resb","maxpower","power","module","MAX_HASH_LENGTH","SHARE_PREFIX","compressAndEncode","compressToEncodedURIComponent","decodeAndDecompress","encoded","decompressFromEncodedURIComponent","compressWithFallback","fullEncoded","queryOnlyState","queryOnlyEncoded","parseShareHash","hash","clearShareHash","url","useAnalysisInitialization","onQueryChange","onChartConfigChange","loadFromShare","hasInitializedShareRef","useAnalysisBuilder","features","useCubeFeatures","storeApi","queryBuilder","combinedFields","s","queryExecution","chartDefaults","uiState","openMetricsModal","addMetric","removeMetric","toggleMetric","reorderMetrics","openBreakdownsModal","addBreakdown","removeBreakdown","toggleBreakdown","setBreakdownGranularity","toggleBreakdownComparison","reorderBreakdowns","setFilters","dropFieldToFilter","setOrder","clearQuery","setFunnelBindingKey","aiState","openAI","closeAI","setAIPrompt","setAIGenerating","setAIError","setAIHasGeneratedQuery","saveAIPreviousState","restoreAIPreviousState","shareButtonStateRef","canShare","handleFieldSelected","fieldType","_cubeName","keepOpen","generateAI","resolve","acceptAI","cancelAI","share","getQueryConfig","getChartConfig","sendGeminiMessage","apiKey","userPrompt","endpoint","requestBody","headers","response","errorMessage","errorData","errorText","extractTextFromResponse","useAnalysisAI","aiEndpoint","setAIState","handleOpenAI","handleCloseAI","handleAIPromptChange","handleGenerateAI","responseText","aiChartType","aiChartConfig","handleAcceptAI","handleCancelAI","useAnalysisShare","shareButtonState","setShareButtonState","handleShare","shareableState","queryOnly","textArea","FieldSearchItem","isSelected","isFocused","onMouseEnter","getFieldIcon","getMeasureTypeIcon","getFieldTypeIcon","getBadgeStyle","getTypeLabel","FieldSearchItem$1","memo","FieldDetailPanel","getIconBgStyle","getTypeDisplay","FieldDetailPanel$1","SearchIcon","CloseIcon","FieldSearchModal","onSelect","selectedFields","externalRecentFields","setSearchTerm","setSelectedCube","focusedField","setFocusedField","focusedIndex","setFocusedIndex","lastSelectedIndex","setLastSelectedIndex","searchInputRef","resultsContainerRef","fieldOptionsMode","allFieldOptions","cubeNames","filteredFields","groupedFields","flatFieldsList","list","selectSingleField","metaField","handleSelectField","fieldIndex","shiftKey","startIndex","endIndex","rangeField","next","focusedElement","searchPlaceholder","modalTitle","focusedFieldId","idx","formatReason","reason","getReasonBadgeClasses","QueryAnalysisPanel","analysis","InfoIcon","ArrowRightIcon","WarningIcon","TableIcon","LinkIcon","SuccessIcon","ErrorIcon","jp","stepIdx","jc","pa","jk","deepFreeze","prop","Response","escapeHTML","inherit$1","original","objects","SPAN_CLOSE","emitsWrappingTags","node","scopeToCSSClass","prefix","pieces","x","HTMLRenderer","parseTree","text","className","newNode","opts","TokenTree","scope","builder","child","TokenTreeEmitter","emitter","source","re","lookahead","concat","anyNumberOfTimes","optional","stripOptionsFromArgs","either","countMatchGroups","startsWith","lexeme","match","BACKREF_RE","_rewriteBackreferences","regexps","joinWith","numCaptures","regex","offset","out","MATCH_NOTHING_RE","IDENT_RE","UNDERSCORE_IDENT_RE","NUMBER_RE","C_NUMBER_RE","BINARY_NUMBER_RE","RE_STARTERS_RE","SHEBANG","beginShebang","resp","BACKSLASH_ESCAPE","APOS_STRING_MODE","QUOTE_STRING_MODE","PHRASAL_WORDS_MODE","COMMENT","begin","modeOptions","ENGLISH_WORD","C_LINE_COMMENT_MODE","C_BLOCK_COMMENT_MODE","HASH_COMMENT_MODE","NUMBER_MODE","C_NUMBER_MODE","BINARY_NUMBER_MODE","REGEXP_MODE","TITLE_MODE","UNDERSCORE_TITLE_MODE","METHOD_GUARD","MODES","skipIfHasPrecedingDot","scopeClassName","_parent","beginKeywords","parent","compileIllegal","compileMatch","compileRelevance","beforeMatchExt","originalMode","COMMON_KEYWORDS","DEFAULT_KEYWORD_SCOPE","compileKeywords","rawKeywords","caseInsensitive","scopeName","compiledKeywords","compileList","keywordList","keyword","pair","scoreForKeyword","providedScore","commonKeyword","seenDeprecations","warn","deprecated","version","MultiClassError","remapScopeNames","regexes","scopeNames","emit","positions","beginMultiClass","endMultiClass","scopeSugar","MultiClass","compileLanguage","language","langRe","global","MultiRegex","terminators","matchData","ResumableMultiRegex","matcher","m2","buildModeRegex","mm","compileMode","cmode","ext","keywordPattern","expandOrCloneMode","dependencyOnParent","variant","HTMLInjectionError","html","escape","inherit","NO_MATCH","MAX_KEYWORD_HITS","HLJS","languages","aliases","plugins","SAFE_MODE","LANGUAGE_NOT_FOUND","PLAINTEXT_LANGUAGE","shouldNotHighlight","languageName","blockLanguage","classes","getLanguage","_class","highlight","codeOrLanguageName","optionsOrCode","ignoreIllegals","code","context","fire","_highlight","codeToHighlight","continuation","keywordHits","keywordData","matchText","processKeywords","top","modeBuffer","lastIndex","word","kind","keywordRelevance","relevance","cssClass","emitKeyword","processSubLanguage","continuations","highlightAuto","processBuffer","emitMultiClass","max","klass","startNewMode","endOfMode","matchPlusRemainder","matched","doIgnore","resumeScanAtSamePosition","doBeginMatch","newMode","beforeCallbacks","doEndMatch","endMode","origin","processContinuations","item","lastMatch","processLexeme","textBeforeMatch","processed","iterations","md","beforeMatch","processedCount","justTextHighlightResult","languageSubset","plaintext","results","autoDetection","sorted","best","secondBest","updateClassName","currentLang","resultLang","highlightElement","configure","userOptions","initHighlighting","highlightAll","initHighlightingOnLoad","wantsHighlight","boot","registerLanguage","languageDefinition","lang","error$1","registerAliases","unregisterLanguage","alias","listLanguages","aliasList","upgradePluginAPI","plugin","addPlugin","removePlugin","deprecateHighlightBlock","core","ATTRIBUTE","PUNCTUATION","LITERALS","LITERALS_MODE","COMMENT_MODE","STRING","QUOTED_IDENTIFIER","MULTI_WORD_TYPES","TYPES","NON_RESERVED_WORDS","RESERVED_WORDS","RESERVED_FUNCTIONS","POSSIBLE_WITHOUT_PARENS","COMBOS","FUNCTIONS","KEYWORDS","VARIABLE","OPERATOR","FUNCTION_CALL","kws_to_regex","kw","MULTI_WORD_KEYWORDS","reduceRelevancy","exceptions","when","qualifyFn","CodeBlock","maxHeight","copied","setCopied","codeRef","CopyIcon","handleCopy","ChevronDownIcon","ColorPaletteSelector","dropdownRef","currentPaletteObj","handlePaletteSelect","AnalysisResultsPanel","totalRowCount","resultsStale","currentPaletteName","onColorPaletteChange","onActiveViewChange","onDisplayLimitChange","hasMetrics","debugDataPerQuery","onShareClick","onRefreshClick","canRefresh","isRefreshing","onClearClick","canClear","enableAI","isAIOpen","onAIToggle","queryCount","onActiveTableChange","showDebug","setShowDebug","activeDebugIndex","setActiveDebugIndex","currentDebugData","debugSql","debugAnalysis","debugLoading","debugError","debugQuery","isShowingFunnelQuery","combinedQueryForChart","allMeasures","ChartIcon","CodeIcon","ShareIcon","TrashIcon","SparklesIcon","renderLoading","renderError","renderHeader","hasQueryContent","renderWaiting","renderEmpty","renderNoData","renderChart","renderDebug","renderTable","tableIndex","tableData","tableQuery","limitedData","renderOverlaySpinner","renderSuccess","shouldShowResults","MetricItemCard","fieldMeta","onRemove","sortDirection","sortPriority","onToggleSort","onDragStart","onDragEnd","ChevronUpIcon","ChevronUpDownIcon","measureType","MeasureIcon","displayTitle","getSortIcon","getSortTooltip","isDraggable","findFieldMeta","getNextSortDirection","MetricsSection","onAdd","onOrderChange","onReorder","draggedIndex","setDraggedIndex","dropTargetIndex","setDropTargetIndex","draggedIndexRef","dropTargetIndexRef","orderKeys","metricsWithMeta","dragCloneRef","handleDragStart","target","clone","rect","offsetX","offsetY","handleDragEnd","handleItemDragOver","itemIndex","currentDraggedIndex","targetIndex","handleItemDrop","currentDropTargetIndex","adjustedTarget","handleSectionDragLeave","relatedTarget","getItemTransform","gapSize","shouldShowGapIndicator","SectionHeading","transform","showGapBefore","nextDirection","TIME_GRANULARITIES","BreakdownItemCard","onGranularityChange","onComparisonToggle","comparisonDisabled","DimensionIcon","TimeIcon","g","BreakdownSection","activeComparisonId","breakdownsWithMeta","TimeDimensionIcon","FilterConfigModal","initialFilter","onSave","onCancel","anchorElement","setFilter","isOperatorDropdownOpen","setIsOperatorDropdownOpen","isValueDropdownOpen","setIsValueDropdownOpen","isDateRangeDropdownOpen","setIsDateRangeDropdownOpen","rangeType","setRangeType","numberValue","setNumberValue","searchText","setSearchText","modalPosition","setModalPosition","debouncedSearchText","useDebounce","fieldInfo","isTimeField","isMeasureField","isDimensionField","fieldTitle","operatorMeta","FILTER_OPERATORS","availableOperators","getAvailableOperators","shouldShowDateRange","shouldShowComboBox","distinctValues","valuesLoading","valuesError","searchValues","useFilterValues","modalHeight","spaceAbove","spaceBelow","modalWidth","shouldAppearAbove","left","flexMatch","singularMatch","num","unit","DATE_RANGE_OPTIONS","requiresNumberInput","handleOperatorChange","operator","handleValueSelect","handleValueRemove","valueToRemove","v","handleDirectInput","numValue","handleBetweenStartInput","currentValues","newValues","handleBetweenEndInput","handleDateInput","handleRangeTypeChange","newRangeType","today","handleNumberValueChange","handleCustomStartDate","handleCustomEndDate","operatorLabel","op","dateRangeLabel","FieldIcon","renderValueInput","AnalysisFilterItem","onUpdate","isModalOpen","setIsModalOpen","buttonRef","valueDisplay","formatValueDisplay","updatedFilter","isSimpleFilter","isGroupFilter","AnalysisFilterGroup","onAddFilter","depth","hideRemoveButton","isAddMenuOpen","setIsAddMenuOpen","addMenuRef","handleToggleType","newType","handleUpdateFilter","newFilters","handleRemoveFilter","handleAddNestedGroup","newGroup","handleAddFilterClick","createNestedAddFilterHandler","nestedIndex","relativePath","getBorderColor","getGroupBgColor","conditionCount","conditionLabel","countFilters","getSelectedFields","addFilterAtPath","path","firstIndex","restPath","targetFilter","AnalysisFilterSection","onFiltersChange","onFieldDropped","setShowFieldModal","isDragOver","setIsDragOver","pendingAddPath","totalFilterCount","handleDragOver","handleDragLeave","handleDrop","_fieldType","defaultOperator","handleUpdateTopLevelFilter","handleRemoveTopLevelFilter","handleClearAll","createAddFilterHandler","basePath","renderFilter","parentPath","currentPath","AnalysisAxisDropZone","onDrop","onDragOver","draggedItem","getFieldMeta","yAxisAssignment","onYAxisAssignmentChange","description","mandatory","maxItems","emptyText","isDraggedOver","setIsDraggedOver","isReorderDraggedOver","setIsReorderDraggedOver","draggingFieldRef","fieldsRef","getCanAcceptMore","effectiveCount","getIsFull","canAcceptMore","isFull","handleGlobalDragEnd","isTopHalf","handleFieldDragEnd","getDefaultFieldMeta","renderFieldIcon","meta","IconComponent","isLeavingContainer","isRelatedTargetOutside","isBeingDragged","currentAxis","chartConfigRegistry","barChartConfig","lineChartConfig","areaChartConfig","pieChartConfig","scatterChartConfig","bubbleChartConfig","radarChartConfig","radialBarChartConfig","treemapChartConfig","dataTableConfig","activityGridChartConfig","kpiNumberConfig","kpiDeltaConfig","kpiTextConfig","markdownConfig","funnelChartConfig","chartTypeLabels","ChartTypeSelector","selectedType","onTypeChange","compact","labelA","labelB","SelectedIcon","selectedLabel","useCase","isAvailable","unavailableReason","tooltipText","AnalysisChartConfigPanel","onChartTypeChange","setDraggedItem","availableFields","getFieldsForDropZone","allAvailableFields","hasChanges","dropZone","currentFields","validFields","getFieldType","schemaMeta","breakdownItem","fromAxis","toAxis","fromValue","filteredValue","toValue","dropZoneConfig","dz","handleRemoveFromAxis","_removed","handleReorder","axisKey","newArray","handleYAxisAssignmentChange","axis","unassignedFields","assignedFields","hasUnassignedFields","StringArrayInput","placeholder","localText","setLocalText","externalText","handleBlur","arrayValue","AnalysisDisplayConfigPanel","onDisplayConfigChange","AxisFormatControls","validateBindingKeyExists","dimName","validateStepQueries","canResolveBindingKey","validateBindingKeyForSteps","validateTimeWindow","validateFunnelConfig","timeError","globalTimeError","isMinimumFunnelConfigValid","getAvailableBindingKeyDimensions","dim","getBindingKeyLabel","first","FunnelBindingKeySelector","searchQuery","setSearchQuery","availableDimensions","groupedDimensions","groups","filteredGroups","dims","matchingDims","handleSelect","handleClear","hasSelection","AnalysisQueryPanel","onActiveTabChange","onAddMetric","onRemoveMetric","onReorderMetrics","onAddBreakdown","onRemoveBreakdown","onBreakdownGranularityChange","onBreakdownComparisonToggle","onReorderBreakdowns","onDropFieldToFilter","_validationStatus","_validationError","onActiveQueryChange","onAddQuery","onRemoveQuery","onMergeStrategyChange","breakdownsLocked","onFunnelBindingKeyChange","comparisonEnabledBreakdown","handleQueryTabClick","handleRemoveQuery","getQueryTabLabel","warning","AnalysisAIPanel","onPromptChange","isGenerating","hasGeneratedQuery","onGenerate","onAccept","AnalysisBuilderInner","_hideSettings","hideShare","useCubeMeta","AnalysisBuilder","innerProps","hasShareHash","PortletAnalysisModal","submitText","builderRef","formTitle","setFormTitle","handleSave","queryConfig","firstQuery","portletData","handleCancel","PortletFilterConfigModal","currentMapping","portletTitle","selectedFilters","setSelectedFilters","handleToggleFilter","formatFilterPreview","valuesText","filterCount","ConfirmModal","onConfirm","confirmText","cancelText","confirmVariant","baseClasses","EyeIcon","EyeOffIcon","DashboardFilterConfigModal","fullSchema","filteredSchema","onDelete","localLabel","setLocalLabel","localFilter","setLocalFilter","showAllFields","setShowAllFields","showFieldSearch","setShowFieldSearch","activeSchema","newFieldType","iconBgClass","iconTextClass","FilterEditModal","convertToMetaResponse","dashboardFields","filteredCubes","filteredMeasures","fullName","filteredDimensions","filteredCubeMeta","FilterIcon","ClockIcon","EditModeFilterList","onAddTimeFilter","onEditFilter","onRemoveFilter","onFilterSelect","isCollapsed","setIsCollapsed","renderFilterChip","dashboardFilter","isUniversalTime","DATE_PRESETS","XTD_OPTIONS","calculateDateRange","preset","endOfToday","yesterday","endOfYesterday","startOfWeek","dayOfWeek","diff","lastNMatch","startDate","lastUnitMatch","endOfLastWeek","startOfLastWeek","startOfLastMonth","endOfLastMonth","lastQuarterYear","startOfLastQuarter","endOfLastQuarter","startOfLastYear","endOfLastYear","formatDateRangeDisplay","startStr","endStr","startNoYear","detectPresetFromDateRange","normalizedRange","formatFilterValueDisplay","formattedValues","DatePresetChips","activePreset","onPresetSelect","presetTooltips","tooltips","range","LAST_UNITS","CustomDateDropdown","onDateRangeChange","currentDateRange","fixedStartDate","setFixedStartDate","fixedEndDate","setFixedEndDate","sinceDate","setSinceDate","lastNumber","setLastNumber","lastUnit","setLastUnit","handleEscape","timeoutId","handleApplyFixed","handleApplySince","handleApplyLast","tabButtonStyle","handleDropdownClick","XTDDropdown","currentXTD","dateRangeText","FilterValueSelector","onValuesChange","hasLoadedInitial","setHasLoadedInitial","lastSearchedTerm","isDimension","shouldFetchValues","handleDropdownToggle","newIsOpen","handleSearchChange","newSearchText","handleDateRangeEndInput","cubeMeta","FilterValuePopover","anchorRef","popoverRef","handleValuesChange","metaResponse","FilterChip","onEdit","showPopover","setShowPopover","chipRef","handleValueChange","handleChipClick","CalendarIcon","CompactFilterBar","onDashboardFiltersChange","showCustomDropdown","setShowCustomDropdown","showXTDDropdown","setShowXTDDropdown","customButtonRef","xtdButtonRef","universalTimeFilter","activePresetId","activeXTDId","nonDateFilters","generateFilterId","handleDateRangeChange","newDateRange","handlePresetSelect","presetValue","handleXTDSelect","xtdValue","handleCustomDateSelect","handleFilterChange","dateRangeTooltip","DashboardFilterPanel","onSaveFilters","editingFilter","setEditingFilter","showFilterBuilder","setShowFilterBuilder","handleAddFilter","handleAddTimeFilter","handleEditFilter","filterToEdit","handleSaveFilter","filterData","existingFilterIndex","handleCloseFilterBuilder","ScaledGridWrapper","scaleFactor","designWidth","actualHeight","setActualHeight","innerRef","visualHeight","findScrollableAncestor","style","overflowY","overflowX","hasScrollableOverflow","hasScrollContent","MobileStackedLayout","onPortletRefresh","portletComponentRefs","setScrollContainer","setContainerRef","sortedPortlets","handlePortletRefresh","ScrollContainerProvider","portletHeight","headerHeight","contentHeight","isIterable","hasIterableEntries","compareEntries","valueA","valueB","mapA","mapB","compareIterables","iteratorA","iteratorB","nextA","nextB","shallow","useShallow","createRowId","equalizeRowColumns","portletIds","cols","minW","minTotal","base","remainder","remaining","extra","adjustRowWidths","columns","adjusted","total","overflow","reducible","delta","convertPortletsToRows","rowsByY","rowY","rowPortlets","normalizeRows","col","convertRowsToPortlets","currentY","updated","currentX","updatedIds","selectStoreState","selectStoreActions","useDashboard","propAllowedModes","isResponsiveEditable","onConfigChange","storeState","storeActions","draftRowsRef","fallbackMode","configMode","selectedFilter","resolvedRows","baseRows","enterEditMode","exitEditMode","toggleEditMode","selectFilter","openAddPortlet","openEditPortlet","openFilterConfig","hasLayoutActuallyChanged","newLayout","newItem","oldItem","updateRowLayout","save","portletsOverride","normalizedRows","updatedPortlets","updatedConfig","handleLayoutModeChange","savePortlet","isNewPortlet","newPortletId","newPortlet","maxY","nextRows","executeDeletePortlet","deletePortlet","confirmDelete","duplicatePortlet","originalPortlet","duplicatedPortlet","refreshPortlet","portletComponent","toggleFilterForPortlet","hasFilter","selectAllForFilter","saveFilterConfig","handlePaletteChange","actions","ChartBarIcon","DeleteIcon","DesktopIcon","DEFAULT_GRID_SETTINGS","getGridSettings","DashboardGrid","dashboardModes","containerWidth","displayMode","useResponsiveDashboard","containerElementRef","scrollContainerRef","editBarRef","combinedContainerRef","foundScrollContainer","portletRefs","dragStateRef","dashboard","isPortletModalOpen","editingPortlet","isFilterConfigModalOpen","filterConfigPortlet","deleteConfirmPortletId","draftRows","isDraggingPortlet","isInitialized","initialLayout","handleLayoutChange","_layout","handleDragStop","_oldItem","_newItem","_placeholder","_e","_element","mutableLayout","layoutItem","handleResizeStop","startRowResize","startY","startRows","handleMouseMove","moveEvent","deltaUnits","handleMouseUp","finalRows","startColumnResize","startX","leftColumn","rightColumn","nextLeft","nextRight","rowItem","nextColumns","colIndex","handleRowDrop","insertIndex","dragState","sourceRowIndex","sourceRow","movedColumn","sourceRowRemoved","targetRowIndex","targetRow","handleNewRowDrop","newRow","handlePortletSave","scrollToPortlet","portletElement","handleDeletePortlet","handleDuplicatePortlet","handleAddPortlet","handleEditPortlet","handleOpenFilterConfig","handleSaveFilterConfig","handleSetPortletRef","handleSetPortletComponentRef","portletIcons","handleToggleFilterForPortlet","handleFilterSelect","handleSelectAllForFilter","portletCallbacks","renderPortletCard","baseLayout","renderActiveLayout","ReactGridLayout","verticalCompactor","AnalyticsDashboard","propDashboardFilters","onDirtyStateChange","handleConfigChangeWithDirtyTracking","handleSaveWithDirtyTracking","useDirtyStateTracking","mergedDashboardFilters","configFilters","propFilters","configFilter","propFilter","pf","configIds","cf","handleDashboardFiltersChange","PortletContainer","onRefresh","DashboardEditModal","initialName","initialDescription","setName","setDescription","isSaving","setIsSaving","handleSubmit","handleClose","QueryBuilderShim","analysisBuilderRef"],"mappings":"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,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IACA;AAAA,EACJ,GAEQC,IAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,GAGQC,IAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,GAKQC,IAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,GAGQC,IAA0B;AAAA,IAC9B;AAAA,IA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","x_google_ignoreList":[0,11,12,13,35,46,47,48,88,89]}
|